feat(pacientes): modo insertar en sync-all — solo crea nuevos, omite existentes
sync_todos() ahora acepta modo='insertar'|'upsert'. La ruta /pacientes/sync-all usa insertar: skippea cédulas que ya están en lab_pacientes. Los hooks automáticos (terceros/automation) siguen en upsert. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e7c6bc794a
commit
1aab14f705
@@ -117,12 +117,12 @@ async def sync_all(
|
||||
return JSONResponse({"success": False, "message": "No se encontraron pacientes con esos criterios."})
|
||||
|
||||
timeout = int(configs.get("api_timeout", 30))
|
||||
resultado = await sync_todos(rows, ingest_url, wa_key, timeout)
|
||||
resultado = await sync_todos(rows, ingest_url, wa_key, timeout, modo="insertar")
|
||||
resultado["success"] = True
|
||||
resultado["message"] = (
|
||||
f"{resultado['total']} pacientes procesados — "
|
||||
f"{resultado['created']} creados, "
|
||||
f"{resultado['updated']} actualizados, "
|
||||
f"{resultado['total']} procesados — "
|
||||
f"{resultado['created']} nuevos, "
|
||||
f"{resultado['skipped']} ya existían, "
|
||||
f"{resultado['errores']} errores."
|
||||
)
|
||||
return JSONResponse(resultado)
|
||||
|
||||
@@ -63,9 +63,16 @@ def mapear_paciente(row: dict) -> dict:
|
||||
}
|
||||
|
||||
|
||||
async def sync_paciente(row: dict, url: str, api_key: str, client: Optional[httpx.AsyncClient] = None) -> dict:
|
||||
async def sync_paciente(
|
||||
row: dict,
|
||||
url: str,
|
||||
api_key: str,
|
||||
client: Optional[httpx.AsyncClient] = None,
|
||||
modo: str = "upsert",
|
||||
) -> dict:
|
||||
"""Envía un paciente al endpoint de WhatsApp. Retorna {ok, action, message}."""
|
||||
payload = mapear_paciente(row)
|
||||
payload["modo"] = modo
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Lab-Key": api_key,
|
||||
@@ -95,17 +102,19 @@ async def sync_paciente(row: dict, url: str, api_key: str, client: Optional[http
|
||||
}
|
||||
|
||||
|
||||
async def sync_todos(rows: list, url: str, api_key: str, timeout: int = 30) -> dict:
|
||||
"""Envía una lista de filas de pacientes. Retorna resumen {total, created, updated, errores}."""
|
||||
resultado = {"total": len(rows), "created": 0, "updated": 0, "errores": 0, "detalle": []}
|
||||
headers = {"Content-Type": "application/json", "X-Lab-Key": api_key}
|
||||
async def sync_todos(rows: list, url: str, api_key: str, timeout: int = 30, modo: str = "upsert") -> dict:
|
||||
"""Envía una lista de filas de pacientes. Retorna resumen {total, created, skipped, updated, errores}."""
|
||||
resultado = {"total": len(rows), "created": 0, "skipped": 0, "updated": 0, "errores": 0, "detalle": []}
|
||||
|
||||
async with httpx.AsyncClient(timeout=timeout) as client:
|
||||
for row in rows:
|
||||
r = await sync_paciente(row, url, api_key, client)
|
||||
r = await sync_paciente(row, url, api_key, client, modo)
|
||||
if r["ok"]:
|
||||
if r["action"] == "created":
|
||||
action = r["action"]
|
||||
if action == "created":
|
||||
resultado["created"] += 1
|
||||
elif action == "skipped":
|
||||
resultado["skipped"] += 1
|
||||
else:
|
||||
resultado["updated"] += 1
|
||||
else:
|
||||
|
||||
@@ -135,7 +135,7 @@ async function runSync() {
|
||||
result.innerHTML = `
|
||||
<div class="bg-green-50 border border-green-200 rounded-lg p-4 space-y-3">
|
||||
<p class="font-medium text-green-800"><i class="fas fa-check-circle mr-2"></i>${json.message}</p>
|
||||
<div class="grid grid-cols-3 gap-3 text-center text-sm">
|
||||
<div class="grid grid-cols-4 gap-3 text-center text-sm">
|
||||
<div class="bg-white rounded-lg p-3 border border-green-100">
|
||||
<p class="text-2xl font-bold text-gray-800">${json.total}</p>
|
||||
<p class="text-gray-500">Total</p>
|
||||
@@ -145,8 +145,12 @@ async function runSync() {
|
||||
<p class="text-gray-500">Nuevos</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-3 border border-green-100">
|
||||
<p class="text-2xl font-bold text-green-600">${json.updated}</p>
|
||||
<p class="text-gray-500">Actualizados</p>
|
||||
<p class="text-2xl font-bold text-gray-400">${json.skipped ?? 0}</p>
|
||||
<p class="text-gray-500">Ya existían</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-3 border border-green-100">
|
||||
<p class="text-2xl font-bold text-red-500">${json.errores}</p>
|
||||
<p class="text-gray-500">Errores</p>
|
||||
</div>
|
||||
</div>
|
||||
${json.errores > 0 ? `<p class="text-sm text-red-600"><i class="fas fa-exclamation-triangle mr-1"></i>${json.errores} errores — revisa los detalles abajo.</p>` : ''}
|
||||
|
||||
Reference in New Issue
Block a user