se integra en draft_sap.py el cambio ee64e5f: DueDate de cuotas = fecha_vencimiento

El commit ee64e5f 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>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-20 22:04:11 -05:00
1 parent 297cfde0e1
commit 96dca78162
3 files changed
+9 -7

No files matched your search

+1 -1
View File
@@ -36,5 +36,5 @@ flowchart TD
- `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`. - `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 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.
- Las cuotas usan `fecha_emision` como `DueDate`; el vencimiento por condición de pago (`DocDueDate`) aplica solo a la cabecera. - 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. - Si `obtener_condicion_pago` no encuentra condición para el proveedor, `DocDueDate` = fecha de contabilización.
+3 -4
View File
@@ -125,12 +125,12 @@ def build_sap_draft(factura: dict, resultados_val: list[dict]) -> dict:
monto_detraccion = math.ceil(monto_detraccion) monto_detraccion = math.ceil(monto_detraccion)
neto = total - monto_detraccion neto = total - monto_detraccion
installments = [ installments = [
{"DueDate": fecha_emision, "Total": monto_detraccion, "InstallmentId": 1, "U_VS_TIPOCUOTA": "D", "U_VS_TIPOSERVICIO": f"{codigo_detraccion}02"}, {"DueDate": fecha_vencimiento, "Total": monto_detraccion, "InstallmentId": 1, "U_VS_TIPOCUOTA": "D", "U_VS_TIPOSERVICIO": f"{codigo_detraccion}02"},
{"DueDate": fecha_emision, "Total": round(neto,2), "InstallmentId": 2, "U_VS_TIPOCUOTA": "N", "U_VS_TIPOSERVICIO": ""}, {"DueDate": fecha_vencimiento, "Total": round(neto,2), "InstallmentId": 2, "U_VS_TIPOCUOTA": "N", "U_VS_TIPOSERVICIO": ""},
] ]
else: else:
installments = [ installments = [
{"DueDate": fecha_emision, "Total": round(total, 2), "InstallmentId": 1, "U_VS_TIPOCUOTA": "N", "U_VS_TIPOSERVICIO": ""}, {"DueDate": fecha_vencimiento, "Total": round(total, 2), "InstallmentId": 1, "U_VS_TIPOCUOTA": "N", "U_VS_TIPOSERVICIO": ""},
] ]
doc_lines = [] doc_lines = []
@@ -151,7 +151,6 @@ def build_sap_draft(factura: dict, resultados_val: list[dict]) -> dict:
doc_lines.append({ doc_lines.append({
"ItemCode": item_code, "ItemCode": item_code,
#"ItemDescription": linea.get("descripcion", "TRANSPORTE DE CARGA MERCADERIA")[:200],
"Quantity": qty, "Quantity": qty,
"PriceAfterVAT": lt_val, "PriceAfterVAT": lt_val,
"WarehouseCode": item.get("warehouse_code", "A-CENTRA"), "WarehouseCode": item.get("warehouse_code", "A-CENTRA"),
+5 -2
View File
@@ -168,8 +168,9 @@ def test_draft_cabecera_y_linea(condicion_pago):
assert linea["U_IDC_GRFLETE"] == "09T001-100" assert linea["U_IDC_GRFLETE"] == "09T001-100"
assert linea["WarehouseCode"] == "A-X" assert linea["WarehouseCode"] == "A-X"
assert draft["DocumentInstallments"] == [ vencimiento = (hoy + timedelta(days=30)).strftime("%Y-%m-%d")
{"DueDate": hoy.strftime("%Y-%m-%d"), "Total": 118.0, "InstallmentId": 1, assert draft["DocumentInstallments"] == [ # la cuota vence en la fecha de vencimiento, no en la de emisión
{"DueDate": vencimiento, "Total": 118.0, "InstallmentId": 1,
"U_VS_TIPOCUOTA": "N", "U_VS_TIPOSERVICIO": ""}, "U_VS_TIPOCUOTA": "N", "U_VS_TIPOSERVICIO": ""},
] ]
@@ -192,6 +193,7 @@ def test_draft_con_detraccion_genera_dos_cuotas(condicion_pago):
draft = draft_sap.build_sap_draft(factura, _resultados()) draft = draft_sap.build_sap_draft(factura, _resultados())
detraccion, neto = draft["DocumentInstallments"] detraccion, neto = draft["DocumentInstallments"]
assert detraccion["DueDate"] == neto["DueDate"] == draft["DocDueDate"] # ambas cuotas vencen en el vencimiento
assert (detraccion["Total"], detraccion["U_VS_TIPOCUOTA"], detraccion["U_VS_TIPOSERVICIO"]) == (12, "D", "00402") assert (detraccion["Total"], detraccion["U_VS_TIPOCUOTA"], detraccion["U_VS_TIPOSERVICIO"]) == (12, "D", "00402")
assert (neto["Total"], neto["U_VS_TIPOCUOTA"]) == (106.0, "N") # 118 - ceil(11.2) assert (neto["Total"], neto["U_VS_TIPOCUOTA"]) == (106.0, "N") # 118 - ceil(11.2)
assert draft["U_VS_AFEDET"] == "Y" assert draft["U_VS_AFEDET"] == "Y"
@@ -211,6 +213,7 @@ def test_draft_sin_condicion_de_pago_vence_el_dia_de_contabilizacion(monkeypatch
fecha = datetime.now().strftime("%Y-%m-%d") fecha = datetime.now().strftime("%Y-%m-%d")
draft = draft_sap.build_sap_draft(_factura(fecha), _resultados()) draft = draft_sap.build_sap_draft(_factura(fecha), _resultados())
assert draft["DocDueDate"] == draft["DocDate"] assert draft["DocDueDate"] == draft["DocDate"]
assert draft["DocumentInstallments"][0]["DueDate"] == draft["DocDate"]
# ============================================================================ # ============================================================================