se agrega fallback OWTR y calculo de fecha de vencimiento por condicion de pago
- hana_manager.get_delivery ahora busca en ODLN y, si no encuentra, en OWTR - sapb1_manager resuelve StockTransfers -> Orders (via U_IDC_NUMOV) para validar precios de flete cuando la guia es un traslado de inventario - se corrige el orden de parametros tipo/serie/numero (sin cruces) en get_delivery, get_delivery_notes y _get_delivery_entries - se agrega sapb1_manager.obtener_condicion_pago (BusinessPartners + PaymentTermsTypes) y pipeline._calcular_fecha_vencimiento para que DocDueDate del draft sea fecha de contabilizacion + dias de la condicion de pago del proveedor - se agrega variante de regex para "VALOR REFER" truncado en sunat_schema.py - se actualiza documentacion (docs/) reflejando estos cambios Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6b0ed6f519
commit
15e3b5079c
231 files changed
+21421
-475
No files matched your search
+86
-28
@@ -4,11 +4,11 @@
|
||||
|
||||
```
|
||||
pipeline.py
|
||||
├── CONSTANTES: CUADRO_VALOR_REFERENCIAL
|
||||
├── HELPERS: _ruta_carpeta()
|
||||
├── CONFIG: RUTA_RED_FACTURACION, RUC_EMPRESA (desde .env)
|
||||
├── HELPERS: _ruta_carpeta(), _copiar_a_red(data, _log)
|
||||
├── PASO 1: step_authenticate() → token | None
|
||||
├── PASO 2: step_fetch_emails() → list[dict]
|
||||
├── _procesar_un_correo() → None (core)
|
||||
├── _procesar_un_correo() → None (core, funciones anidadas)
|
||||
└── run_pipeline() → None
|
||||
```
|
||||
|
||||
@@ -51,44 +51,75 @@ flowchart TD
|
||||
I -- No --> C
|
||||
I -- Sí --> J[6. _procesar_pdfs]:::highlight
|
||||
J --> K[7. _procesar_xmls]:::highlight
|
||||
K --> L{Hay documentos?}
|
||||
K --> K2[8. _completar_guias]
|
||||
K2 --> K3[9. _validar_guias]
|
||||
K3 --> L{Hay documentos?}
|
||||
L -- No --> C
|
||||
L -- Sí --> M[8. _guardar_resultado]
|
||||
M --> N[9. Filtrar facturas tipo 01]
|
||||
L -- Sí --> M[10. _guardar_resultado]
|
||||
M --> N[11. Filtrar facturas tipo 01]
|
||||
N --> O{Hay facturas?}
|
||||
O -- No --> C
|
||||
O -- Sí --> P[Bucle: por cada factura]
|
||||
|
||||
P --> Q[10. _validate_prices]:::highlight
|
||||
Q --> R[11. _build_sap_draft]:::highlight
|
||||
R --> S[12. _guardar_draft_json]
|
||||
P --> Q[12. _validate_prices]:::highlight
|
||||
Q --> Q2[12.5 _obtener_valor_referencial_sap]
|
||||
Q2 --> R[13. _build_sap_draft]:::highlight
|
||||
R --> S[14. _guardar_draft_json]
|
||||
S --> T{Todas coinciden?}
|
||||
T -- Sí --> U[13. sapb1_manager.create_draft]
|
||||
T -- Sí --> U[15. sapb1_manager.create_draft]
|
||||
T -- No --> V[⏭️ Draft NO creado]
|
||||
U --> W[14. outlook_utilities.send_email]
|
||||
U --> W[16. outlook_utilities.send_email]
|
||||
V --> W
|
||||
W --> P
|
||||
|
||||
classDef highlight fill:#fff3e0,stroke:#e65100,stroke-width:3px;
|
||||
```
|
||||
|
||||
`_procesar_xmls` (paso 7) incluye internamente la copia de PDF/XML a la ruta de red (`_copiar_a_red`, ver más abajo) por cada comprobante procesado.
|
||||
|
||||
---
|
||||
|
||||
## Funciones internas de `_procesar_un_correo`
|
||||
|
||||
> `_ruta_carpeta` y `_copiar_a_red` están definidas a nivel de módulo (no anidadas); el resto son funciones anidadas dentro de `_procesar_un_correo`.
|
||||
|
||||
| Función | Línea | Propósito |
|
||||
|---------|-------|-----------|
|
||||
| `_descargar_adjuntos()` | 107 | Descarga adjuntos vía Microsoft Graph |
|
||||
| `_descomprimir()` | 136 | Descomprime archivos ZIP |
|
||||
| `_filtrar_y_limpiar()` | 151 | Filtra solo PDF/XML, elimina el resto |
|
||||
| **`_procesar_pdfs()`** | **193** | **Extrae datos de PDFs, renombra, genera cache** |
|
||||
| **`_procesar_xmls(pdf_cache)`** | **248** | **Procesa XMLs, cruza con PDF, asigna guías** |
|
||||
| `_guardar_resultado(documentos)` | 372 | Guarda JSON con datos extraídos |
|
||||
| **`_build_sap_draft(factura, resultados_val)`** | **403** | **Construye payload del draft SAP B1** |
|
||||
| **`_validate_prices(factura)`** | **564** | **Valida precios contra DeliveryNotes SAP** |
|
||||
| `_build_validation_html(resultados)` | 741 | Genera tabla HTML para notificación |
|
||||
| `_build_notification_body(status, factura, validation_table)` | 771 | Arma cuerpo del email de notificación |
|
||||
| `_guardar_draft_json(draft, serie, numero)` | 810 | Guarda draft JSON para depuración |
|
||||
| `_ruta_carpeta()` (módulo) | 33 | Resuelve una ruta relativa al directorio del script |
|
||||
| `_copiar_a_red(data, _log)` (módulo) | 37 | Copia PDF/XML de un comprobante a la ruta de red configurable |
|
||||
| `_descargar_adjuntos()` | 169 | Descarga adjuntos vía Microsoft Graph |
|
||||
| `_descomprimir()` | 198 | Descomprime archivos ZIP |
|
||||
| `_filtrar_y_limpiar()` | 213 | Filtra solo PDF/XML, elimina el resto |
|
||||
| **`_procesar_pdfs()`** | **255** | **Extrae datos de PDFs, renombra, genera cache** |
|
||||
| **`_procesar_xmls(pdf_cache)`** | **310** | **Procesa XMLs, cruza con PDF, asigna guías, copia a red** |
|
||||
| `_completar_guias(documentos, pdf_cache)` | 465 | Completa guías faltantes en líneas XML desde el PDF cache |
|
||||
| `_validar_guias(documentos)` | 524 | Advierte (log) guías con datos incompletos (falta tipo/serie/numero) |
|
||||
| `_guardar_resultado(documentos, datos_pdf)` | 534 | Guarda JSON con datos extraídos (XML y PDF) |
|
||||
| `_calcular_fecha_vencimiento(fecha_base, condicion_pago)` | 665 | Calcula `DocDueDate` = fecha de contabilización + días de `PaymentTermsTypes` |
|
||||
| **`_build_sap_draft(factura, resultados_val)`** | **694** | **Construye payload del draft SAP B1 (incluye `U_VS_ANEXO_PDF`/`U_VS_ANEXO_XML`, `DocDueDate` por condición de pago)** |
|
||||
| **`_validate_prices(factura)`** | **856** | **Valida precios contra DeliveryNotes/Orders SAP** |
|
||||
| `_build_validation_html(resultados)` | 1032 | Genera tabla HTML de validación de precios |
|
||||
| `_obtener_valor_referencial_sap(factura)` | 1062 | Consulta `Sp_ObtenerValorReferencial` en HANA por cada guía única |
|
||||
| `_build_valor_referencial_html(factura, guias_valor_ref)` | 1091 | Genera tabla HTML comparando valor referencial XML vs SAP |
|
||||
| `_build_notification_body(status, factura, validation_table, valor_referencial_table, **kwargs)` | 1127 | Arma cuerpo del email de notificación |
|
||||
| `_guardar_draft_json(draft, serie, numero)` | 1169 | Guarda draft JSON para depuración |
|
||||
|
||||
---
|
||||
|
||||
## `_copiar_a_red(data, _log)` — Copia a ruta de red
|
||||
|
||||
Copia el PDF y el XML de cada comprobante procesado a una ruta de red UNC configurable, en paralelo al guardado local existente (no lo reemplaza). No falla el pipeline si la ruta no está configurada o no está disponible: solo registra una advertencia.
|
||||
|
||||
- **Configuración** (`.env`): `RUTA_RED_FACTURACION` (ruta base UNC) y `RUC_EMPRESA` (RUC fijo de Aberio).
|
||||
- **Estructura de destino**:
|
||||
```
|
||||
{RUTA_RED_FACTURACION}\{año}\{mes}\{día}\{tipo}\{RUC_EMPRESA}\{ruc_emisor}\
|
||||
{RUC_EMPRESA}-{tipo}-{serie}-{numero}_FormatoImpreso.pdf
|
||||
{RUC_EMPRESA}-{tipo}-{serie}-{numero}.xml
|
||||
```
|
||||
`RUC_EMPRESA` es el RUC de Aberio (fijo); `ruc_emisor` es el RUC del proveedor que emitió la factura (varía por comprobante). Año/mes/día salen de `fecha_emision`, sin ceros a la izquierda en mes/día.
|
||||
- Guarda las rutas resultantes en `data["ruta_red_pdf"]` / `data["ruta_red_xml"]`, que luego usa `_build_sap_draft` para llenar `U_VS_ANEXO_PDF` / `U_VS_ANEXO_XML` en el draft SAP B1.
|
||||
- Se invoca desde `_procesar_xmls`, justo después de resolver `data["ruta_pdf"]`.
|
||||
|
||||
---
|
||||
|
||||
@@ -96,19 +127,46 @@ flowchart TD
|
||||
|
||||
```
|
||||
run_pipeline
|
||||
├── database_utilities.init_db
|
||||
├── step_authenticate
|
||||
│ └── outlook_utilities.get_access_token
|
||||
├── step_fetch_emails
|
||||
│ └── outlook_utilities.get_emails
|
||||
└── _procesar_un_correo (por cada email)
|
||||
├── database_utilities.get_existing_ids / save_emails
|
||||
├── _descargar_adjuntos
|
||||
│ └── outlook_utilities.download_attachments
|
||||
├── _descomprimir
|
||||
│ └── email_utilities.descomprimir_adjuntos
|
||||
├── _filtrar_y_limpiar
|
||||
├── _procesar_pdfs
|
||||
│ └── pdf_utilities.extraer_datos_pdf / renombrar_pdf
|
||||
├── _procesar_xmls
|
||||
│ ├── sunat_schema.extraer_datos_xml
|
||||
│ ├── pdf_utilities.extraer_referencias
|
||||
│ └── _copiar_a_red
|
||||
├── _completar_guias
|
||||
├── _validar_guias
|
||||
├── _guardar_resultado
|
||||
├── _validate_prices (por factura)
|
||||
│ └── sapb1_manager.get_delivery_notes
|
||||
├── _build_sap_draft
|
||||
├── _guardar_draft_json
|
||||
├── sapb1_manager.create_draft
|
||||
└── outlook_utilities.send_email
|
||||
│ └── sunat_schema.split_serie_numero, pdf_utilities.TIPO_MAP
|
||||
├── (por cada factura tipo 01)
|
||||
│ ├── _validate_prices
|
||||
│ │ ├── sapb1_manager.get_zonas
|
||||
│ │ └── sapb1_manager.get_delivery_notes
|
||||
│ │ ├── hana_manager.get_delivery (fallback si SL no responde;
|
||||
│ │ │ busca en ODLN y, si no hay, en OWTR)
|
||||
│ │ └── si el DocEntry vino de OWTR (StockTransfers), resuelve
|
||||
│ │ además la Orden de Venta asociada (Orders vía
|
||||
│ │ U_IDC_NUMOV) para poder validar las líneas FL*
|
||||
│ ├── _build_validation_html
|
||||
│ ├── _obtener_valor_referencial_sap
|
||||
│ │ └── hana_manager.obtener_valor_referencial
|
||||
│ ├── _build_valor_referencial_html
|
||||
│ ├── _build_sap_draft
|
||||
│ │ └── sapb1_manager.obtener_condicion_pago (BusinessPartners +
|
||||
│ │ PaymentTermsTypes, para calcular DocDueDate)
|
||||
│ ├── _guardar_draft_json
|
||||
│ ├── sapb1_manager.create_draft (si todas las líneas coinciden)
|
||||
│ ├── _build_notification_body
|
||||
│ └── outlook_utilities.send_email
|
||||
```
|
||||
Reference in new issue
Block a user