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:
georgeandClaude Sonnet 5 committed 2026-09-10 13:21:04 -05:00
1 parent 6b0ed6f519
commit 15e3b5079c
231 files changed
+21421 -475

No files matched your search

+3 -2
View File
@@ -32,6 +32,7 @@ GUIAS_NOTES_PATTERNS = [
# Agregar aquí nuevas variantes a medida que aparezcan en facturas de otros clientes.
VALOR_REFERENCIAL_PATTERNS = [
r"VALOR\s+REFERENCIAL\.?\s*:?\s*(?:S/\.?\s*)?([\d,]+\.\d+)", # "VALOR REFERENCIAL: S/ 2,345.00" / "VALOR REFERENCIAL: 468.86"
r"VALOR\s+REFER\.?\s*:?\s*(?:S/\.?\s*)?([\d,]+\.\d+)", # "VALOR REFER\t:S/ 1431.16"
r"VALOR\s+REF\.?\s*:?\s*(?:S/\.?\s*)?([\d,]+\.\d+)", # "VALOR REF:S/ 1,139.75"
r"VAL\.?\s*REF\.?\s*:?\s*(?:S/\.?\s*)?([\d,]+\.\d+)", # "VAL.REF.:S/700.25"
r"V\.?\s*REF\.?\s*:?\s*(?:S/\.?\s*)?([\d,]+\.\d+)", # "V.REF: S/ 2940.80 TN: 36.85"
@@ -128,7 +129,7 @@ class DatosComprobante:
refs_str = ""
if self.documentos_referencia:
refs_str = "\n Documentos Ref: " + ", ".join(
f"{ref.id} (Tipo {ref.tipo})" for ref in self.documentos_referencia
f"{ref.serie}-{ref.numero} (Tipo {ref.tipo})" for ref in self.documentos_referencia
)
detraccion_str = ""
if self.tiene_detraccion:
@@ -686,7 +687,7 @@ def extraer_datos_xml(ruta_xml: str) -> Optional[dict]:
return datos.to_dict()
if "DespatchAdvice" in tag:
tipo = _find_text(root, "desp:DespatchAdviceTypeCode", NAMESPACES) or _find_text(root, "cbc:DespatchAdviceTypeCode", NAMESPACES) or ""
if tipo in ["31"]:
if tipo in ("09", "31"):
datos = _parse_despatch_advice(root)
return datos.to_dict()
return None