""" Recalcula leads_lake en MetricasDiarias para días 8-10 de junio 2026 añadiendo la atribución de leadforms via cursoid + UserAgent. También actualiza ConvLeadsLakeMes, Leads Lake y ConvLeadsLakeMesFinal. """ import json import re from datetime import datetime from airtable_client import AirtableClient DAYS = ["2026-06-08", "2026-06-09", "2026-06-10", "2026-06-11"] def _course_num(name: str) -> str | None: m = re.search(r'fco_(?:search|pmx)_(\d+)', name, re.IGNORECASE) return m.group(1) if m else None def run(): at = AirtableClient() campaigns = at.get_active_gacampaignmes() print(f"→ {len(campaigns)} campañas activas este mes\n") # Mapping cursoid → PMX campaign_id para leadforms diarios cursoid_to_campaign: dict[str, str] = {} for c in campaigns: num = _course_num(c["curso"]) if num and "pmx" in c["curso"].lower() and "_leadform" not in c["curso"].lower(): cursoid_to_campaign[num] = c["google_campaign_id"] print(f"→ Mapping cursoid→campaign: {len(cursoid_to_campaign)} entradas") # Obtener leads por campaña para cada día (una llamada bulk por día) daily_counts: dict[str, dict[str, int]] = {} for date_str in DAYS: daily_counts[date_str] = at.get_leads_by_campaign_on_date(date_str, cursoid_to_campaign) total = sum(daily_counts[date_str].values()) print(f" {date_str}: {total} leads totales encontrados") print() # Actualizar MetricasDiarias para cada campaña metricas_updates = [] for campaign in campaigns: cid = campaign["google_campaign_id"] try: md = json.loads(campaign["metricas_diarias"]) except (json.JSONDecodeError, TypeError): md = {} changed = False for date_str in DAYS: day_key = date_str[8:10] if day_key not in md: continue new_count = daily_counts[date_str].get(cid, 0) old_count = md[day_key].get("leads_lake", 0) if old_count != new_count: print(f" {campaign['curso'][:45]} día {day_key}: leads_lake {old_count} → {new_count}") md[day_key]["leads_lake"] = new_count # Recalcular ingreso_lxp para el día (leads_lake × PPL) md[day_key]["ingreso"] = round(new_count * campaign["ppl"], 2) changed = True if changed: metricas_updates.append({ "airtable_id": campaign["airtable_id"], "metricas_json": json.dumps(md, ensure_ascii=False), }) if metricas_updates: print(f"\n→ Actualizando MetricasDiarias ({len(metricas_updates)} registros)...") at.batch_update_metricas_diarias(metricas_updates) print(" ✓ MetricasDiarias actualizado.") else: print(" ✓ MetricasDiarias sin cambios.") # Cursoids con múltiples campañas PMX activas (mismo criterio que run.py) pmx_count_by_cursoid: dict[str, int] = {} for c in campaigns: num = _course_num(c["curso"]) if num and "pmx" in c["curso"].lower() and "_leadform" not in c["curso"].lower(): pmx_count_by_cursoid[num] = pmx_count_by_cursoid.get(num, 0) + 1 ambiguous_pmx_cursoids = {num for num, cnt in pmx_count_by_cursoid.items() if cnt > 1} if ambiguous_pmx_cursoids: print(f" ⚠️ Cursoids con múltiples PMX (paths 4/5 desactivados): {ambiguous_pmx_cursoids}") # Recalcular totales mensuales con la nueva atribución print("\n→ Recalculando totales mensuales (leads_lake acumulado del mes)...") final_leads_data = [] for campaign in campaigns: cid = campaign["google_campaign_id"] leads, lead_ids = at.get_leads_this_month_gads(cid, campaign["curso"], ambiguous_pmx_cursoids) at.update_gacampaignmes_leads_lake(campaign["airtable_id"], lead_ids) final_leads_data.append({ "airtable_id": campaign["airtable_id"], "conv_leads_lake_mes": leads, "conv_leads_lake_mes_grupo": leads, }) if leads > 0: print(f" {campaign['curso'][:45]}: {leads} leads") at.batch_update_gacampaignmes_final_leads(final_leads_data) print(" ✓ ConvLeadsLakeMesFinal actualizado.") if __name__ == "__main__": run()