cargando primer proyecto a gitea

This commit is contained in:
George committed 2026-05-15 16:39:08 -05:00
commit 533105e7c3
16 files changed
+1327

No files matched your search

+188
View File
@@ -0,0 +1,188 @@
import os
########################################################
def calcular_puntuacion(nombre_archivo, ruc, tipo, serie_numero):
"""
Calcula una puntuación de 0 a 4 según cuántos elementos coinciden en el nombre del archivo.
serie_numero se descompone en serie y número.
"""
puntos = 0
nombre_archivo = nombre_archivo.upper()
# 1. RUC
if ruc and ruc != "N/A" and ruc in nombre_archivo:
puntos += 1
# 2. Tipo
if tipo and tipo != "99" and tipo in nombre_archivo:
puntos += 1
# 3. Serie y 4. Número
if "-" in serie_numero:
partes = serie_numero.split("-")
serie = partes[0].upper()
numero = partes[1]
if serie in nombre_archivo:
puntos += 1
if numero in nombre_archivo:
puntos += 1
return puntos
########################################################
def procesar_renombrado_agrupado(email_obj, ruta_base):
"""
Lógica de agrupación y renombrado de archivos según puntuación y tipo.
"""
metadatos = email_obj.get('metadatos_adjuntos', [])
tipos_permitidos = ["01", "03", "07", "08", "02", "09", "14"]
# 1. Identificar "Pivotes" (pivotes para agrupar)
# Preferencia: XML Maestros. Fallback: PDFs con metadata válida si no hay XMLs.
xml_maestros = [m for m in metadatos if m['extension'] == ".xml" and m['tipo'] in tipos_permitidos]
if xml_maestros:
pivotes = xml_maestros
else:
# En correos solo PDF, tratamos a cada PDF con nombre propuesto como un pivote
pivotes = [m for m in metadatos if m['extension'] == ".pdf" and m['archivo_propuesto'] is not None]
if not pivotes:
return {} # Nada que agrupar
nuevos_archivos = []
mapeo_renombrado = {} # original -> nuevo
agrupacion = {} # archivo_propuesto -> [lista de nombres nuevos]
# Inicializar el diccionario de agrupación con los nombres de los pivotes
for p in pivotes:
agrupacion[p['archivo_propuesto']] = []
# 2. Agrupar cada archivo con su mejor pivote
for m in metadatos:
nombre_original = m['archivo']
extension = m['extension'].lower()
# Si es un pivote, su nombre es directo y ya está inicializado
if m in pivotes:
nombre_nuevo = f"{m['archivo_propuesto']}{extension}"
mapeo_renombrado[nombre_original] = nombre_nuevo
agrupacion[m['archivo_propuesto']].append(nombre_nuevo)
else:
# Buscar el mejor match entre los pivotes que aún acepten este tipo de archivo
mejor_pivote = None
max_puntos = -1
is_cdr = m['tipo'] == "CDR" or "R-" in nombre_original or "R_" in nombre_original or "CDR" in nombre_original.upper()
is_pdf = extension == ".pdf"
is_xml = extension == ".xml" and not is_cdr
for p in pivotes:
p_prop = p['archivo_propuesto']
grupo_actual = agrupacion[p_prop]
ya_tiene_pdf = any(f.lower().endswith('.pdf') for f in grupo_actual)
ya_tiene_cdr = any(f.startswith('CDR-') for f in grupo_actual)
if (is_pdf and ya_tiene_pdf) or (is_cdr and ya_tiene_cdr) or is_xml:
continue
puntos = calcular_puntuacion(
nombre_original,
p['ruc'],
p['tipo'],
p['serie_numero']
)
if puntos > max_puntos:
max_puntos = puntos
mejor_pivote = p
if mejor_pivote and max_puntos > 0:
prefix = "CDR-" if is_cdr else ""
nombre_nuevo = f"{prefix}{mejor_pivote['archivo_propuesto']}{extension}"
mapeo_renombrado[nombre_original] = nombre_nuevo
agrupacion[mejor_pivote['archivo_propuesto']].append(nombre_nuevo)
else:
# Si no hay match, va a OTROS
mapeo_renombrado[nombre_original] = nombre_original
if "OTROS" not in agrupacion: agrupacion["OTROS"] = []
agrupacion["OTROS"].append(nombre_original)
# 3. Ejecutar el renombrado físico y actualizar metadatos
for m in metadatos:
nombre_original = m['archivo']
nombre_nuevo = mapeo_renombrado.get(nombre_original)
if nombre_nuevo and nombre_nuevo != nombre_original:
ruta_old = os.path.join(ruta_base, nombre_original)
ruta_new = os.path.join(ruta_base, nombre_nuevo)
try:
if os.path.exists(ruta_old):
# Si el destino ya existe, borramos para sobreescribir (o podrías manejarlo de otra forma)
if os.path.exists(ruta_new) and ruta_old != ruta_new:
os.remove(ruta_new)
os.rename(ruta_old, ruta_new)
m['archivo'] = nombre_nuevo
except Exception as e:
print(f" ⚠️ Error renombrando {nombre_original}: {e}")
# 4. Actualizar la lista de archivos en el email_obj
email_obj['archivos'] = [m['archivo'] for m in metadatos]
return agrupacion
########################################################
def mover_archivos_a_resultado(email_obj, ruta_origen, ruta_destino):
"""
Mueve los archivos procesados de la carpeta temporal a la carpeta final de resultados.
Solo mueve archivos que pertenecen a un grupo válido (basado en archivo_propuesto).
Excluye los archivos en la categoría 'OTROS'.
"""
agrupacion = email_obj.get('agrupacion_archivos', {})
if not agrupacion:
return
if not os.path.exists(ruta_destino):
os.makedirs(ruta_destino)
print(f" 📁 Carpeta de destino creada: {ruta_destino}")
for key, archivos in agrupacion.items():
if key == "OTROS":
continue # No mover archivos no identificados
for archivo in archivos:
ruta_old = os.path.join(ruta_origen, archivo)
ruta_new = os.path.join(ruta_destino, archivo)
try:
if os.path.exists(ruta_old):
if os.path.exists(ruta_new) and ruta_old != ruta_new:
os.remove(ruta_new)
os.rename(ruta_old, ruta_new)
except Exception as e:
print(f" ⚠️ Error trasladando {archivo} a resultado: {e}")
########################################################
def limpiar_carpeta_descarga(ruta):
"""
Elimina todos los archivos dentro de la carpeta de descarga para dejarla limpia.
"""
if not os.path.exists(ruta):
return
print(f" 🧹 Limpiando carpeta de descarga: {ruta}")
for archivo in os.listdir(ruta):
ruta_archivo = os.path.join(ruta, archivo)
try:
if os.path.isfile(ruta_archivo):
os.remove(ruta_archivo)
elif os.path.isdir(ruta_archivo):
import shutil
shutil.rmtree(ruta_archivo)
except Exception as e:
print(f" ⚠️ No se pudo eliminar {archivo}: {e}")
########################################################