diff --git a/agent.py b/agent.py index b7c19cc..1a548da 100644 --- a/agent.py +++ b/agent.py @@ -19,6 +19,9 @@ ESTADO DE LA CAMPAÑA: - Nunca recomiendes reactivar una campaña si status_google = ENABLED (ya está activa). - Si status_google = PAUSED y la acción es AUMENTAR_PRESUPUESTO, menciona en el consejo que primero hay que reactivarla. +CAPPING: +- Si capping = 0, significa que no hay límite de leads configurado para este mes. No menciones el capping en el consejo ni en la justificación. Toma la decisión basándote únicamente en rentabilidad y ritmo. + REGLAS DE DECISIÓN: 1. urgencia=PAUSAR → accion=PAUSAR siempre. El capping está lleno, seguir gastando destruye margen. 2. urgencia=SPRINT → accion=AUMENTAR_PRESUPUESTO con parametro entre 1.3 y 1.5. Quedan pocos días y leads por entregar. diff --git a/airtable_client.py b/airtable_client.py index 714ce7a..25b7c22 100644 --- a/airtable_client.py +++ b/airtable_client.py @@ -306,6 +306,7 @@ class AirtableClient: "capping_mensual": int(f.get("CapTotalMes") or 0), "cpa_maximo": float(f.get("CPAMax") or 0), "margen_objetivo": float(f.get("MargenObjetivo") or 0), + "conv_leads_lake_mes": int(f.get("ConvLeadsLakeMes") or 0), }) return result @@ -341,7 +342,10 @@ class AirtableClient: mes_inicio = f"{now.year}-{now.month:02d}-01" formula = ( f"AND(" - f"FIND('gad_campaignid={campaign_id}',{{attr_referer}})," + f"OR(" + f"{{GACampaignID}}='{campaign_id}'," + f"FIND('gad_campaignid={campaign_id}',{{attr_referer}})" + f")," f"{{attr_utm_medium}}='paid_search'," f"{{creado}}>='{mes_inicio}'" f")" @@ -354,6 +358,19 @@ class AirtableClient: """Actualiza el campo 'Leads Lake' de un registro GACampaignMes.""" self.gacampaignmes.update(gcm_record_id, {"Leads Lake": lead_ids}) + def batch_update_gacampaignmes_final_leads(self, gcm_records: list[dict]) -> None: + """ + Copia ConvLeadsLakeMes → ConvLeadsLakeMesFinal en GACampaignMes. + Se llama una vez por ejecución diaria. + gcm_records: lista de dicts con 'airtable_id' y 'conv_leads_lake_mes' + """ + batch = [ + {"id": r["airtable_id"], "fields": {"ConvLeadsLakeMesFinal": r["conv_leads_lake_mes"]}} + for r in gcm_records + ] + for i in range(0, len(batch), 10): + self.gacampaignmes.batch_update(batch[i:i+10]) + def batch_update_gacampaignmes_advice(self, updates: list[tuple[str, str, str]]) -> None: """ Actualiza en lote los campos 'Consejo' y 'Criticidad' de GACampaignMes. diff --git a/analyzer.py b/analyzer.py index 56df025..e5f74d3 100644 --- a/analyzer.py +++ b/analyzer.py @@ -35,8 +35,9 @@ def analyze(campaign_config: dict, leads_entregados: int, ads_metrics: dict) -> else: urgencia = "EN_RITMO" - # Discrepancia entre leads Airtable y conversiones Google - discrepancia = abs(conversiones_google - leads_entregados) + # Discrepancia entre leads Airtable (ConvLeadsLakeMes) y conversiones Google + conv_leads_lake_mes = campaign_config.get("conv_leads_lake_mes", leads_entregados) + discrepancia = abs(conversiones_google - conv_leads_lake_mes) return { "curso": campaign_config["curso"], diff --git a/run.py b/run.py index f601fde..e7c2352 100644 --- a/run.py +++ b/run.py @@ -211,7 +211,7 @@ def run(): if analysis["alerta_tracking"]: print(f" 🚨 ALERTA TRACKING: {analysis['discrepancia_tracking']} leads de diferencia " - f"entre Airtable ({leads}) y Google Ads ({int(analysis['conversiones_google'])})") + f"entre Airtable ({campaign['conv_leads_lake_mes']}) y Google Ads ({int(analysis['conversiones_google'])})") print(f" Decisión: {accion_icono} {decision['accion']} " f"(confianza: {decision['confianza']*100:.0f}%)") @@ -251,6 +251,17 @@ def run(): at.batch_update_gacampaignmes_advice(advice_updates) print(" ✓ Consejos y criticidad guardados.") + # Copiar ConvLeadsLakeMes → ConvLeadsLakeMesFinal (snapshot diario) + final_leads_data = [ + {"airtable_id": item["campaign"]["airtable_id"], + "conv_leads_lake_mes": item["campaign"]["conv_leads_lake_mes"]} + for item in collected + ] + if final_leads_data: + print(f"→ Actualizando ConvLeadsLakeMesFinal ({len(final_leads_data)} registros)...") + at.batch_update_gacampaignmes_final_leads(final_leads_data) + print(" ✓ ConvLeadsLakeMesFinal actualizado.") + # Resumen final ordenado por prioridad (ya está ordenado) print(f"{'='*55}") print("RESUMEN FINAL")