- GAMes: new Airtable table aggregating daily fco_ metrics (coste, ingreso_sum, ingreso_lxp, leads, leads_lake) - run.py: accumulate fco_ daily aggregate and write to GAMes each run - slack_reporter.py: replace sparkline with daily margin % table (Sumatorio + LeadsxPPL per day) - backfill_games_mayo.py: populated GAMes with all 17 existing May days Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
74 lines
2.5 KiB
Python
74 lines
2.5 KiB
Python
"""
|
|
Script one-off: crea el registro de mayo 2026 en GAMes y rellena MetricasDiarias
|
|
con el agregado diario de todas las campañas fco_ a partir de GACampaignMes.
|
|
|
|
Ejecutar una sola vez:
|
|
python backfill_games_mayo.py
|
|
"""
|
|
import json
|
|
from airtable_client import AirtableClient
|
|
|
|
at = AirtableClient()
|
|
|
|
MES = 5
|
|
ANIO = 2026
|
|
|
|
print("Cargando registros GACampaignMes de mayo (campañas fco_)...")
|
|
records = at.gacampaignmes.all(
|
|
formula="AND({Mes}='5',{Año}='2026')",
|
|
fields=["CampaignID", "MetricasDiarias", "Campaign Name (from CampaignID)"],
|
|
)
|
|
|
|
campaigns_records = at.campaigns.all(fields=["CampaignID", "PPL"])
|
|
at_id_to_info = {
|
|
r["id"]: {
|
|
"gid": str(r["fields"].get("CampaignID", "")).strip(),
|
|
"ppl": float(r["fields"].get("PPL", 0) or 0),
|
|
}
|
|
for r in campaigns_records
|
|
}
|
|
|
|
# Agregar métricas por día para campañas fco_
|
|
daily_agg: dict[str, dict] = {}
|
|
|
|
for r in records:
|
|
at_cids = r["fields"].get("CampaignID", [])
|
|
if not at_cids:
|
|
continue
|
|
info = at_id_to_info.get(at_cids[0], {})
|
|
ppl = info.get("ppl", 0)
|
|
|
|
campaign_names = r["fields"].get("Campaign Name (from CampaignID)", [])
|
|
campaign_name = (campaign_names[0] if campaign_names else "").lower()
|
|
if not campaign_name.startswith("fco_"):
|
|
continue
|
|
|
|
try:
|
|
md = json.loads(r["fields"].get("MetricasDiarias") or "{}")
|
|
except (json.JSONDecodeError, TypeError):
|
|
md = {}
|
|
|
|
for day_str, vals in md.items():
|
|
if day_str not in daily_agg:
|
|
daily_agg[day_str] = {"coste": 0.0, "ingreso_sum": 0.0, "ingreso_lxp": 0.0, "leads": 0, "leads_lake": 0}
|
|
daily_agg[day_str]["coste"] += vals.get("coste", 0)
|
|
daily_agg[day_str]["ingreso_sum"] += vals.get("ingreso", 0)
|
|
daily_agg[day_str]["ingreso_lxp"] += vals.get("leads_lake", 0) * ppl
|
|
daily_agg[day_str]["leads"] += int(vals.get("leads", 0))
|
|
daily_agg[day_str]["leads_lake"] += int(vals.get("leads_lake", 0))
|
|
|
|
print(f" > Dias agregados: {sorted(daily_agg.keys())}")
|
|
|
|
# Redondear
|
|
for d in daily_agg:
|
|
daily_agg[d] = {k: round(v, 2) if isinstance(v, float) else v for k, v in daily_agg[d].items()}
|
|
|
|
print("Creando/obteniendo registro GAMes de mayo 2026...")
|
|
games_rid = at.get_or_create_games_record(MES, ANIO)
|
|
print(f" > Record ID: {games_rid}")
|
|
|
|
print("Guardando MetricasDiarias en GAMes...")
|
|
at.update_games_metricas(games_rid, json.dumps(daily_agg, ensure_ascii=False))
|
|
|
|
print(f"OK Backfill GAMes completado: {len(daily_agg)} dias guardados.")
|