fase 1: registro de comprobantes con código de seguimiento
Nueva tabla comprobantes (creada en init_db) y módulo seguimiento.py: cada comprobante recibe un código ABR-AAMMDD-NNNNN que conserva si reaparece en otro correo, más su resultado (aceptado/rechazado/error) y el estado de la notificación. El pipeline lo registra por factura sin bloquear el flujo si el seguimiento falla. Las pruebas usan una BD temporal para no tocar emails.db. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9d295d6485
commit
297cfde0e1
9 files changed
+563
-6
No files matched your search
+39
@@ -21,11 +21,46 @@ import persistencia
|
||||
import draft_sap
|
||||
import notificaciones
|
||||
import sapb1_manager
|
||||
import seguimiento
|
||||
from pipeline_utils import log
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# SEGUIMIENTO (códigos y resultado por comprobante)
|
||||
# ============================================================================
|
||||
def _registrar_comprobante(email: dict, factura: dict) -> dict | None:
|
||||
"""
|
||||
Registra la factura en ``seguimiento`` y devuelve su registro (con el código
|
||||
de seguimiento), o None si falla: el seguimiento nunca debe impedir
|
||||
procesar la factura.
|
||||
"""
|
||||
try:
|
||||
registro = seguimiento.registrar_comprobante(
|
||||
email["id"], factura.get("ruc_emisor") or "", factura.get("tipo", "01"),
|
||||
factura.get("serie", ""), factura.get("numero", ""),
|
||||
)
|
||||
except Exception as ex:
|
||||
log(f"⚠️ No se pudo registrar el comprobante en seguimiento: {ex}", severity=logging.WARNING)
|
||||
return None
|
||||
|
||||
log(f"🔖 Código de seguimiento: {registro['codigo_seguimiento']}")
|
||||
if registro["reenvio"]:
|
||||
log(f"⚠️ Comprobante ya recibido antes ({registro['veces_recibido']} veces, estado: {registro['estado']})", severity=logging.WARNING)
|
||||
return registro
|
||||
|
||||
|
||||
def _registrar_resultado(registro: dict | None, estado: str, **kwargs) -> None:
|
||||
"""Guarda el resultado del comprobante; si falla, solo lo registra en el log."""
|
||||
if not registro:
|
||||
return
|
||||
try:
|
||||
seguimiento.actualizar_resultado(registro["codigo_seguimiento"], estado, **kwargs)
|
||||
except Exception as ex:
|
||||
log(f"⚠️ No se pudo guardar el resultado en seguimiento: {ex}", severity=logging.WARNING)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# PASO 1: Autenticación Microsoft Graph
|
||||
# ============================================================================
|
||||
@@ -153,6 +188,7 @@ def _procesar_un_correo(email: dict, token: str, email_addr: str, download_folde
|
||||
numero = factura.get("numero", "?")
|
||||
|
||||
log(f"📄 Factura: {serie}-{numero}")
|
||||
registro = _registrar_comprobante(email, factura)
|
||||
|
||||
# 12. Validar precios (consulta SAP DNs, NO requiere draft)
|
||||
todas_coinciden, resultados_val = draft_sap.validate_prices(factura)
|
||||
@@ -179,12 +215,15 @@ def _procesar_un_correo(email: dict, token: str, email_addr: str, download_folde
|
||||
sap_result = sapb1_manager.create_draft(draft)
|
||||
doc_entry = sap_result.get("DocEntry")
|
||||
log(f"✅ Draft SAP B1 creado: {serie}-{numero} → DocEntry {doc_entry}")
|
||||
_registrar_resultado(registro, "aceptado", doc_entry=doc_entry)
|
||||
html_body = notificaciones.build_notification_body("created", factura, validation_table, valor_referencial_table, doc_entry=doc_entry)
|
||||
except Exception as ex:
|
||||
log(f"❌ Error creando draft {serie}-{numero}: {ex}", severity=logging.ERROR)
|
||||
_registrar_resultado(registro, "error", observaciones=[{"codigo": "error_sap", "detalle": str(ex)}])
|
||||
html_body = notificaciones.build_notification_body("error", factura, validation_table, valor_referencial_table, error=ex)
|
||||
else:
|
||||
log(f"⏭️ Draft NO creado: {serie}-{numero} — validación falló")
|
||||
_registrar_resultado(registro, "rechazado", observaciones=[{"codigo": "precios_no_coinciden"}])
|
||||
html_body = notificaciones.build_notification_body("skipped", factura, validation_table, valor_referencial_table)
|
||||
|
||||
# 16. Enviar notificación al remitente original, con copia al equipo
|
||||
|
||||
Reference in new issue
Block a user