import httpx import traceback as tb from fastapi import APIRouter, Request, Depends, Query from fastapi.responses import JSONResponse from app.auth import get_current_user from app.database import get_connection from app.services.scheduler import sync_recientes from app.services.firebird_service import get_firebird_from_config router = APIRouter(prefix="/envios", tags=["envios"]) @router.get("/tns") async def envios_tns(request: Request, user: dict = Depends(get_current_user)): return request.app.state.templates.TemplateResponse("envios_tns.html", { "request": request, "user": user, }) @router.get("/erp") async def envios_erp(request: Request, user: dict = Depends(get_current_user)): conn = get_connection() configs = {row["key"]: row["value"] for row in conn.execute("SELECT * FROM config").fetchall()} conn.close() wa_url = configs.get("whatsapp_url", "") wa_key = configs.get("whatsapp_api_key", "") return request.app.state.templates.TemplateResponse("envios_erp.html", { "request": request, "user": user, "wa_configurado": bool(wa_url and wa_key), "wa_url": wa_url, }) @router.post("/erp/sync-now") async def erp_sync_now( ventana_min: int = Query(default=30, ge=1, le=1440), user: dict = Depends(get_current_user), ): try: resultado = await sync_recientes(ventana_min=ventana_min) return JSONResponse(resultado) except Exception as e: return JSONResponse({"ok": False, "error": str(e), "traceback": tb.format_exc()}) @router.post("/erp/sync-diagnosticos") async def erp_sync_diagnosticos( user: dict = Depends(get_current_user), start_from: int = Query(default=0, ge=0, description="Índice desde el que reanudar"), ): """Migra los 12.422 diagnósticos CIE-10 de Firebird → WhatsApp en lotes de 200.""" try: conn = get_connection() configs = {row["key"]: row["value"] for row in conn.execute("SELECT * FROM config").fetchall()} conn.close() wa_url = configs.get("whatsapp_url", "").rstrip("/") wa_key = configs.get("whatsapp_api_key", "") if not wa_url or not wa_key: return JSONResponse({"ok": False, "error": "whatsapp_url o whatsapp_api_key no configurados"}) fb, ok, msg = get_firebird_from_config(configs) if not ok: return JSONResponse({"ok": False, "error": f"Firebird: {msg}"}) ok_r, err_r, rows = fb.execute_query( "SELECT TRIM(d.COD_DIAG) AS COD_DIAG, TRIM(d.CONCEPTO) AS CONCEPTO " "FROM DIAGNOSTICO d ORDER BY d.COD_DIAG", None ) fb.disconnect() if not ok_r: return JSONResponse({"ok": False, "error": f"Query Firebird: {err_r}"}) diagnosticos = [{"cod": r["COD_DIAG"], "concepto": r["CONCEPTO"]} for r in (rows or [])] total = len(diagnosticos) batch_size = 200 url = f"{wa_url}/api/lab/ingest_diagnosticos.php" headers = {"Content-Type": "application/json", "X-Lab-Key": wa_key} insertados = 0 errores = [] async with httpx.AsyncClient(timeout=60) as client: for i in range(start_from, total, batch_size): lote = diagnosticos[i:i + batch_size] try: resp = await client.post(url, json={"rows": lote}, headers=headers) try: data = resp.json() except Exception: raw = resp.text[:400].strip() errores.append(f"Lote {i}-{i+len(lote)} HTTP {resp.status_code}: {raw!r}") if i == 0: break # Si el primer lote ya falla, no tiene sentido continuar continue if data.get("ok"): insertados += data.get("insertados", len(lote)) else: errores.append(f"Lote {i}-{i+len(lote)}: {data.get('error', '?')}") if i == 0: break except Exception as ex: errores.append(f"Lote {i}-{i+len(lote)}: {ex}") if i == 0: break return JSONResponse({ "ok": len(errores) == 0, "total": total, "insertados": insertados, "lotes": (total + batch_size - 1) // batch_size, "errores": errores, }) except Exception as e: return JSONResponse({"ok": False, "error": str(e), "traceback": tb.format_exc()})