Files
georgeandClaude Sonnet 5 15e3b5079c 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>
2026-09-10 13:21:04 -05:00

119 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import sys
import json
import glob
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from sunat_schema import extraer_datos_xml
def renombrar_xml(ruta_actual: str, data: dict, carpeta: str) -> str | None:
"""Renombra el XML a {prefijo}{ruc}-{tipo}-{serie}-{numero}.xml y retorna la nueva ruta.
Si es un CDR (ApplicationResponse), el prefijo es 'CDR-'."""
if not data:
return None
prefijo = "CDR-" if data.get("es_cdr") else ""
nombre = f"{prefijo}{data.get('ruc_emisor', '')}-{data.get('tipo', '')}-{data.get('serie', '')}-{data.get('numero', '')}.xml"
destino = os.path.join(carpeta, nombre)
if destino != ruta_actual:
if os.path.exists(destino):
os.remove(destino)
os.rename(ruta_actual, destino)
return destino
CARPETA_BASE = os.path.join(os.path.dirname(__file__), "correos_prueba")
def procesar_carpetas():
carpetas = sorted(
[d for d in os.listdir(CARPETA_BASE) if os.path.isdir(os.path.join(CARPETA_BASE, d))]
)
total = 0
for carpeta in carpetas:
ruta_carpeta = os.path.join(CARPETA_BASE, carpeta)
archivos_xml = sorted(
os.path.join(ruta_carpeta, f) for f in os.listdir(ruta_carpeta)
if f.lower().endswith(".xml") and os.path.isfile(os.path.join(ruta_carpeta, f))
)
if not archivos_xml:
continue
correlativo = carpeta.split("_")[0]
documentos = []
for xml_path in archivos_xml:
print(f"📄 {carpeta}/{os.path.basename(xml_path)}")
data = extraer_datos_xml(xml_path)
if data:
ruta_xml = renombrar_xml(xml_path, data, ruta_carpeta)
data["ruta_xml"] = ruta_xml or xml_path
data["ruta_pdf"] = None
if data.get("es_cdr"):
print(f" ├── ℹ️ {data.get('serie','?')}-{data.get('numero','?')} (CDR) — omitido del resultado")
continue
documentos.append(data)
print(f" ├── ✅ {data.get('serie','?')}-{data.get('numero','?')} ({data.get('tipo_descripcion','?')})")
else:
print(f" ├── ℹ️ No es factura 01 ni guía 31")
if documentos:
# Post-procesamiento
# 1. Distribuir documentos_referencia (tipo 09 y 31) a cada línea
for doc in documentos:
if doc.get("tipo") != "01":
continue
refs_09 = [r for r in doc.get("documentos_referencia", []) if r.get("tipo") == "09"]
refs_31 = [r for r in doc.get("documentos_referencia", []) if r.get("tipo") == "31"]
for i, linea in enumerate(doc.get("lineas", [])):
if linea.get("guias_remision"):
continue
if i < len(refs_09):
es_ultima = i == len(doc["lineas"]) - 1
if es_ultima:
linea["guias_remision"] = [dict(r) for r in refs_09[i:]]
else:
linea["guias_remision"] = [dict(refs_09[i])]
if not linea.get("guia_transportista") and i < len(refs_31):
linea["guia_transportista"] = dict(refs_31[i])
# 2. Resolver GREs desde guías de transporte (tipo 31 → tipo 09)
guia_lookup = {}
for doc in documentos:
if doc.get("tipo") in ("31", "09"):
guia_lookup[(doc["tipo"], doc["serie"], doc["numero"])] = doc
for doc in documentos:
if doc.get("tipo") != "01":
continue
for ref in doc.get("documentos_referencia", []):
if ref["tipo"] == "31":
guia_doc = guia_lookup.get(("31", ref["serie"], ref["numero"]))
if guia_doc:
gre_list = [g for g in guia_doc.get("documentos_referencia", []) if g.get("tipo") == "09"]
if gre_list:
for i, linea in enumerate(doc.get("lineas", [])):
if not linea.get("guias_remision"):
es_ultima = i == len(doc["lineas"]) - 1
if es_ultima:
linea["guias_remision"] = gre_list[i:]
elif i < len(gre_list):
linea["guias_remision"] = [gre_list[i]]
if not linea.get("guia_transportista"):
linea["guia_transportista"] = dict(ref)
ruta_json = os.path.join(ruta_carpeta, f"xml_resultado_{correlativo}.json")
with open(ruta_json, "w", encoding="utf-8") as f:
json.dump(documentos, f, ensure_ascii=False, indent=2)
print(f" └── 💾 Guardado: xml_resultado_{correlativo}.json ({len(documentos)} doc(s))")
total += len(documentos)
print(f"\n{'='*60}")
print(f"📊 Total documentos XML procesados: {total}")
if __name__ == "__main__":
procesar_carpetas()