Pipeline de inserción
El endpoint insertar facturas procesa cada batch en
un orden estricto de prioridad. Cada paso es un filtro: si falla, detiene el proceso y
devuelve un 422. Conocer este orden te permite diagnosticar exactamente por qué se
rechazó un batch y en qué etapa.
Diagrama del flujo
Sección titulada «Diagrama del flujo»flowchart TD
Start([POST /facturas/insertar]) --> Auth{ApiKey válido?}
Auth -- no --> E401([401])
Auth -- sí --> P1{1· body es array no vacío?}
P1 -- no --> E1([422 body inválido])
P1 -- sí --> P2{2· campos obligatorios?}
P2 -- no --> E2([422 errores·])
P2 -- sí --> P3{3· fechas V1/V2/V3?}
P3 -- no --> E3([422 FECHAS_INVALIDAS<br/>TODO el batch])
P3 -- sí --> P4{4· manifiestos hoy/nuevos?}
P4 -- no --> E4([422 MANIFIESTOS_FECHA_INVALIDA<br/>TODO el batch])
P4 -- sí --> P5{5· batch duplicado hoy?}
P5 -- sí --> D([200 resumen original])
P5 -- no --> P6[6· persistir payload crudo]
P6 --> P7[7· procesar por manifiesto]
P7 --> P8{rechazos por manifiesto?}
P8 -- sí --> R([422 + inserta los válidos])
P8 -- no --> OK([200 éxito])
style E3 fill:#fde3e3,stroke:#c0392b,color:#7a271a
style E4 fill:#fde3e3,stroke:#c0392b,color:#7a271a
style OK fill:#dcf3e3,stroke:#1f8a4c,color:#14532d
style D fill:#dcf3e3,stroke:#1f8a4c,color:#14532d
Los pasos en detalle
Sección titulada «Los pasos en detalle»-
Parsear el body
Sección titulada «Parsear el body»El cuerpo debe ser un array JSON no vacío. Si llega vacío, nulo o con otro tipo, se responde
422con “El body debe ser un array JSON de facturas no vacío.” -
Validar estructura
Sección titulada «Validar estructura»Se revisa que cada factura traiga sus campos obligatorios y que cada línea traiga los suyos. Cualquier falta acumula un error en
errores[]y se responde422. ElTotaldebe ser numérico y ≥ 0;LineasFacturano puede estar vacío. -
Validar fechas (por factura)
Sección titulada «Validar fechas (por factura)»Es la línea de defensa más temprana contra data corrupta: ocurre antes de tocar la base de datos. Revisa cada factura del manifiesto: ninguna puede ser futura ni tener más de 30 días de antigüedad (ver reglas de fecha). La mezcla de fechas dentro de un manifiesto está permitida. Si una sola factura falla, se rechaza ese manifiesto completo con
motivo: FECHAS_INVALIDAS. La respuesta traemanifiestos_validos[]ymanifiestos_rechazados[]con el detalle. El rechazo queda en el log; la notificación in-app a admins es opcional (off por defecto). -
Validar manifiestos existentes
Sección titulada «Validar manifiestos existentes»Si intentas agregar facturas a un manifiesto que ya existe y fue creado antes de hoy, se rechaza todo el batch con
motivo: MANIFIESTOS_FECHA_INVALIDA. La respuesta traemanifiestos_no_afectados[]con los manifiestos válidos a reenviar por separado. -
Detectar batch duplicado
Sección titulada «Detectar batch duplicado»Se calcula un hash del contenido. Si un batch idéntico ya se procesó hoy (y no falló), no se reprocesa: se responde
200con el resumen del proceso original. Esto hace seguro reintentar ante un timeout. -
Persistir el payload crudo
Sección titulada «Persistir el payload crudo»El lote recibido se guarda tal cual, con un
batch_uuid. Esto da trazabilidad completa: ante cualquier duda, Hosana puede revisar exactamente qué se recibió. -
Procesar el batch (por manifiesto)
Sección titulada «Procesar el batch (por manifiesto)»Aquí se procesa manifiesto por manifiesto, en este orden:
- Validar almacenes —
Almaceninexistente →ALMACENES_DESCONOCIDOS. - Manifiesto cerrado →
MANIFIESTO_CERRADO. - Facturas duplicadas en otro manifiesto →
FACTURAS_DUPLICADAS_EN_OTRO_MANIFIESTO. - Crear el manifiesto si no existe (fecha operativa derivada de
FechaFactura). - Clasificar facturas: nuevas (se insertan), idénticas (sin cambios), o con diferencias (conflicto pendiente de revisión).
- Insertar las nuevas en bloque y recalcular los totales del manifiesto.
Un rechazo aquí es por manifiesto: las facturas de los manifiestos válidos del mismo batch sí entran.
- Validar almacenes —
-
Construir la respuesta
Sección titulada «Construir la respuesta»Se arma el
resumencon los conteos y, si hubo rechazos, el arreglomanifiestos_rechazados[]. El código HTTP es200si no hubo ningún rechazo, o422si hubo al menos un manifiesto rechazado.
Una distinción que conviene tener clara: los pasos 3 y 4 son todo o nada sobre el batch
completo, mientras que el paso 7 actúa por manifiesto. Cuando ves insertadas: 0 junto
a un motivo de fecha, el rechazo fue temprano; cuando ves algunas insertadas y otras
rechazadas, ocurrió durante el procesamiento.