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}", })