Fix month-change MetricasDiarias overwrite bug, add per-date Ads metrics helpers
On month change, run.py redirected the write to the previous month's GACampaignMes record but built the JSON from the new month's near-empty record, overwriting the previous month's full daily history with just the redirected day. Now it merges with the previous month's real MetricasDiarias (via get_metricas_diarias_prev_month) before writing. Also add get_metrics_for_date() and get_daily_metrics_for_month() to GoogleAdsClient for reconstructing historical daily cost/conversions, needed by the backfill scripts.
This commit is contained in:
parent
ea201ef565
commit
31193c57ee
@ -100,6 +100,70 @@ class GoogleAdsClient:
|
||||
print(f" ❌ Error obteniendo métricas de hoy: {e}")
|
||||
return result
|
||||
|
||||
def get_metrics_for_date(self, date_str: str) -> dict:
|
||||
"""
|
||||
Devuelve métricas de una fecha concreta ('YYYY-MM-DD') para TODAS las
|
||||
campañas en una sola query. Retorna dict {campaign_id: {conversions, cost}}.
|
||||
"""
|
||||
ga_service = self.client.get_service("GoogleAdsService")
|
||||
query = f"""
|
||||
SELECT
|
||||
campaign.id,
|
||||
metrics.conversions,
|
||||
metrics.cost_micros
|
||||
FROM campaign
|
||||
WHERE campaign.status != 'REMOVED'
|
||||
AND segments.date = '{date_str}'
|
||||
"""
|
||||
result = {}
|
||||
try:
|
||||
response = ga_service.search(customer_id=self.customer_id, query=query)
|
||||
for row in response:
|
||||
cid = str(row.campaign.id)
|
||||
result[cid] = {
|
||||
"conversions": row.metrics.conversions,
|
||||
"cost": row.metrics.cost_micros / 1_000_000,
|
||||
}
|
||||
except GoogleAdsException as e:
|
||||
print(f" ❌ Error obteniendo métricas del {date_str}: {e}")
|
||||
return result
|
||||
|
||||
def get_daily_metrics_for_month(self, year: int, month: int) -> dict:
|
||||
"""
|
||||
Devuelve coste y conversiones diarias de todas las campañas para un mes
|
||||
completo. Retorna dict {date_str ('YYYY-MM-DD'): {campaign_id: {cost, conversions}}}.
|
||||
"""
|
||||
start = f"{year}-{month:02d}-01"
|
||||
if month == 12:
|
||||
end = f"{year + 1}-01-01"
|
||||
else:
|
||||
end = f"{year}-{month + 1:02d}-01"
|
||||
ga_service = self.client.get_service("GoogleAdsService")
|
||||
query = f"""
|
||||
SELECT
|
||||
campaign.id,
|
||||
segments.date,
|
||||
metrics.conversions,
|
||||
metrics.cost_micros
|
||||
FROM campaign
|
||||
WHERE campaign.status != 'REMOVED'
|
||||
AND segments.date >= '{start}'
|
||||
AND segments.date < '{end}'
|
||||
"""
|
||||
result: dict = {}
|
||||
try:
|
||||
response = ga_service.search(customer_id=self.customer_id, query=query)
|
||||
for row in response:
|
||||
date_str = row.segments.date
|
||||
cid = str(row.campaign.id)
|
||||
result.setdefault(date_str, {})[cid] = {
|
||||
"conversions": row.metrics.conversions,
|
||||
"cost": row.metrics.cost_micros / 1_000_000,
|
||||
}
|
||||
except GoogleAdsException as e:
|
||||
print(f" ❌ Error obteniendo métricas diarias del mes: {e}")
|
||||
return result
|
||||
|
||||
def get_daily_conversions_for_month(self, year: int, month: int) -> dict:
|
||||
"""
|
||||
Devuelve conversiones diarias de todas las campañas para un mes completo.
|
||||
|
||||
14
run.py
14
run.py
@ -398,8 +398,13 @@ def run():
|
||||
if metricas_updates:
|
||||
print(f"→ Actualizando MetricasDiarias ({len(metricas_updates)} registros)...")
|
||||
if cambio_mes:
|
||||
# Ayer pertenece al mes anterior: redirigir escritura al GACampaignMes correcto
|
||||
# Ayer pertenece al mes anterior: redirigir escritura al GACampaignMes correcto.
|
||||
# El "campaign" en memoria es el del mes nuevo (recién creado, MetricasDiarias
|
||||
# casi vacío) — hay que hacer merge con el MetricasDiarias REAL del mes anterior
|
||||
# antes de escribir, o se pierde el resto de días ya acumulados (bug que borró
|
||||
# el histórico de junio salvo el día 30 al hacer un overwrite directo).
|
||||
prev_map = at.get_gcm_id_map_for_month(ayer.month, ayer.year)
|
||||
prev_metricas = at.get_metricas_diarias_prev_month()
|
||||
redirected = []
|
||||
omitidos = []
|
||||
for u in metricas_updates:
|
||||
@ -409,7 +414,14 @@ def run():
|
||||
None,
|
||||
)
|
||||
if gid and gid in prev_map:
|
||||
try:
|
||||
existing_md = json.loads(prev_metricas.get(gid, {}).get("metricas") or "{}")
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
existing_md = {}
|
||||
nuevo_dia_md = json.loads(u["metricas_json"])
|
||||
existing_md.update(nuevo_dia_md)
|
||||
u["airtable_id"] = prev_map[gid]
|
||||
u["metricas_json"] = json.dumps(existing_md, ensure_ascii=False)
|
||||
redirected.append(u)
|
||||
else:
|
||||
omitidos.append(gid)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user