Files
descarga_factura_transporte/docs/construir_draft.md
T
GeorgeandClaude Sonnet 5.5 d5a82ea025 se integra en draft_sap.py el cambio c5210c8: DueDate de cuotas = fecha_vencimiento
El commit c5210c8 del remoto cambió el DueDate de las cuotas en pipeline.py,
que ya se había dividido en módulos; al hacer el rebase se tomó la versión
dividida y aquí se reaplica el mismo cambio en draft_sap.build_sap_draft
(también se quita la línea comentada de ItemDescription). Se actualizan las
pruebas y la nota de construir_draft.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 22:04:11 -05:00

2.7 KiB

Construir Draft SAP B1

Función: draft_sap.build_sap_draft(factura, resultados_val) → dict listo para POST /Drafts.

flowchart TD
    A["factura + resultados_val<br>(de validate_prices)"] --> B["ItemCode según fecha_emision:<br>C103002-A (mes anterior)<br>C103002 (mes actual)"]
    B --> B2["CardCode = PL + ruc_emisor<br>sapb1_manager.obtener_condicion_pago(CardCode)<br>(BusinessPartners.PayTermsGrpCode → PaymentTermsTypes)"]
    B2 --> B3["DocDueDate = fecha_contabilizacion (hoy) +<br>NumberOfAdditionalDays<br>(si es 0, NumberOfAdditionalMonths * 30)"]
    B3 --> C["Calcular cuotas<br>DocumentInstallments"]

    C --> D{"¿Tiene detracción?"}
    D -->|Sí| E["monto_detraccion = ceil(monto)<br>Cuota 1: monto_detraccion<br>U_VS_TIPOCUOTA = D<br>U_VS_TIPOSERVICIO = codigo + '02'"]
    E --> F["Cuota 2: neto = total - monto_detraccion<br>U_VS_TIPOCUOTA = N"]
    D -->|No| G["Cuota única por el total<br>U_VS_TIPOCUOTA = N"]

    F --> H["Por cada línea de factura (índice i)"]
    G --> H

    H --> I["guias_lt[] = resultados_val[i]['guias_lt']<br>(si no hay, se salta la línea)"]
    I --> K["Por cada item en guias_lt[]"]

    K --> L["PriceAfterVAT = draft_price<br>truncado a 6 decimales"]
    L --> M["Quantity = draft_quantity"]
    M --> N["Crear DocumentLine:<br>ItemCode, Quantity, PriceAfterVAT,<br>WarehouseCode, FreeText (descripción[:100]),<br>campos fijos U_* / Costing / TaxCode I18,<br>U_IDC_GRFLETE = tipo+serie-numero de la guía"]
    N --> K

    K --> P["U_IDC_VALREF = suma de valor_referencial<br>de las líneas del XML"]
    P --> Q["U_IDC_NUMGR = primera guía de la<br>última línea que tuvo guías"]
    Q --> R["Cabecera: DocType, DocDate = hoy,<br>DocDueDate, TaxDate = fecha_emision,<br>CardCode, NumAtCard, Comments,<br>U_VS_ANEXO_PDF / U_VS_ANEXO_XML<br>(rutas de red de copiar_a_red)"]
    R --> S["DocumentLines[] + DocumentInstallments[]"]
    S --> T["← Retornar dict para POST /Drafts"]

Notas

  • draft_quantity y draft_price los fija validate_prices: con ok=True salen de SAP (int(max Quantity FL*) y suma de PriceAfterVAT FL*); con ok=False salen del XML (int(cantidad) y total_linea / cantidad). Ver validar_precios.md.
  • El valor referencial del draft (U_IDC_VALREF) sale del XML SUNAT (sunat_schema), no de SAP. La comparación contra SAP (Sp_ObtenerValorReferencial, vía hana_manager) solo se muestra en el correo de notificación.
  • El DueDate de las cuotas es el mismo fecha_vencimiento que usa la cabecera (DocDueDate): fecha de contabilización + días de la condición de pago. TaxDate es la única fecha que lleva la emisión del comprobante.
  • Si obtener_condicion_pago no encuentra condición para el proveedor, DocDueDate = fecha de contabilización.