feat(contratos): tabla de contratos con tipo_usuario por contrato
Agrega tabla `contratos` en SQLite sembrada con los 17 contratos del laboratorio. `generar_rda_paciente` consulta el mapa contrato→tipoUsuario como primera prioridad antes de derivar de TIPOUSU/TIPOUSUSISPRO. Incluye CRUD en /contratos con UI en sidebar. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
7d2a9df447
commit
0f3a760de4
@@ -21,6 +21,19 @@ def _migrate(conn):
|
||||
conn.execute("ALTER TABLE envios ADD COLUMN contrato TEXT")
|
||||
if "mensaje_tns" not in cols:
|
||||
conn.execute("ALTER TABLE envios ADD COLUMN mensaje_tns TEXT")
|
||||
|
||||
tables = {r[0] for r in conn.execute("SELECT name FROM sqlite_master WHERE type='table'")}
|
||||
if "contratos" not in tables:
|
||||
conn.execute("""
|
||||
CREATE TABLE contratos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
numero_contrato TEXT UNIQUE NOT NULL,
|
||||
nit_empresa TEXT NOT NULL DEFAULT '',
|
||||
tipo_usuario TEXT NOT NULL,
|
||||
descripcion TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.commit()
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ from app.services.json_generator import (
|
||||
)
|
||||
from app.services.api_client import get_tns_token, TNS_BASE
|
||||
from app.services.whatsapp_sync import sync_paciente, sync_todos, guardar_sync_log
|
||||
from app.routes.contratos import load_contrato_map
|
||||
|
||||
router = APIRouter(prefix="/automation", tags=["automation"])
|
||||
|
||||
@@ -278,12 +279,13 @@ async def run_automation(
|
||||
esp_def = configs.get("especialidad_default", "")
|
||||
remis_def = configs.get("remisionante_default", "00")
|
||||
prefijo_def = configs.get("prefijo_tns_default", "00")
|
||||
contrato_map = load_contrato_map()
|
||||
|
||||
async with httpx.AsyncClient(timeout=timeout) as client:
|
||||
for id_recepcion, grupo_rows in grupos.items():
|
||||
num_fac = str(grupo_rows[0].get("NUM_FACTURA") or "").strip()
|
||||
num_override = num_fac
|
||||
rda_json = generar_rda_paciente(grupo_rows, prof_def, esp_def, remis_def, prefijo_def, num_override)
|
||||
rda_json = generar_rda_paciente(grupo_rows, prof_def, esp_def, remis_def, prefijo_def, num_override, contrato_map=contrato_map)
|
||||
factura = num_override or str(id_recepcion)
|
||||
try:
|
||||
resp = await client.post(endpoint, json=rda_json, headers=headers)
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
from fastapi import APIRouter, Request, Form, Depends
|
||||
from fastapi.responses import RedirectResponse, JSONResponse
|
||||
from app.database import get_connection
|
||||
from app.auth import get_current_user
|
||||
|
||||
router = APIRouter(prefix="/contratos", tags=["contratos"])
|
||||
|
||||
_SEED = [
|
||||
("001", "860078828", "11", "EPS SANITAS"),
|
||||
("002", "830054904", "11", "EPS COMPENSAR"),
|
||||
("003", "900278729", "12", "PARTICULAR"),
|
||||
("004", "800106339", "11", "EPS NUEVA EPS"),
|
||||
("005", "800153424", "11", "EPS SURA"),
|
||||
("006", "805009741", "11", "EPS COOMEVA"),
|
||||
("007", "860002183", "11", "EPS FAMISANAR"),
|
||||
("008", "860002503", "11", "EPS CRUZ BLANCA"),
|
||||
("009", "860027404", "11", "EPS COLSANITAS"),
|
||||
("010", "860039988", "11", "EPS SALUD TOTAL"),
|
||||
("011", "890903790", "11", "EPS SAVIA SALUD"),
|
||||
("012", "900178724", "11", "EPS MUTUAL SER"),
|
||||
("034", "860078828", "11", "EPS SANITAS (alt)"),
|
||||
("035", "860078828", "11", "EPS SANITAS (alt)"),
|
||||
("036", "860078828", "11", "EPS SANITAS (alt)"),
|
||||
("20062026", "800182856", "01", "SUBSIDIADO"),
|
||||
("CW225489", "899999068", "07", "POLIZA / SEGURO"),
|
||||
]
|
||||
|
||||
|
||||
def ensure_defaults():
|
||||
conn = get_connection()
|
||||
for nc, nit, tu, desc in _SEED:
|
||||
exists = conn.execute(
|
||||
"SELECT id FROM contratos WHERE numero_contrato = ?", (nc,)
|
||||
).fetchone()
|
||||
if not exists:
|
||||
conn.execute(
|
||||
"INSERT INTO contratos (numero_contrato, nit_empresa, tipo_usuario, descripcion) VALUES (?,?,?,?)",
|
||||
(nc, nit, tu, desc),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def load_contrato_map() -> dict:
|
||||
"""Devuelve {numero_contrato: tipo_usuario} incluyendo variante sin ceros a la izquierda."""
|
||||
conn = get_connection()
|
||||
rows = conn.execute("SELECT numero_contrato, tipo_usuario FROM contratos").fetchall()
|
||||
conn.close()
|
||||
result = {}
|
||||
for r in rows:
|
||||
nc = r["numero_contrato"].strip()
|
||||
tu = r["tipo_usuario"].strip()
|
||||
result[nc] = tu
|
||||
nc_s = nc.lstrip("0") or nc
|
||||
if nc_s != nc:
|
||||
result[nc_s] = tu
|
||||
return result
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def contratos_page(request: Request, user: dict = Depends(get_current_user)):
|
||||
conn = get_connection()
|
||||
rows = conn.execute("SELECT * FROM contratos ORDER BY numero_contrato").fetchall()
|
||||
conn.close()
|
||||
return request.app.state.templates.TemplateResponse("contratos.html", {
|
||||
"request": request, "user": user, "contratos": rows,
|
||||
})
|
||||
|
||||
|
||||
@router.post("/create")
|
||||
async def contrato_create(
|
||||
request: Request,
|
||||
user: dict = Depends(get_current_user),
|
||||
numero_contrato: str = Form(...),
|
||||
nit_empresa: str = Form(""),
|
||||
tipo_usuario: str = Form(...),
|
||||
descripcion: str = Form(""),
|
||||
):
|
||||
conn = get_connection()
|
||||
try:
|
||||
conn.execute(
|
||||
"INSERT INTO contratos (numero_contrato, nit_empresa, tipo_usuario, descripcion) VALUES (?,?,?,?)",
|
||||
(numero_contrato.strip(), nit_empresa.strip(), tipo_usuario.strip(), descripcion.strip()),
|
||||
)
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
conn.close()
|
||||
return RedirectResponse("/contratos", status_code=302)
|
||||
|
||||
|
||||
@router.post("/update/{contrato_id}")
|
||||
async def contrato_update(
|
||||
contrato_id: int,
|
||||
user: dict = Depends(get_current_user),
|
||||
numero_contrato: str = Form(...),
|
||||
nit_empresa: str = Form(""),
|
||||
tipo_usuario: str = Form(...),
|
||||
descripcion: str = Form(""),
|
||||
):
|
||||
conn = get_connection()
|
||||
conn.execute(
|
||||
"UPDATE contratos SET numero_contrato=?, nit_empresa=?, tipo_usuario=?, descripcion=? WHERE id=?",
|
||||
(numero_contrato.strip(), nit_empresa.strip(), tipo_usuario.strip(), descripcion.strip(), contrato_id),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return RedirectResponse("/contratos", status_code=302)
|
||||
|
||||
|
||||
@router.post("/delete/{contrato_id}")
|
||||
async def contrato_delete(contrato_id: int, user: dict = Depends(get_current_user)):
|
||||
conn = get_connection()
|
||||
conn.execute("DELETE FROM contratos WHERE id = ?", (contrato_id,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return RedirectResponse("/contratos", status_code=302)
|
||||
@@ -8,6 +8,7 @@ from app.auth import get_current_user
|
||||
from app.services.firebird_service import get_firebird_from_config
|
||||
from app.services.json_generator import generar_rda_paciente, agrupar_por_recepcion
|
||||
from app.services.api_client import get_tns_token, TNS_BASE
|
||||
from app.routes.contratos import load_contrato_map
|
||||
|
||||
router = APIRouter(prefix="/transaccion", tags=["transaccion"])
|
||||
|
||||
@@ -96,11 +97,12 @@ async def preview_transaccion(
|
||||
esp_def = cfg.get("especialidad_default", "")
|
||||
remis_def = cfg.get("remisionante_default", "00")
|
||||
prefijo_def = cfg.get("prefijo_tns_default", "00")
|
||||
contrato_map = load_contrato_map()
|
||||
|
||||
items = []
|
||||
for id_rec, grupo_rows in grupos.items():
|
||||
enviado = _is_sent(id_rec)
|
||||
rda = generar_rda_paciente(grupo_rows, prof_def, esp_def, remis_def, prefijo_def)
|
||||
rda = generar_rda_paciente(grupo_rows, prof_def, esp_def, remis_def, prefijo_def, contrato_map=contrato_map)
|
||||
items.append({
|
||||
"idrecepcion": id_rec,
|
||||
"factura": grupo_rows[0].get("NUM_FACTURA", ""),
|
||||
@@ -166,6 +168,7 @@ async def send_one(
|
||||
cfg.get("remisionante_default", "00"),
|
||||
cfg.get("prefijo_tns_default", "00"),
|
||||
numero_override_one,
|
||||
contrato_map=load_contrato_map(),
|
||||
)
|
||||
|
||||
raw_resp = ""
|
||||
@@ -234,6 +237,8 @@ async def send_transaccion(
|
||||
if solo_pendientes == "1":
|
||||
grupos = {k: v for k, v in grupos.items() if not _is_sent(k)}
|
||||
|
||||
contrato_map = load_contrato_map()
|
||||
|
||||
token, token_err = await get_tns_token(
|
||||
cfg.get("tns_empresa", ""), cfg.get("tns_usuario", ""), cfg.get("tns_password", "")
|
||||
)
|
||||
@@ -256,6 +261,7 @@ async def send_transaccion(
|
||||
cfg.get("remisionante_default", "00"),
|
||||
cfg.get("prefijo_tns_default", "00"),
|
||||
numero_override,
|
||||
contrato_map=contrato_map,
|
||||
)
|
||||
raw_resp = ""
|
||||
ok_rda = False
|
||||
|
||||
@@ -134,7 +134,7 @@ def _calcular_descuento_pct(rows: list) -> int:
|
||||
|
||||
def generar_rda_paciente(rows: list, default_profesional: str = "", default_especialidad: str = "",
|
||||
default_remisionante: str = "00", default_prefijo: str = "00",
|
||||
numero_override: str = "") -> dict:
|
||||
numero_override: str = "", contrato_map: dict = None) -> dict:
|
||||
if not rows:
|
||||
return {}
|
||||
h = rows[0]
|
||||
@@ -191,15 +191,20 @@ def generar_rda_paciente(rows: list, default_profesional: str = "", default_espe
|
||||
cod_forma_pago = "CLIP" if es_particular else "INST"
|
||||
autorizacion = None if es_particular else (str(h.get("AUTORIZACION") or "").strip() or None)
|
||||
|
||||
# tipousuario: particular siempre "12"; para convenios usar TIPOUSUSISPRO o derivar
|
||||
# tipousuario: prioridad 1→tabla contratos, 2→particular, 3→TIPOUSUSISPRO/TIPOUSU
|
||||
_TIPOUSU_MAP = {"1": "11", "5": "07"} # EPS→11, Póliza→07
|
||||
if es_particular:
|
||||
tipoususispro = "12"
|
||||
else:
|
||||
tipoususispro = str(h.get("TIPOUSUSISPRO") or "").strip()
|
||||
if not tipoususispro:
|
||||
tipousu = str(h.get("TIPOUSU") or "").strip()
|
||||
tipoususispro = _TIPOUSU_MAP.get(tipousu, "11")
|
||||
tipoususispro = ""
|
||||
if contrato_map and cod_contrato_raw:
|
||||
_nc_s = cod_contrato_raw.lstrip("0") or cod_contrato_raw
|
||||
tipoususispro = contrato_map.get(cod_contrato_raw) or contrato_map.get(_nc_s) or ""
|
||||
if not tipoususispro:
|
||||
if es_particular:
|
||||
tipoususispro = "12"
|
||||
else:
|
||||
tipoususispro = str(h.get("TIPOUSUSISPRO") or "").strip()
|
||||
if not tipoususispro:
|
||||
tipousu = str(h.get("TIPOUSU") or "").strip()
|
||||
tipoususispro = _TIPOUSU_MAP.get(tipousu, "11")
|
||||
|
||||
via_ingreso = "01"
|
||||
modalidad = "01"
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
<a href="/queries" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/queries' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">␍
|
||||
<i class="fas fa-database w-5 mr-2"></i> Consultas SQL␍
|
||||
</a>␍
|
||||
<a href="/contratos" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/contratos' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">␍
|
||||
<i class="fas fa-file-contract w-5 mr-2"></i> Contratos␍
|
||||
</a>␍
|
||||
<hr class="my-3 border-gray-700">␍
|
||||
<p class="px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">Envíos</p>␍
|
||||
<a href="/terceros" class="flex items-center px-3 py-2.5 rounded-lg text-sm font-medium {% if request.url.path == '/terceros' %}bg-blue-600 text-white{% else %}text-gray-300 hover:bg-gray-700{% endif %}">␍
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Contratos{% endblock %}
|
||||
{% block header %}Contratos{% endblock %}
|
||||
{% block content %}
|
||||
<div class="max-w-4xl space-y-6">
|
||||
|
||||
<!-- Agregar contrato -->
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
|
||||
<div class="px-6 py-4 border-b border-gray-200">
|
||||
<h3 class="font-semibold text-gray-800"><i class="fas fa-plus-circle mr-2 text-blue-500"></i>Agregar Contrato</h3>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<form method="POST" action="/contratos/create" class="grid grid-cols-4 gap-3 items-end">
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">N° Contrato</label>
|
||||
<input type="text" name="numero_contrato" required placeholder="Ej: 001"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">NIT Empresa</label>
|
||||
<input type="text" name="nit_empresa" placeholder="Ej: 860078828"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">Tipo Usuario</label>
|
||||
<select name="tipo_usuario" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
<option value="11">11 — Contributivo (EPS)</option>
|
||||
<option value="12">12 — Particular</option>
|
||||
<option value="07">07 — Póliza / Seguro</option>
|
||||
<option value="01">01 — Subsidiado</option>
|
||||
<option value="10">10 — No Afiliado</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">Descripción</label>
|
||||
<input type="text" name="descripcion" placeholder="Ej: EPS SANITAS"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
<div class="col-span-4 flex justify-end">
|
||||
<button type="submit"
|
||||
class="px-5 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition-colors">
|
||||
<i class="fas fa-plus mr-1"></i> Agregar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabla de contratos -->
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
|
||||
<div class="px-6 py-4 border-b border-gray-200 flex items-center justify-between">
|
||||
<h3 class="font-semibold text-gray-800">
|
||||
<i class="fas fa-list mr-2 text-gray-500"></i>Contratos registrados
|
||||
<span class="ml-2 text-xs bg-gray-100 text-gray-600 px-2 py-0.5 rounded-full">{{ contratos|length }}</span>
|
||||
</h3>
|
||||
<span class="text-xs text-gray-400">El tipo de usuario se aplica automáticamente al generar RIPS por contrato</span>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead class="bg-gray-50 border-b border-gray-200">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">N° Contrato</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">NIT Empresa</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">Tipo Usuario</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">Descripción</th>
|
||||
<th class="px-4 py-3 text-center text-xs font-semibold text-gray-500 uppercase">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
{% for c in contratos %}
|
||||
<tr class="hover:bg-gray-50" id="row-{{ c.id }}">
|
||||
<td class="px-4 py-3 font-mono font-semibold text-gray-800">{{ c.numero_contrato }}</td>
|
||||
<td class="px-4 py-3 text-gray-600">{{ c.nit_empresa }}</td>
|
||||
<td class="px-4 py-3">
|
||||
{% set tu = c.tipo_usuario %}
|
||||
{% if tu == '11' %}
|
||||
<span class="px-2 py-0.5 bg-blue-100 text-blue-700 rounded-full text-xs font-medium">11 — Contributivo</span>
|
||||
{% elif tu == '12' %}
|
||||
<span class="px-2 py-0.5 bg-gray-100 text-gray-700 rounded-full text-xs font-medium">12 — Particular</span>
|
||||
{% elif tu == '07' %}
|
||||
<span class="px-2 py-0.5 bg-purple-100 text-purple-700 rounded-full text-xs font-medium">07 — Póliza</span>
|
||||
{% elif tu == '01' %}
|
||||
<span class="px-2 py-0.5 bg-green-100 text-green-700 rounded-full text-xs font-medium">01 — Subsidiado</span>
|
||||
{% else %}
|
||||
<span class="px-2 py-0.5 bg-yellow-100 text-yellow-700 rounded-full text-xs font-medium">{{ tu }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-gray-500">{{ c.descripcion }}</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<button onclick="openEdit({{ c.id }}, '{{ c.numero_contrato }}', '{{ c.nit_empresa }}', '{{ c.tipo_usuario }}', '{{ c.descripcion }}')"
|
||||
class="text-blue-600 hover:text-blue-800 mr-3 text-xs">
|
||||
<i class="fas fa-edit"></i> Editar
|
||||
</button>
|
||||
<form method="POST" action="/contratos/delete/{{ c.id }}" class="inline"
|
||||
onsubmit="return confirm('¿Eliminar contrato {{ c.numero_contrato }}?')">
|
||||
<button type="submit" class="text-red-500 hover:text-red-700 text-xs">
|
||||
<i class="fas fa-trash"></i> Eliminar
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="px-4 py-8 text-center text-gray-400">No hay contratos registrados</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal editar -->
|
||||
<div id="edit-modal" class="hidden fixed inset-0 bg-black/40 z-50 flex items-center justify-center">
|
||||
<div class="bg-white rounded-xl shadow-xl w-full max-w-lg p-6">
|
||||
<h3 class="font-semibold text-gray-800 mb-4"><i class="fas fa-edit mr-2 text-blue-500"></i>Editar Contrato</h3>
|
||||
<form method="POST" id="edit-form" class="space-y-4">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">N° Contrato</label>
|
||||
<input type="text" name="numero_contrato" id="edit-nc" required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">NIT Empresa</label>
|
||||
<input type="text" name="nit_empresa" id="edit-nit"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">Tipo Usuario</label>
|
||||
<select name="tipo_usuario" id="edit-tu"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
<option value="11">11 — Contributivo (EPS)</option>
|
||||
<option value="12">12 — Particular</option>
|
||||
<option value="07">07 — Póliza / Seguro</option>
|
||||
<option value="01">01 — Subsidiado</option>
|
||||
<option value="10">10 — No Afiliado</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">Descripción</label>
|
||||
<input type="text" name="descripcion" id="edit-desc"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end space-x-3 pt-2">
|
||||
<button type="button" onclick="closeEdit()"
|
||||
class="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 border border-gray-300 rounded-lg">
|
||||
Cancelar
|
||||
</button>
|
||||
<button type="submit"
|
||||
class="px-5 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition-colors">
|
||||
<i class="fas fa-save mr-1"></i> Guardar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openEdit(id, nc, nit, tu, desc) {
|
||||
document.getElementById('edit-form').action = '/contratos/update/' + id;
|
||||
document.getElementById('edit-nc').value = nc;
|
||||
document.getElementById('edit-nit').value = nit;
|
||||
document.getElementById('edit-tu').value = tu;
|
||||
document.getElementById('edit-desc').value = desc;
|
||||
document.getElementById('edit-modal').classList.remove('hidden');
|
||||
}
|
||||
function closeEdit() {
|
||||
document.getElementById('edit-modal').classList.add('hidden');
|
||||
}
|
||||
document.getElementById('edit-modal').addEventListener('click', function(e) {
|
||||
if (e.target === this) closeEdit();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -56,8 +56,10 @@ async def startup():
|
||||
init_db()
|
||||
from app.routes.config import ensure_defaults as config_defaults
|
||||
from app.routes.queries import ensure_defaults as query_defaults
|
||||
from app.routes.contratos import ensure_defaults as contratos_defaults
|
||||
config_defaults()
|
||||
query_defaults()
|
||||
contratos_defaults()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@@ -65,7 +67,7 @@ async def root():
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
|
||||
from app.routes import auth, dashboard, config, queries, terceros, transaccion, logs, automation, test_rda, debug_fb, pacientes
|
||||
from app.routes import auth, dashboard, config, queries, terceros, transaccion, logs, automation, test_rda, debug_fb, pacientes, contratos
|
||||
|
||||
app.include_router(auth.router)
|
||||
app.include_router(dashboard.router)
|
||||
@@ -78,6 +80,7 @@ app.include_router(automation.router)
|
||||
app.include_router(test_rda.router)
|
||||
app.include_router(debug_fb.router)
|
||||
app.include_router(pacientes.router)
|
||||
app.include_router(contratos.router)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user