- Join EMPRESA table in all RDA queries to get CODCONTRATO (TNS contract code) - Use EMPRESA.CODCONTRATO as numeroContrato instead of raw NIT_EMPRESA - Especialidad always uses default_especialidad (ignore Firebird COD_ESPECIALIDAD) - sucursal defaults to '00' (not empty) in config and endpoints - Fix config template label: especialidad default is TNS code not Firebird code Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
204 lines
7.3 KiB
Python
204 lines
7.3 KiB
Python
import json as json_lib
|
|
import httpx
|
|
from datetime import datetime
|
|
from fastapi import APIRouter, Request, Form, Depends
|
|
from fastapi.responses import JSONResponse
|
|
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_rda_paciente, agrupar_por_recepcion
|
|
from app.services.api_client import get_tns_token, TNS_BASE
|
|
|
|
router = APIRouter(prefix="/transaccion", tags=["transaccion"])
|
|
|
|
|
|
@router.get("")
|
|
async def transaccion_page(request: Request, user: dict = Depends(get_current_user)):
|
|
conn = get_connection()
|
|
envios = conn.execute("""
|
|
SELECT * FROM envios WHERE tipo = 'transaccion'
|
|
ORDER BY created_at DESC LIMIT 20
|
|
""").fetchall()
|
|
queries = conn.execute(
|
|
"SELECT * FROM queries WHERE query_type = 'transaccion' ORDER BY name"
|
|
).fetchall()
|
|
configs = {row["key"]: row["value"] for row in conn.execute("SELECT * FROM config").fetchall()}
|
|
conn.close()
|
|
|
|
return request.app.state.templates.TemplateResponse("transaccion.html", {
|
|
"request": request, "user": user,
|
|
"envios": envios, "queries": queries,
|
|
"configs": configs,
|
|
})
|
|
|
|
|
|
@router.post("/preview")
|
|
async def preview_transaccion(
|
|
request: Request,
|
|
user: dict = Depends(get_current_user),
|
|
query_id: int = Form(...),
|
|
factura: str = Form(""),
|
|
fecha_inicio: str = Form(...),
|
|
fecha_fin: str = Form(...),
|
|
):
|
|
conn = get_connection()
|
|
q = conn.execute("SELECT * FROM queries WHERE id = ?", (query_id,)).fetchone()
|
|
configs = {row["key"]: row["value"] for row in conn.execute("SELECT * FROM config").fetchall()}
|
|
conn.close()
|
|
|
|
if not q:
|
|
return JSONResponse({"success": False, "message": "Consulta no encontrada"})
|
|
|
|
fb, ok, msg = get_firebird_from_config(configs)
|
|
if not ok:
|
|
return JSONResponse({"success": False, "message": f"Error Firebird: {msg}"})
|
|
|
|
if ":num_factura" in q["query_text"] and not factura:
|
|
fb.disconnect()
|
|
return JSONResponse({"success": False, "message": "Ingresa el número de factura"})
|
|
|
|
# Extraer solo la parte numérica: "LHXC 3918" o "LHXC-3918" → 3918
|
|
import re as _re
|
|
nums = _re.findall(r'\d+', factura)
|
|
num_factura_val = int(nums[-1]) if nums else factura
|
|
|
|
params = {
|
|
"fecha_ini": f"{fecha_inicio} 00:00:00",
|
|
"fecha_fin": f"{fecha_fin} 23:59:59",
|
|
}
|
|
if ":num_factura" in q["query_text"]:
|
|
params["num_factura"] = num_factura_val
|
|
|
|
success, error, rows = fb.execute_query(q["query_text"], params)
|
|
fb.disconnect()
|
|
|
|
if not success:
|
|
return JSONResponse({"success": False, "message": error})
|
|
|
|
grupos = agrupar_por_recepcion(rows)
|
|
prof_def = configs.get("profesional_default", "")
|
|
esp_def = configs.get("especialidad_default", "")
|
|
json_result = [generar_rda_paciente(grupo, prof_def, esp_def) for grupo in grupos.values()]
|
|
|
|
return JSONResponse({
|
|
"success": True,
|
|
"rows_count": len(rows),
|
|
"grupos_count": len(grupos),
|
|
"columns": list(rows[0].keys()) if rows else [],
|
|
"preview": rows[:5],
|
|
"generated_json": json_result[0] if json_result else None,
|
|
"total_json": len(json_result),
|
|
})
|
|
|
|
|
|
@router.post("/send")
|
|
async def send_transaccion(
|
|
request: Request,
|
|
user: dict = Depends(get_current_user),
|
|
query_id: int = Form(...),
|
|
factura: str = Form(""),
|
|
fecha_inicio: str = Form(...),
|
|
fecha_fin: str = Form(...),
|
|
):
|
|
conn = get_connection()
|
|
q = conn.execute("SELECT * FROM queries WHERE id = ?", (query_id,)).fetchone()
|
|
configs = {row["key"]: row["value"] for row in conn.execute("SELECT * FROM config").fetchall()}
|
|
conn.close()
|
|
|
|
if not q:
|
|
return JSONResponse({"success": False, "message": "Consulta no encontrada"})
|
|
|
|
fb, ok, msg = get_firebird_from_config(configs)
|
|
if not ok:
|
|
return JSONResponse({"success": False, "message": f"Error Firebird: {msg}"})
|
|
|
|
if ":num_factura" in q["query_text"] and not factura:
|
|
fb.disconnect()
|
|
return JSONResponse({"success": False, "message": "Ingresa el número de factura"})
|
|
|
|
# Extraer solo la parte numérica: "LHXC 3918" o "LHXC-3918" → 3918
|
|
import re as _re
|
|
nums = _re.findall(r'\d+', factura)
|
|
num_factura_val = int(nums[-1]) if nums else factura
|
|
|
|
params = {
|
|
"fecha_ini": f"{fecha_inicio} 00:00:00",
|
|
"fecha_fin": f"{fecha_fin} 23:59:59",
|
|
}
|
|
if ":num_factura" in q["query_text"]:
|
|
params["num_factura"] = num_factura_val
|
|
|
|
success, error, rows = fb.execute_query(q["query_text"], params)
|
|
fb.disconnect()
|
|
|
|
if not success:
|
|
return JSONResponse({"success": False, "message": error})
|
|
if not rows:
|
|
return JSONResponse({"success": False, "message": "No se encontraron datos"})
|
|
|
|
grupos = agrupar_por_recepcion(rows)
|
|
|
|
token, token_err = await get_tns_token(
|
|
configs.get("tns_empresa", ""),
|
|
configs.get("tns_usuario", ""),
|
|
configs.get("tns_password", ""),
|
|
)
|
|
if not token:
|
|
return JSONResponse({"success": False, "message": f"Error login TNS: {token_err}"})
|
|
|
|
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {token}"}
|
|
api_sucursal = configs.get("api_sucursal", "") or "00"
|
|
endpoint = f"{TNS_BASE}/v2/rda/RdaPaciente/Insertar?codigosucursal={api_sucursal}"
|
|
|
|
total_enviados = 0
|
|
total_errores = 0
|
|
resultados = []
|
|
prof_def = configs.get("profesional_default", "")
|
|
esp_def = configs.get("especialidad_default", "")
|
|
|
|
async with httpx.AsyncClient(timeout=int(configs.get("api_timeout", 30))) as client:
|
|
for id_recepcion, grupo_rows in grupos.items():
|
|
trans_json = generar_rda_paciente(grupo_rows, prof_def, esp_def)
|
|
|
|
status_ok = False
|
|
response_text = ""
|
|
try:
|
|
resp = await client.post(endpoint, json=trans_json, headers=headers)
|
|
status_ok = resp.is_success
|
|
response_text = resp.text[:1000]
|
|
except Exception as e:
|
|
response_text = str(e)
|
|
|
|
if status_ok:
|
|
total_enviados += 1
|
|
else:
|
|
total_errores += 1
|
|
|
|
fact = str(grupo_rows[0].get("NUM_FACTURA", id_recepcion))
|
|
resultados.append({"factura": fact, "success": status_ok, "msg": response_text})
|
|
|
|
conn = get_connection()
|
|
conn.execute("""
|
|
INSERT INTO envios (user_id, tipo, factura, fecha_inicio, fecha_fin,
|
|
pacientes_count, servicios_count, status, json_enviado, respuesta_api, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""", (
|
|
user["user_id"], "transaccion", fact,
|
|
fecha_inicio, fecha_fin,
|
|
1, len(grupo_rows),
|
|
"success" if status_ok else "error",
|
|
json_lib.dumps(trans_json, indent=2, ensure_ascii=False)[:5000],
|
|
response_text,
|
|
datetime.now().isoformat(),
|
|
))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
return JSONResponse({
|
|
"success": total_errores == 0,
|
|
"total_enviados": total_enviados,
|
|
"total_errores": total_errores,
|
|
"resultados": resultados,
|
|
"message": f"Enviados: {total_enviados}, Errores: {total_errores}",
|
|
})
|