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:
Lizandro Guarnizo
2026-07-09 15:00:21 -05:00
co-authored by Claude Sonnet 4.6
parent 7d2a9df447
commit 0f3a760de4
8 changed files with 337 additions and 12 deletions
+3 -1
View File
@@ -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)
+117
View File
@@ -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)
+7 -1
View File
@@ -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