Update campaign status in both tables from per-campaign Google Ads metrics

- get_active_gacampaignmes() now returns campaign_at_id (Google Ads Campaigns record ID)
- New batch_update_status() updates Status in GACampaignMes and Google Ads Campaigns
- run.py first pass collects status from get_campaign_metrics() and batch-updates
  both tables at end of pass, ensuring fresh status after each run

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jose Manuel 2026-04-21 13:05:42 +02:00
parent f6f897adeb
commit d9a8e7ee0d
2 changed files with 46 additions and 7 deletions

View File

@ -272,13 +272,15 @@ class AirtableClient:
mes_num = str(now.month) mes_num = str(now.month)
anio_str = str(now.year) anio_str = str(now.year)
# Mapping at_record_id → google_campaign_id # Mapping at_record_id → google_campaign_id y gid → at_record_id
campaigns_records = self.campaigns.all(fields=["CampaignID"]) campaigns_records = self.campaigns.all(fields=["CampaignID"])
at_id_to_gid = { at_id_to_gid = {}
r["id"]: str(r["fields"].get("CampaignID", "")).strip() gid_to_at_id = {}
for r in campaigns_records for r in campaigns_records:
if r["fields"].get("CampaignID") gid = str(r["fields"].get("CampaignID", "")).strip()
} if gid:
at_id_to_gid[r["id"]] = gid
gid_to_at_id[gid] = r["id"]
formula = f"AND({{Mes}}='{mes_num}',{{Año}}='{anio_str}')" formula = f"AND({{Mes}}='{mes_num}',{{Año}}='{anio_str}')"
records = self.gacampaignmes.all(formula=formula) records = self.gacampaignmes.all(formula=formula)
@ -295,7 +297,8 @@ class AirtableClient:
name = name_list[0] if name_list else "Sin nombre" name = name_list[0] if name_list else "Sin nombre"
result.append({ result.append({
"airtable_id": r["id"], "airtable_id": r["id"], # GACampaignMes record ID
"campaign_at_id": gid_to_at_id.get(gid, ""), # Google Ads Campaigns record ID
"curso": name, "curso": name,
"cursoid_text": "", "cursoid_text": "",
"google_campaign_id": gid, "google_campaign_id": gid,
@ -306,6 +309,28 @@ class AirtableClient:
}) })
return result return result
def batch_update_status(self, updates: list[tuple[str, str, str]]) -> None:
"""
Actualiza en lote el campo Status en GACampaignMes y Google Ads Campaigns.
updates: lista de (gcm_record_id, campaign_at_id, google_status)
google_status: 'ENABLED' | 'PAUSED'
"""
STATUS_MAP = {"ENABLED": "Activa", "PAUSED": "Pausada"}
gcm_batch = []
cat_batch = []
for gcm_id, cat_id, google_status in updates:
at_status = STATUS_MAP.get(google_status, "Pausada")
if gcm_id:
gcm_batch.append({"id": gcm_id, "fields": {"Status": at_status}})
if cat_id:
cat_batch.append({"id": cat_id, "fields": {"Status": at_status}})
for i in range(0, len(gcm_batch), 10):
self.gacampaignmes.batch_update(gcm_batch[i:i+10])
for i in range(0, len(cat_batch), 10):
self.campaigns.batch_update(cat_batch[i:i+10])
def get_leads_this_month_gads(self, campaign_id: str) -> tuple[int, list[str]]: def get_leads_this_month_gads(self, campaign_id: str) -> tuple[int, list[str]]:
""" """
Leads del mes actual para una campaña de Google Ads. Leads del mes actual para una campaña de Google Ads.

14
run.py
View File

@ -121,6 +121,7 @@ def run():
# === PRIMERA PASADA: recopilar datos de todas las campañas === # === PRIMERA PASADA: recopilar datos de todas las campañas ===
collected = [] collected = []
skipped = [] skipped = []
status_updates = [] # (gcm_id, campaign_at_id, google_status) para batch update
for campaign in campaigns: for campaign in campaigns:
cid = campaign["google_campaign_id"] cid = campaign["google_campaign_id"]
@ -133,6 +134,15 @@ def run():
skipped.append(f"[{cid}] {campaign['curso']}") skipped.append(f"[{cid}] {campaign['curso']}")
continue continue
# Recopilar status para actualizar ambas tablas al final del pase
google_status = metrics.get("status", "")
if google_status:
status_updates.append((
campaign["airtable_id"],
campaign.get("campaign_at_id", ""),
google_status,
))
analysis = analyze(campaign, leads, metrics) analysis = analyze(campaign, leads, metrics)
decision = decide(analysis) decision = decide(analysis)
@ -144,6 +154,10 @@ def run():
"decision": decision, "decision": decision,
}) })
# Actualizar status en GACampaignMes y Google Ads Campaigns
if status_updates:
at.batch_update_status(status_updates)
if skipped: if skipped:
print(f" ⚠️ {len(skipped)} campañas sin métricas omitidas:") print(f" ⚠️ {len(skipped)} campañas sin métricas omitidas:")
for s in skipped: for s in skipped: