""" generar_lista.py Genera datos.js con predicciones de compra limpias a partir de lista_compra_estimado.csv Uso: python generar_lista.py """ import pandas as pd import json import re from datetime import datetime # --------------------------------------------------------------------------- # Filtros de basura (líneas del ticket que no son productos) # --------------------------------------------------------------------------- BAD_PATTERNS = [ r'^\s*%', r'tarjeta', r'^total(\s|$|\s*\()', r'€/kg', r'\d+,\d+\s*kg', r'^n\.c', r'^aut[\s\d]', r'verificado', r'visa', r'bancaria', r'devoluciones', r'mastercard', r'importe', r'^iva\s', r'^cuota\s', r'^\d+,\d+\s*€', # líneas de precio suelto r'^\d{1,3}\s*€', # líneas tipo "15 €" ] def es_basura(nombre): n = nombre.lower().strip() if not n or len(n) < 3: return True return any(re.search(p, n) for p in BAD_PATTERNS) def limpiar_nombre(nombre): nombre = nombre.strip() # Quitar el "1" pegado al inicio del nombre que viene de la cantidad en el ticket # "1Yogur Limon" → "Yogur Limon" | "1+Prot Pud" → "+Prot Pud" # Pero "16 Huevos Camperos" → "16 Huevos Camperos" (es un pack de 16 huevos) nombre = re.sub(r'^1([A-ZÁÉÍÓÚÑ+a-záéíóúñ])', r'\1', nombre) return nombre.strip() # --------------------------------------------------------------------------- # Cargar datos # --------------------------------------------------------------------------- try: # Intentar UTF-8 primero, si falla usar cp1252 (Windows) try: df = pd.read_csv('lista_compra_estimado.csv', encoding='utf-8') except UnicodeDecodeError: df = pd.read_csv('lista_compra_estimado.csv', encoding='cp1252') except FileNotFoundError: print("❌ No se encontró lista_compra_estimado.csv") print(" Ejecuta primero: python autocompra5.py (o autocompra7.py)") exit(1) print(f" Productos en CSV: {len(df)}") # Filtrar basura df = df[~df['producto'].apply(es_basura)].copy() print(f" Después de filtrar basura: {len(df)}") # Limpiar nombres df['nombre'] = df['producto'].apply(limpiar_nombre) # Parsear fechas estimadas df['fecha'] = pd.to_datetime(df['fecha_estimada_proxima_compra'], format='%d/%m/%Y', errors='coerce') df = df.dropna(subset=['fecha', 'diferencia_dias']) # Excluir productos sin frecuencia real (frecuencia = 0 significa comprado una sola vez) df = df[df['diferencia_dias'] > 0] # Eliminar duplicados (mismo nombre → quedarse con el de menor frecuencia, más fiable) df = df.sort_values('diferencia_dias') df = df.drop_duplicates(subset='nombre', keep='first') # Calcular días hasta la próxima compra desde HOY hoy = pd.Timestamp(datetime.now().date()) df['dias_hasta'] = (df['fecha'] - hoy).dt.days # Ordenar: primero los más frecuentes (más urgentes a recoger), luego por fecha estimada df = df.sort_values(['diferencia_dias', 'dias_hasta']) # --------------------------------------------------------------------------- # Construir JSON de salida # --------------------------------------------------------------------------- resultado = [] for _, row in df.iterrows(): resultado.append({ 'producto': row['nombre'], 'fecha_estimada': row['fecha_estimada_proxima_compra'], 'dias_hasta': int(row['dias_hasta']), 'frecuencia_dias': round(float(row['diferencia_dias']), 1), }) # Escribir datos.js (cargable como