fix: group ventas by NUM_FACTURA, not IDRECEPCION
A single CMXC invoice (e.g. CMXC-307) can have multiple receptions. Previously each reception was sent as a separate ventas, causing TNS to accept the first and reject the rest with "ya existe" — leaving only 1/N of the services registered. Now agrupar_por_factura groups all receptions sharing the same NUM_FACTURA into one ventas JSON with all their services in detallePedido. One factura = one send. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
531fb29122
commit
7f2dffc63e
@@ -11,6 +11,7 @@ from app.services.json_generator import (
|
||||
generar_tercero_api,
|
||||
generar_rda_paciente,
|
||||
agrupar_por_recepcion,
|
||||
agrupar_por_factura,
|
||||
generar_factura_venta,
|
||||
)
|
||||
from app.services.api_client import get_tns_token, TNS_BASE
|
||||
@@ -453,13 +454,13 @@ async def preview_automation(
|
||||
if rda_por_pac.get(str(p.get("CODIGO", "")))
|
||||
]
|
||||
|
||||
grupos_vta_all = agrupar_por_recepcion(rows_vta)
|
||||
grupos_vta_all = agrupar_por_factura(rows_vta)
|
||||
grupos_vta = {k: v for k, v in grupos_vta_all.items()
|
||||
if str(v[0].get("CODCONTRATO") or "").strip() not in excluded_ventas
|
||||
and int(v[0].get("NUM_FACTURA") or 0) != 0}
|
||||
|
||||
ventas_preview = []
|
||||
for id_rec, grupo_rows in grupos_vta.items():
|
||||
for num_fac_key, grupo_rows in grupos_vta.items():
|
||||
num_fac = str(grupo_rows[0].get("NUM_FACTURA") or "").strip()
|
||||
prefijo = str(grupo_rows[0].get("PREFIJO") or "").strip()
|
||||
venta_json = generar_factura_venta(grupo_rows, default_vendedor="00",
|
||||
@@ -732,7 +733,7 @@ async def run_automation(
|
||||
|
||||
# ── PASO 4: Enviar Facturas Venta ─────────────────────────────────────────
|
||||
excluded_ventas = load_excluded_ventas_set()
|
||||
grupos_vta_all = agrupar_por_recepcion(rows_vta)
|
||||
grupos_vta_all = agrupar_por_factura(rows_vta)
|
||||
grupos_vta = {k: v for k, v in grupos_vta_all.items()
|
||||
if str(v[0].get("CODCONTRATO") or "").strip() not in excluded_ventas
|
||||
and int(v[0].get("NUM_FACTURA") or 0) != 0}
|
||||
@@ -741,13 +742,14 @@ async def run_automation(
|
||||
endpoint_venta = f"{TNS_BASE}/v2/facturacion/Ventas/Crear?codigosucursal={api_sucursal or '00'}"
|
||||
if "ventas" in pasos_set:
|
||||
async with httpx.AsyncClient(timeout=timeout) as client:
|
||||
for id_rec, grupo_rows in grupos_vta.items():
|
||||
for num_fac_key, grupo_rows in grupos_vta.items():
|
||||
num_fac = str(grupo_rows[0].get("NUM_FACTURA") or "").strip()
|
||||
prefijo = str(grupo_rows[0].get("PREFIJO") or "").strip()
|
||||
venta_json = generar_factura_venta(grupo_rows, default_vendedor="00",
|
||||
default_prefijo=prefijo_def, numero_override=num_fac)
|
||||
factura_display = f"{prefijo}-{num_fac}"
|
||||
contrato_vta = str(grupo_rows[0].get("CODCONTRATO") or "").strip()
|
||||
id_rec_display = str(grupo_rows[0].get("IDRECEPCION") or "")
|
||||
try:
|
||||
resp = await client.post(endpoint_venta, json=venta_json, headers=headers)
|
||||
status, msg = _parse_tns_resp(resp)
|
||||
@@ -760,7 +762,7 @@ async def run_automation(
|
||||
resultado["paso4_ventas"]["enviados"] += 1
|
||||
|
||||
resultado["paso4_ventas"]["detalle"].append({
|
||||
"idrecepcion": id_rec,
|
||||
"idrecepcion": id_rec_display,
|
||||
"factura": factura_display,
|
||||
"paciente": str(grupo_rows[0].get("COD_PACIENTE", "")),
|
||||
"examenes": len(grupo_rows),
|
||||
@@ -769,7 +771,7 @@ async def run_automation(
|
||||
|
||||
_guardar_envio(user["user_id"], "ventas", factura_display, venta_json, msg, status,
|
||||
fecha_inicio=fecha, fecha_fin=fecha, servicios=len(grupo_rows),
|
||||
idrecepcion=id_rec, contrato=contrato_vta,
|
||||
idrecepcion=id_rec_display, contrato=contrato_vta,
|
||||
cedula=pac_map.get(str(grupo_rows[0].get("COD_PACIENTE", "")), ""))
|
||||
|
||||
r1 = resultado["paso1_terceros"]
|
||||
|
||||
@@ -125,6 +125,15 @@ def agrupar_por_recepcion(rows: list) -> dict:
|
||||
return grupos
|
||||
|
||||
|
||||
def agrupar_por_factura(rows: list) -> dict:
|
||||
"""Agrupa filas por NUM_FACTURA — para ventas CMXC donde una factura puede tener varias recepciones."""
|
||||
grupos = defaultdict(list)
|
||||
for row in rows:
|
||||
key = str(row.get("NUM_FACTURA") or "")
|
||||
grupos[key].append(dict(row))
|
||||
return grupos
|
||||
|
||||
|
||||
def generar_rda_paciente(rows: list, default_profesional: str = "", default_especialidad: str = "",
|
||||
default_remisionante: str = "00", default_prefijo: str = "00",
|
||||
numero_override: str = "", contrato_map: dict = None,
|
||||
|
||||
Reference in New Issue
Block a user