Files
descarga_factura_transporte/docs/validar_precios.md
T
GeorgeandClaude Sonnet 5.5 6030320822 se actualiza la documentación: sapb1_manager, nombres de funciones y cifras
- Nueva página docs/sapb1_manager.md: sesión, funciones, clasificación de
  errores (SapNoDisponible frente a rechazo de SAP), búsqueda de facturas
  existentes y cómo se ubica una guía.
- procesar_pdfs.md y procesar_xmls.md usaban los nombres anteriores a la
  división de pipeline.py (_procesar_pdfs, _ruta_carpeta...) y números de
  línea que envejecen; ahora apuntan a documentos.py.
- inventario.md: árbol de dependencias con los módulos nuevos.
- pipeline.md: _procesar_factura, importes_coinciden, hana_disponible y
  buscar_factura_existente; validar_precios.md, hana_manager.md, main.md y
  procesar_xmls.md con las notas que faltaban; README sin la cifra de pruebas
  vieja.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 14:56:34 -05:00

3.4 KiB
Raw Blame History

Validar Precios

flowchart TD
    A["factura con lineas[]"] --> B["Obtener maestro zonas<br>SAP U_IDC_ZONAS"]
    B --> C["Por cada línea de factura"]

    C --> D{"cantidad > 0?"}
    D -->|No| E["Resultado: cantidad cero, sin validar"]
    D -->|Sí| F{"¿Hay guías de remisión?"}
    F -->|No| G["Resultado: sin guía de referencia"]

    F -->|Sí| H["Por cada guía en guias[]"]
    H --> I["Consultar SAP B1<br>get_delivery_notes()"]
    I --> I2{"¿Guía encontrada en<br>ODLN o en OWTR?"}
    I2 -->|ODLN| I3["Documento = DeliveryNotes(DocEntry)"]
    I2 -->|OWTR| I4["Documento = StockTransfers(DocEntry)<br>→ leer U_IDC_NUMOV<br>→ Documento = Orders(U_IDC_NUMOV)"]
    I3 --> J["Por cada documento<br>(DeliveryNote u Orden de Venta)"]
    I4 --> J

    J --> K["Obtener zona desde<br>U_IDC_DESTINO"]
    K --> L["Extraer WarehouseCode<br>de DocumentLines[0]"]
    L --> M["Acumular Weight1<br>de DocumentLines[0]"]
    M --> N["Por cada línea FL* en<br>DocumentLines"]


    N --> O["Sumar LineTotal"]
    O --> P["Máx Quantity"]
    P --> Q["Sumar PriceAfterVAT"]
    Q --> R["Construir guias_lt[]<br>para cada guía:<br>line_total, quantity,<br>price_after_vat_sum,<br>warehouse_code, zona, weight1"]

    R --> S["Comparar total_linea (XML)<br>vs sap_total (FL*)"]
    S --> T{"importes_coinciden:<br>diferencia redondeada a 2 decimales ≤ 0.01<br>y ninguna guía falló?"}
    T -->|Sí| U["ok = True<br>draft_quantity = int(Quantity máx FL*)<br>draft_price = suma PriceAfterVAT FL*"]
    T -->|No| V["ok = False<br>draft_quantity = int(cantidad XML)<br>draft_price = total_linea / cantidad"]

    U --> W["Resultado por línea:<br>ok, draft_price, sap_price,<br>label, warehouse_code, guias_lt[]"]
    V --> W
    W --> C
    C --> X["todas_coinciden = all(ok)"]

Notas

  • Si la consulta a SAP de una guía lanza error, esa guía queda con ceros y la línea completa se marca ok = False (se registra como WARNING).
  • Si ninguna guía de la línea existe en SAP, el resultado lleva label = "Sin guías SAP" y se registra "línea saltada", pero igual queda ok = False (salvo que total_linea sea 0), por lo que todas_coinciden es falso y no se crea el draft.
  • weight1 (peso de la primera línea de cada guía) se sigue calculando y guardando en guias_lt[], pero el draft ya no lo usa.
  • Función: draft_sap.validate_prices(factura) → (todas_coinciden, resultados).
  • Tolerancia: pipeline_utils.importes_coinciden redondea la diferencia entre el importe de la línea del XML y el de SAP a 2 decimales (lo que muestra un comprobante) y admite hasta 1 céntimo. Comparar la diferencia sin redondear (abs(a - b) < 0.01) no era fiable por la coma flotante: 431.41 − 431.40 daba 0.01000000000004775 (se rechazaba) y 624.39 − 624.38 daba 0.00999999999999091 (se aceptaba), así que el mismo céntimo pasaba o no según el importe. Con datos reales de SAP, ninguna línea cambió de resultado al introducir el redondeo. Se usa también para comparar el valor referencial del correo técnico.
  • Caída de SAP vs. guía inexistente: validate_prices deja pasar SapNoDisponible (timeout, sin conexión, HTTP 5xx) en vez de convertirla en un error de la guía; el pipeline la trata como servicio fuera de línea. Otros errores de consulta quedan en guias_lt[].error (ver draft_sap.hay_error_de_consulta) y se tratan como error interno. Una guía sin datos en SAP solo se reporta como "no encontrada" si HANA responde (draft_sap.hana_disponible).