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}")
|
print(f" ❌ Error obteniendo métricas de hoy: {e}")
|
||||||
return result
|
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:
|
def get_daily_conversions_for_month(self, year: int, month: int) -> dict:
|
||||||
"""
|
"""
|
||||||
Devuelve conversiones diarias de todas las campañas para un mes completo.
|
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:
|
if metricas_updates:
|
||||||
print(f"→ Actualizando MetricasDiarias ({len(metricas_updates)} registros)...")
|
print(f"→ Actualizando MetricasDiarias ({len(metricas_updates)} registros)...")
|
||||||
if cambio_mes:
|
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_map = at.get_gcm_id_map_for_month(ayer.month, ayer.year)
|
||||||
|
prev_metricas = at.get_metricas_diarias_prev_month()
|
||||||
redirected = []
|
redirected = []
|
||||||
omitidos = []
|
omitidos = []
|
||||||
for u in metricas_updates:
|
for u in metricas_updates:
|
||||||
@ -409,7 +414,14 @@ def run():
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
if gid and gid in prev_map:
|
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["airtable_id"] = prev_map[gid]
|
||||||
|
u["metricas_json"] = json.dumps(existing_md, ensure_ascii=False)
|
||||||
redirected.append(u)
|
redirected.append(u)
|
||||||
else:
|
else:
|
||||||
omitidos.append(gid)
|
omitidos.append(gid)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user