Add monthly margin breakdown by vertical to Slack summary table

- Compute monthly_verticals in run.py and send_slack_report.py using per-vertical CPL targets
- Display vertical breakdown (spend, leads, CPL, target, margin) inside the monthly table block
- Add alarmas vertical (CPL target 8€) to Baserow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jose Manuel 2026-06-13 23:14:32 +02:00
parent ac7a0a9738
commit ff3aafe82a
3 changed files with 26 additions and 0 deletions

6
run.py
View File

@ -120,6 +120,7 @@ def run():
print(f"→ Fetching monthly daily totals for {config.META_CAMPAIGN_PREFIX}...") print(f"→ Fetching monthly daily totals for {config.META_CAMPAIGN_PREFIX}...")
daily_rows = meta.get_monthly_daily_totals() daily_rows = meta.get_monthly_daily_totals()
_daily: dict = {} _daily: dict = {}
monthly_verticals: dict = {}
for row in daily_rows: for row in daily_rows:
v = _extract_vertical(row["campaign_name"]) v = _extract_vertical(row["campaign_name"])
target = vertical_cpls.get(v, config.META_TARGET_CPL) target = vertical_cpls.get(v, config.META_TARGET_CPL)
@ -128,6 +129,10 @@ def run():
d["spend"] += row["spend"] d["spend"] += row["spend"]
d["leads"] += row["leads"] d["leads"] += row["leads"]
d["margin"] += margin d["margin"] += margin
mv = monthly_verticals.setdefault(v, {"spend": 0.0, "leads": 0, "margin": 0.0, "target_cpl": target})
mv["spend"] += row["spend"]
mv["leads"] += row["leads"]
mv["margin"] += margin
daily_totals = [ daily_totals = [
{ {
"date": date, "date": date,
@ -373,6 +378,7 @@ def run():
mode="DRY_RUN" if config.DRY_RUN else "PRODUCTION", mode="DRY_RUN" if config.DRY_RUN else "PRODUCTION",
verticals=verticals, verticals=verticals,
campaign_details=campaign_details, campaign_details=campaign_details,
monthly_verticals=monthly_verticals,
) )
except Exception as e: except Exception as e:
print(f" Warning: Slack notification failed: {e}") print(f" Warning: Slack notification failed: {e}")

View File

@ -40,6 +40,7 @@ def main():
print("Obteniendo datos mensuales de Meta...") print("Obteniendo datos mensuales de Meta...")
daily_rows = meta.get_monthly_daily_totals() daily_rows = meta.get_monthly_daily_totals()
_daily: dict = {} _daily: dict = {}
monthly_verticals: dict = {}
for row in daily_rows: for row in daily_rows:
v = _extract_vertical(row["campaign_name"]) v = _extract_vertical(row["campaign_name"])
target = vertical_cpls.get(v, config.META_TARGET_CPL) target = vertical_cpls.get(v, config.META_TARGET_CPL)
@ -51,6 +52,10 @@ def main():
d["spend"] += row["spend"] d["spend"] += row["spend"]
d["leads"] += row["leads"] d["leads"] += row["leads"]
d["margin"] += margin d["margin"] += margin
mv = monthly_verticals.setdefault(v, {"spend": 0.0, "leads": 0, "margin": 0.0, "target_cpl": target})
mv["spend"] += row["spend"]
mv["leads"] += row["leads"]
mv["margin"] += margin
daily_totals = [ daily_totals = [
{ {
"date": date, "date": date,
@ -163,6 +168,7 @@ def main():
mode="DRY_RUN", mode="DRY_RUN",
verticals=verticals, verticals=verticals,
campaign_details=campaign_details, campaign_details=campaign_details,
monthly_verticals=monthly_verticals,
) )
if ts: if ts:
print(f" ✓ Mensaje enviado (ts={ts})") print(f" ✓ Mensaje enviado (ts={ts})")

View File

@ -153,6 +153,7 @@ def send_daily_report(
mode: str = "DRY_RUN", mode: str = "DRY_RUN",
verticals: dict = None, verticals: dict = None,
campaign_details: dict = None, campaign_details: dict = None,
monthly_verticals: dict = None,
) -> str | None: ) -> str | None:
"""Envía el informe diario consolidado. Devuelve el ts del mensaje.""" """Envía el informe diario consolidado. Devuelve el ts del mensaje."""
now = datetime.now() now = datetime.now()
@ -192,6 +193,19 @@ def send_daily_report(
lines.append( lines.append(
f"{'TOTAL':<5} {total_spend:>6.0f}{int(total_leads):>5} {total_cpl:>6.2f}{m_tot_sign:>8}" f"{'TOTAL':<5} {total_spend:>6.0f}{int(total_leads):>5} {total_cpl:>6.2f}{m_tot_sign:>8}"
) )
# Margen mensual por vertical
if monthly_verticals:
mv_lines = ["", f"{'Vertical':<16} {'Gasto':>7} {'Leads':>5} {'CPL':>7} {'Obj':>5} {'Margen':>8}"]
mv_lines.append("" * 54)
for v, mv in sorted(monthly_verticals.items(), key=lambda x: -x[1]["margin"]):
v_cpl = round(mv["spend"] / mv["leads"], 2) if mv["leads"] > 0 else 0.0
m_sign = f"+{mv['margin']:.0f}" if mv["margin"] >= 0 else f"{mv['margin']:.0f}"
obj = mv.get("target_cpl", 0)
mv_lines.append(
f"{v:<16} {mv['spend']:>6.0f}{mv['leads']:>5} {v_cpl:>6.2f}{obj:>4.1f}{m_sign:>8}"
)
lines += mv_lines
blocks.append({ blocks.append({
"type": "section", "type": "section",
"text": { "text": {