Files
rips_manager/app/routes/test_rda.py
T

274 lines
10 KiB
Python

import json as json_lib
from fastapi import APIRouter, Request, Depends
from fastapi.responses import JSONResponse
import httpx
from app.database import get_connection
from app.auth import get_current_user
from app.services.firebird_service import get_firebird_from_config
from app.services.json_generator import (
generar_tercero_api,
generar_rda_paciente,
agrupar_por_recepcion,
)
from app.services.api_client import get_tns_token, TNS_BASE
router = APIRouter(prefix="/test-rda", tags=["test-rda"])
_SQL_RDA_BY_WHERE = """
SELECT
r.IDRECEPCION, r.PREFIJO, r.NUM_FACTURA, r.FECHA_RECEPCION, r.COD_PACIENTE,
r.NIT_EMPRESA, r.DIAG_PPAL, r.TIPOUSU, r.TIPOUSUSISPRO, r.AUTORIZACION, r.CLASEPROC,
r.HORAINICIORECEPCION, r.VALORTOTAL, rel.COD_EXAMEN, rel.PRECIO, rel.FECHA_REPORTADO,
m.COD_ESPECIALIDAD,
COALESCE(NULLIF(TRIM(m.CODIGO), ''), NULLIF(TRIM(r.USUARIO), ''), '') AS profesional,
e.CODCONTRATO,
TRIM(m.DOCIDMEDICO) AS DOCIDMEDICO
FROM RECEPCION r
JOIN RELACION rel ON rel.IDRECEPCION = r.IDRECEPCION
LEFT JOIN MEDICO m ON m.CODIGO = r.COD_MEDICO
LEFT JOIN EMPRESA e ON e.NIT = r.NIT_EMPRESA
WHERE {where}
AND r.NUM_FACTURA > 0
AND e.CODCONTRATO IS NOT NULL
AND TRIM(e.CODCONTRATO) <> ''
ORDER BY r.IDRECEPCION
"""
_SQL_CANDIDATOS = """
SELECT FIRST 100
r.IDRECEPCION,
r.NUM_FACTURA,
r.FECHA_RECEPCION,
r.COD_PACIENTE,
r.NIT_EMPRESA,
e.CODCONTRATO,
LIST(DISTINCT rel.COD_EXAMEN, ', ') AS examenes,
COUNT(DISTINCT rel.COD_EXAMEN) AS total_examenes
FROM RECEPCION r
JOIN RELACION rel ON rel.IDRECEPCION = r.IDRECEPCION
LEFT JOIN EMPRESA e ON e.NIT = r.NIT_EMPRESA
WHERE r.NUM_FACTURA > 0
AND e.CODCONTRATO IS NOT NULL
AND TRIM(e.CODCONTRATO) <> ''
GROUP BY r.IDRECEPCION, r.NUM_FACTURA, r.FECHA_RECEPCION, r.COD_PACIENTE, r.NIT_EMPRESA, e.CODCONTRATO
ORDER BY r.IDRECEPCION DESC
"""
_SQL_PACIENTE = """
SELECT p.CODIGO, p.NOMBRES, p.APELLIDOS, p.DOCIDENT, p.TIPOIDENT,
p.F_NACIMIENTO, p.SEXO, p.DIRECCION, p.TELEFONOS, p.EMAIL
FROM PACIENTE p WHERE p.CODIGO = :cod
"""
@router.get("")
async def test_page(request: Request, user: dict = Depends(get_current_user)):
return request.app.state.templates.TemplateResponse(
"test_rda.html", {"request": request, "user": user}
)
@router.get("/candidatos")
async def get_candidatos(request: Request, user: dict = Depends(get_current_user),
contrato: str = "", factura: str = "", articulos: str = ""):
db = get_connection()
cfg = {r[0]: r[1] for r in db.execute("SELECT key, value FROM config").fetchall()}
db.close()
fb, fb_ok, fb_msg = get_firebird_from_config(cfg)
if not fb_ok:
return JSONResponse({"error": f"Error Firebird: {fb_msg}"})
# Artículos configurados con especialidad en TNS
arts_default = "CH4,CREA,TGP,VSG,PCR,AU,FER,TPO,TSH,TGO,GLI,BUN,COL,TRI,HDL,LDL,HBA1,VB12,VITD,PO,K,NA,MG,URO,PRL,T4L,T3,T4,T3L,HIV,VDRL,PSA,AFP,CEA,CA125,CA199,FV,TP,TPT"
arts_str = articulos.strip() if articulos.strip() else arts_default
arts_list = [a.strip().upper() for a in arts_str.split(",") if a.strip()]
arts_in = ", ".join(f"'{a}'" for a in arts_list)
filtros = [
"r.NUM_FACTURA > 0",
"e.CODCONTRATO IS NOT NULL",
"TRIM(e.CODCONTRATO) <> ''",
# Solo registros donde TODOS los exámenes están en el listado permitido
f"NOT EXISTS (SELECT 1 FROM RELACION rx WHERE rx.IDRECEPCION = r.IDRECEPCION AND rx.COD_EXAMEN NOT IN ({arts_in}))",
]
params = {}
if contrato:
filtros.append("e.CODCONTRATO = :contrato")
params["contrato"] = contrato
if factura:
filtros.append("r.NUM_FACTURA = :factura")
params["factura"] = int(factura)
sql_final = """
SELECT FIRST 10
r.IDRECEPCION, r.NUM_FACTURA, r.FECHA_RECEPCION, r.COD_PACIENTE, r.NIT_EMPRESA,
e.CODCONTRATO,
LIST(DISTINCT rel.COD_EXAMEN, ', ') AS EXAMENES,
COUNT(DISTINCT rel.COD_EXAMEN) AS TOTAL_EXAMENES
FROM RECEPCION r
JOIN RELACION rel ON rel.IDRECEPCION = r.IDRECEPCION
LEFT JOIN EMPRESA e ON e.NIT = r.NIT_EMPRESA
WHERE """ + " AND ".join(filtros) + """
GROUP BY r.IDRECEPCION, r.NUM_FACTURA, r.FECHA_RECEPCION, r.COD_PACIENTE, r.NIT_EMPRESA, e.CODCONTRATO
ORDER BY r.IDRECEPCION DESC
"""
ok2, err2, rows = fb.execute_query(sql_final, params)
fb.disconnect()
if not ok2:
return JSONResponse({"error": err2})
candidatos = []
for row in rows:
candidatos.append({
"idrecepcion": row.get("IDRECEPCION"),
"factura": row.get("NUM_FACTURA"),
"fecha": str(row.get("FECHA_RECEPCION", ""))[:10],
"paciente": row.get("COD_PACIENTE", ""),
"empresa": row.get("NIT_EMPRESA", ""),
"contrato": row.get("CODCONTRATO", ""),
"examenes": row.get("EXAMENES", ""),
"total": row.get("TOTAL_EXAMENES", 0),
})
return JSONResponse({"candidatos": candidatos})
@router.post("/enviar")
async def test_enviar(request: Request, user: dict = Depends(get_current_user)):
form = await request.form()
modo = form.get("modo", "idrecepcion")
valor = str(form.get("valor", "")).strip()
if not valor:
return JSONResponse({"error": "Ingresa un IDRECEPCION o número de factura"})
db = get_connection()
cfg = {r[0]: r[1] for r in db.execute("SELECT key, value FROM config").fetchall()}
db.close()
prof_def = cfg.get("profesional_default", "XIMENA")
esp_def = cfg.get("especialidad_default", "02")
remis_def = cfg.get("remisionante_default", "00")
prefijo_def = cfg.get("prefijo_tns_default", "00")
api_sucursal = cfg.get("api_sucursal", "00") or "00"
fb, fb_ok, fb_msg = get_firebird_from_config(cfg)
if not fb_ok:
return JSONResponse({"error": f"Error Firebird: {fb_msg}"})
if modo == "factura":
where = "r.NUM_FACTURA = :val"
params = {"val": int(valor)}
else:
where = "r.IDRECEPCION = :val"
params = {"val": int(valor)}
ok2, err2, rows_rda = fb.execute_query(
_SQL_RDA_BY_WHERE.format(where=where), params
)
if not ok2:
fb.disconnect()
return JSONResponse({"error": f"Error consulta: {err2}"})
if not rows_rda:
fb.disconnect()
return JSONResponse({"error": "Sin registros (¿NUM_FACTURA = 0 o contrato vacío?)"})
# Pacientes únicos
pacientes_unicos = {}
for row in rows_rda:
cod = str(row.get("COD_PACIENTE", "")).strip()
if cod and cod not in pacientes_unicos:
ok3, err3, prows = fb.execute_query(_SQL_PACIENTE, {"cod": cod})
if ok3 and prows:
pacientes_unicos[cod] = prows[0]
fb.disconnect()
token, err_tns = await get_tns_token(
cfg.get("tns_empresa", ""), cfg.get("tns_usuario", ""), cfg.get("tns_password", "")
)
if not token:
return JSONResponse({"error": f"Error login TNS: {err_tns}"})
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
endpoint_rda = f"{TNS_BASE}/v2/rda/RdaPaciente/Insertar?codigosucursal={api_sucursal}"
pasos = []
# Paso 1: crear terceros
async with httpx.AsyncClient(timeout=20) as client:
for cod, pac_row in pacientes_unicos.items():
tercero_json = generar_tercero_api(pac_row)
try:
r = await client.post(
f"{TNS_BASE}/v2/tablas/Tercero/Crear",
json=tercero_json, headers=headers,
)
try:
data = r.json()
msg = data.get("message") or r.text[:200]
except Exception:
msg = r.text[:200]
pasos.append({
"tipo": "tercero",
"codigo": cod,
"nombre": tercero_json.get("nombre", ""),
"status": r.status_code,
"ok": r.status_code in (200, 201),
"mensaje": msg,
})
except Exception as ex:
pasos.append({"tipo": "tercero", "codigo": cod, "ok": False, "mensaje": str(ex)})
# Paso 2: enviar RDA
grupos = agrupar_por_recepcion(rows_rda)
async with httpx.AsyncClient(timeout=30) as client:
for id_rec, grupo_rows in grupos.items():
rda_json = generar_rda_paciente(grupo_rows, prof_def, esp_def, remis_def, prefijo_def)
examenes = [r.get("COD_EXAMEN", "") for r in grupo_rows]
try:
r = await client.post(endpoint_rda, json=rda_json, headers=headers)
try:
data = r.json()
ok_rda = (data.get("status") or (data.get("data") or {}).get("success", False)) if isinstance(data, dict) else False
msg_rda = ((data.get("data") or {}).get("response") or data.get("message") or r.text[:200])
except Exception:
ok_rda = r.status_code < 300
msg_rda = r.text[:200]
pasos.append({
"tipo": "rda",
"idrecepcion": id_rec,
"factura": rda_json.get("numero", ""),
"paciente": rda_json.get("codTercero", ""),
"contrato": rda_json.get("numeroContrato", ""),
"examenes": examenes,
"status": r.status_code,
"ok": ok_rda,
"mensaje": msg_rda,
"json_enviado": rda_json,
})
except Exception as ex:
pasos.append({
"tipo": "rda", "idrecepcion": id_rec, "ok": False,
"examenes": examenes, "mensaje": str(ex), "json_enviado": {},
})
rda_ok = sum(1 for p in pasos if p["tipo"] == "rda" and p["ok"])
rda_err = sum(1 for p in pasos if p["tipo"] == "rda" and not p["ok"])
return JSONResponse({
"resumen": {
"total_recepciones": len(grupos),
"rda_exitosos": rda_ok,
"rda_errores": rda_err,
"pacientes_procesados": len(pacientes_unicos),
},
"pasos": pasos,
})