118 lines
5.2 KiB
Python
118 lines
5.2 KiB
Python
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()
|