import sys import json import os import outlook_utilities import database_utilities import email_services import logger_utilities import document_processor import file_manager from datetime import datetime, timedelta from config_loader import CONFIG ######################################################## if __name__ == "__main__": # Configurar Logger (Redirige stdout a archivo y consola) log_path = logger_utilities.setup_logger() logger_utilities.limpiar_logs_antiguos(dias=30) inicio_ejecucion = datetime.now() print("="*60) print(f"🚀 INICIO DE EJECUCIÓN: {inicio_ejecucion.strftime('%Y-%m-%d %H:%M:%S')}") print(f"📄 Log guardado en: {log_path}") print("="*60) # Inicializar Base de Datos database_utilities.init_db() # Calcular fechas hoy = datetime.now() ayer = hoy - timedelta(days=1) fecha_inicio = ayer.strftime("%Y-%m-%d") fecha_fin = hoy.strftime("%Y-%m-%d") print(f"Rango de búsqueda: {fecha_inicio} al {fecha_fin}") try: print("Intentando obtener token de acceso...") outlook_token = outlook_utilities.get_access_token() print("✅ Token obtenido exitosamente.") print(f"Token prefix: {outlook_token[:15]}...") except Exception as e: print(f"❌ Error: {e}") sys.exit(1) todos_procesados = [] for mail in CONFIG.mails: print("\n" + "="*60) print(f"[MAIL] {mail.email}") emails = outlook_utilities.get_emails(mail.email, outlook_token, fecha_inicio, fecha_fin) print(f"Se encontraron {len(emails)} correos.") # Filtrar y guardar usando el servicio de emails emails_a_procesar = email_services.filtrar_correos_nuevos(emails) if emails_a_procesar: print(f"Descargando adjuntos en: {mail.ruta_descarga}") emails_finales = [] # Lista definitiva de correos con adjuntos válidos for e in emails_a_procesar: try: # Guardar lista original para el log archivos_orig = outlook_utilities.download_attachments( mail.email, e['id'], outlook_token, mail.ruta_descarga ) if archivos_orig: # Encabezado del correo con fecha print(f"\n📬 [{e['fecha']}] {e['subject'][:80]}...") # --- SECCIÓN 1: ADJUNTOS ORIGINALES --- print(f" ├── 📂 Adjuntos originales:") for idx, a in enumerate(archivos_orig): prefijo = " │ └── " if idx == len(archivos_orig)-1 else " │ ├── " print(f"{prefijo}{a}") # 1. Procesar adjuntos (unzip + filtro) # Usamos una copia de la lista original archivos_unzipped = email_services.procesar_adjuntos_email(e, archivos_orig.copy(), mail.ruta_descarga) if archivos_unzipped: # 2. Extraer metadatos iniciales (antes del renombrado) metadatos = document_processor.procesar_adjuntos_enriquecidos(e, mail.ruta_descarga) e['metadatos_adjuntos'] = metadatos # 3. Aplicar lógica de agrupación y renombrado # Esto modifica e['metadatos_adjuntos'] in-place agrupacion = file_manager.procesar_renombrado_agrupado(e, mail.ruta_descarga) e['agrupacion_archivos'] = agrupacion # --- SECCIÓN 2: PROCESO --- print(f" ├── ⚙️ Proceso:") logs_proceso = [] # Detectar ZIPs procesados zips = [a for a in archivos_orig if a.lower().endswith('.zip')] for z in zips: logs_proceso.append(f"📦 Descomprimido: {z}") # Detectar Renombrados (si el nombre final no está en los unzipped filtrados) for m in e['metadatos_adjuntos']: if m['archivo'] not in archivos_unzipped: logs_proceso.append(f"🏷️ Renombrado a: {m['archivo']}") if not logs_proceso: print(f" │ └── Sin cambios especiales") else: for idx, log in enumerate(logs_proceso): prefijo = " │ └── " if idx == len(logs_proceso)-1 else " │ ├── " print(f"{prefijo}{log}") # 4. Mover archivos a carpeta de resultados final file_manager.mover_archivos_a_resultado(e, mail.ruta_descarga, mail.ruta_final) # --- SECCIÓN 3: RESULTADO FINAL --- print(f" └── 📄 Resultado Final:") for idx, m in enumerate(e['metadatos_adjuntos']): prefijo = " └── " if idx == len(e['metadatos_adjuntos'])-1 else " ├── " icono = "📕" if m['extension'] == ".pdf" else "🌐" info_extra = f"[{m['tipo']}] {m['serie_numero']} - RUC: {m['ruc']}" print(f"{prefijo}{icono} {m['archivo']} -> {info_extra}") emails_finales.append(e) else: print(f" └── ℹ️ Descartado (sin archivos PDF/XML válidos).") except Exception as ex: print(f" ❌ Error procesando {e['id'][:10]}: {ex}") # 5. Sincronizar a SMB al terminar de procesar TODOS los correos de esta cuenta if emails_finales: import smb_utils smb_utils.sincronizar_a_smb(mail.ruta_final, mail.smb_folder) # 6. Limpiar carpeta de descarga original file_manager.limpiar_carpeta_descarga(mail.ruta_descarga) # Actualizamos el listado con los que realmente tienen contenido útil emails_a_procesar = emails_finales print(f"\n✅ Proceso completado para {mail.email}. {len(emails_a_procesar)} correos listos para procesar.") # Acumular para el guardado final en JSON todos_procesados.extend(emails_a_procesar) # Guardar resultados globales en JSON if todos_procesados: output_dir = "output_json" if not os.path.exists(output_dir): os.makedirs(output_dir) timestamp_json = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") json_path = os.path.join(output_dir, f"{timestamp_json}.json") with open(json_path, "w", encoding="utf-8") as f: json.dump(todos_procesados, f, ensure_ascii=False, indent=4) print("\n" + "="*60) print(f"💾 Resultados exportados a: {json_path}") fin_ejecucion = datetime.now() duracion = fin_ejecucion - inicio_ejecucion print("\n" + "="*60) print(f"🏁 FIN DE EJECUCIÓN: {fin_ejecucion.strftime('%Y-%m-%d %H:%M:%S')}") print(f"⏱️ Duración total: {str(duracion).split('.')[0]}") # Sin microsegundos print("="*60)