Fix tracking discrepancy direction, improve daily metrics table, increase max_tokens
Some checks failed
Weekly Strategic Report / run (push) Has been cancelled

- analyzer.py: use abs() for tracking discrepancy so both directions alert
- slack_reporter.py: daily table adds L.AT/L.GA/Coste/€.AT/€.GA columns; margin uses Google Ads conversions × PPL; split monthly rankings into separate blocks; fix stale margen field
- run.py: leads_grupo always uses Google Ads conversions; tracking alert shows direction (over/under attribution)
- agent.py: increase decide() max_tokens 700→750 to fix JSON truncation for long campaign names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jose Manuel 2026-06-13 20:27:31 +02:00
parent a024508062
commit d23cb6b9c2
4 changed files with 50 additions and 28 deletions

View File

@ -228,7 +228,7 @@ def weekly_strategic_analysis(games_md_this: dict, games_md_prev_week: dict,
def decide(analysis: dict) -> dict:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=700,
max_tokens=750,
system=SYSTEM_PROMPT,
messages=[{
"role": "user",

View File

@ -35,7 +35,7 @@ def analyze(campaign_config: dict, leads_entregados: int, ads_metrics: dict) ->
else:
urgencia = "EN_RITMO"
# Discrepancia entre leads Airtable (ConvLeadsLakeMes) y conversiones Google
# Discrepancia en ambas direcciones: Google > Airtable puede indicar conversiones falsas
conv_leads_lake_mes = campaign_config.get("conv_leads_lake_mes", leads_entregados)
discrepancia = abs(conversiones_google - conv_leads_lake_mes)

11
run.py
View File

@ -220,10 +220,8 @@ def run():
if is_pmx_with_leadform:
leads_grupo = int(metrics.get("conversions", 0)) + leadform_conv_by_course.get(course_num, 0)
elif is_pmx_with_companion:
leads_grupo = int(metrics.get("conversions", 0))
else:
leads_grupo = leads
leads_grupo = int(metrics.get("conversions", 0))
analysis = analyze(campaign, leads_grupo, metrics)
decision = decide(analysis)
@ -296,8 +294,11 @@ def run():
f"Rentable: {'' if analysis['rentable'] else ''}")
if analysis["alerta_tracking"]:
print(f" 🚨 ALERTA TRACKING: {analysis['discrepancia_tracking']} leads de diferencia "
f"entre Airtable ({campaign['conv_leads_lake_mes']}) y Google Ads ({int(analysis['conversiones_google'])})")
at_leads = campaign['conv_leads_lake_mes']
ga_leads = int(analysis['conversiones_google'])
direction = "Airtable > Google (sobre-atribución?)" if at_leads > ga_leads else "Google > Airtable (conversiones falsas?)"
print(f" 🚨 ALERTA TRACKING: {analysis['discrepancia_tracking']:.0f} leads de diferencia "
f"— Airtable {at_leads} vs Google Ads {ga_leads}{direction}")
print(f" Decisión: {accion_icono} {decision['accion']} "
f"(confianza: {decision['confianza']*100:.0f}%)")

View File

@ -185,35 +185,56 @@ def build_and_send(collected: list, dry_run: bool, prev_month_metricas: dict = N
except ValueError:
continue
if d not in daily_totals:
daily_totals[d] = {"coste": 0.0, "ingreso_sum": 0.0}
daily_totals[d]["coste"] += vals.get("coste", 0)
daily_totals[d]["ingreso_sum"] += vals.get("ingreso", 0)
daily_totals[d] = {"coste": 0.0, "ing_gads": 0.0, "ing_at": 0.0, "leads_gads": 0, "leads_at": 0}
daily_totals[d]["coste"] += vals.get("coste", 0)
daily_totals[d]["ing_gads"] += vals.get("ingreso", 0) # conv_hoy × PPL
daily_totals[d]["ing_at"] += vals.get("leads_lake", 0) * ppl # leads_lake × PPL
daily_totals[d]["leads_gads"] += int(vals.get("leads", 0))
daily_totals[d]["leads_at"] += int(vals.get("leads_lake", 0))
def _eur(v: float) -> str:
return f"{v:,.0f}".replace(",", ".")
def _marg(v: float) -> str:
return ("+" if v >= 0 else "") + f"{v:,.0f}".replace(",", ".")
def _pct(v: float) -> str:
return ("+" if v >= 0 else "") + f"{v:.1f}%"
margin_table_block = None
if daily_totals and not primer_dia_mes:
rows = ["Día Margen € %"]
total_coste = total_ing = 0.0
hdr = f"{'Día':>3} {'L.AT':>5} {'L.GA':>5} {'Coste':>7} {'€.AT':>7} {'€.GA':>7} {'Margen':>9} {'%':>7}"
sep = "" * len(hdr)
rows = [hdr, sep]
tot = {"coste": 0.0, "ing_gads": 0.0, "ing_at": 0.0, "leads_gads": 0, "leads_at": 0}
for d in sorted(daily_totals):
coste = daily_totals[d]["coste"]
ing_sum = daily_totals[d]["ingreso_sum"]
margen = ing_sum - coste
pct = round(margen / ing_sum * 100, 1) if ing_sum > 0 else 0.0
total_coste += coste
total_ing += ing_sum
s_eur = ("+" if margen >= 0 else "") + f"{margen:,.0f}".replace(",", ".")
s_pct = ("+" if pct >= 0 else "") + f"{pct:.1f}%"
rows.append(f"{d:02d} {s_eur:>9} {s_pct:>7}")
total_margen = total_ing - total_coste
total_pct = round(total_margen / total_ing * 100, 1) if total_ing > 0 else 0.0
s_tot_eur = ("+" if total_margen >= 0 else "") + f"{total_margen:,.0f}".replace(",", ".")
s_tot_pct = ("+" if total_pct >= 0 else "") + f"{total_pct:.1f}%"
rows.append("" * 24)
rows.append(f"TOT {s_tot_eur:>9} {s_tot_pct:>7}")
v = daily_totals[d]
ing = v["ing_gads"] # margen: conv Google Ads × PPL
marg = ing - v["coste"]
pct_v = round(marg / ing * 100, 1) if ing > 0 else 0.0
for k in tot:
tot[k] += v[k]
rows.append(
f"{d:02d} {v['leads_at']:>5} {v['leads_gads']:>5}"
f" {_eur(v['coste']):>7}"
f" {_eur(v['ing_at']):>7} {_eur(v['ing_gads']):>7}"
f" {_marg(marg):>9} {_pct(pct_v):>7}"
)
tot_ing = tot["ing_gads"]
tot_marg = tot_ing - tot["coste"]
tot_pct = round(tot_marg / tot_ing * 100, 1) if tot_ing > 0 else 0.0
rows.append(sep)
rows.append(
f"{'TOT':>3} {tot['leads_at']:>5} {tot['leads_gads']:>5}"
f" {_eur(tot['coste']):>7}"
f" {_eur(tot['ing_at']):>7} {_eur(tot['ing_gads']):>7}"
f" {_marg(tot_marg):>9} {_pct(tot_pct):>7}"
)
margin_table_block = {
"type": "section",
"text": {
"type": "mrkdwn",
"text": _trunc(f"📅 *MÁRGENES POR DÍA — {MESES_ES[now.month].upper()}*\n```\n" + "\n".join(rows) + "\n```"),
"text": _trunc(f"📅 *MÉTRICAS POR DÍA — {MESES_ES[now.month].upper()}* _(L.AT=leads Airtable · L.GA=conv Google Ads · €.AT=fact×PPL Airtable · €.GA=fact×PPL Google Ads)_\n```\n" + "\n".join(rows) + "\n```"),
},
}