Cómo funciona HOY — pantalla por pantalla
El sistema ya es super poderoso (CPA, objetivo×fuente, cliente paga X → partner Y → Relo X−Y, budgets total/none/por-segmento, tiered, per-CID). El problema NO es falta de poder — es que el poder está regado, invisible, inconsistente y en parte es teatro. Esto es la realidad exacta, sin adornos, para aterrizar los flows.
! El patrón — 4 anti-patrones que se repiten en TODO
Regado
El mismo número se edita en N pantallas: el cap en 6 lugares, la tarifa en 4+, la atribución en 3, la pausa en 5 mecanismos. Ninguno se cruza ni muestra los otros.
Invisible
La precedencia (qué tarifa gana), la razón de pausa, el warning de sobre-asignación y la salud del pool — todo se calcula en el backend pero no se muestra en ninguna pantalla.
Inconsistente
Unos paths audit-logean, otros no. El mismo cap se escribe por 2 rutas con checks distintos. "Over budget" significa 2 cosas. El reset mid-month se hace con SQL crudo — no hay UI.
En parte teatro
El wizard de campaña finge configurar (pasos 2+3 no se envían). La página oficial de reglas no deja editar ("llega en chunk 2B" — nunca llegó). Botones muertos. Features que dicen "coming soon" pero ya existen en el tab de al lado.
1 Planner /v2/c/:slug/planner
Tabla densa por segmento: Client budget · Relo earns · Partner pays · Relo margin · Health. Expandes → tabla por-partner (rate + Payment cap) + tiered deals + Campaign sprints (per-CID). Hero con 4 tiles (budget/payout/margin/status). Botones: Save · Copy last month · Suggest allocation · Approve & notify · Target margin (87%).
- No tiene control de pausa ni de reset mid-month aquí — esos viven en OTRA pantalla. Asignar y pausar están partidos.
- "Partner pays" es un blend read-only ponderado por volumen — no se puede editar en la fila, y no cuadra con un promedio ingenuo de las tarifas de abajo.
- Los Campaign Sprints escriben al DB al instante (se saltan el botón Save) — todo lo demás es "draft hasta Save", esto no. Modelo mental roto.
- Target margin (87%) es solo localStorage — no se guarda en el server; cambias de compu y se resetea.
- El Save sobre-escribe la PSC en su lugar (key
partner_id+segment_code, sin fecha) — diverge de la precedencia documentada; no crea fila nueva con vigencia. - MonthPicker solo prev/next — saltar de mes lejano = muchos clics.
2 Budgets / caps partner_segment_budgets.budget_amount
- Control Panel → +Budget drawer (el principal) —
POST /segment-budgets - Planner → Save — batch upsert directo, bypasea el handler del drawer
- Relo Copilot (AI) — mismo write path, otra puerta
- Endpoint bulk huérfano — existe, nadie lo llama
- Onboarding — siembra 12 meses de golpe
- 6º cap distinto:
match_rules budget_override(sprint per-CID) — se aplica ANTES del cap del segmento, y el Control Panel nunca lo consulta → muestra un cap que no es el que el engine enforza.
- El warning de sobre-asignación (Σ caps de partners vs pool de Samsung) se calcula en el backend, pero el drawer lo ignora y el Planner ni lo corre.
- Unos paths audit-logean, otros no (el Planner no deja rastro; el drawer sí).
- El reset mid-month (
budget_start_from+locked_commission) — NO tiene write path en el código. Se hace con SQL crudo. Todo lo LEE bien, nada lo ESCRIBE por UI. - Sin enforcement pool↔caps: son dos números independientes en dos pantallas, reconciliados solo por un warning string que la UI tira + una pausa-cron después del hecho.
3 Pausas paused_at · auto_pause_at_100 · cascade
- Per-partner-per-segmento (el único con UI: botón Pause/Resume)
- Partner completo (todos sus segmentos) — sin botón en la UI
- Auto-pausa al 100% (
auto_pause_at_100, cron) - Cascada (pool de Samsung agotado → pausa a TODOS, cron)
- Global por segmento del cliente — sin caller en la UI
- La cascada y la global taggean idéntico (
inherited_pause_from='client') → indistinguibles en la data. - La UI no renderiza razón ni origen de pausa → una cascada-pausa y una pausa manual se ven idénticas en pantalla. No sabes por qué está pausado.
/api/clients/:id/budget-health(la única salud del pool) tiene cero callers — la salud del pool es invisible.
4 Lanzar campaña /v2/c/:slug/campaigns → Launch
Wizard 5 pasos: Type → Tracking → Rules → Partners → Review.
- Paso 2 (Tracking) es cosmético — la fuente que eliges nunca se envía.
- Paso 3 (Reglas/pricing) es decorativo — el pricing que eliges no se lee; el review del paso 5 hardcodea texto falso ("CPA per sale · $50 fixed") sin importar qué clicaste.
- Solo cablea el PRIMER segmento — una campaña multi-segmento configura de menos todo lo demás.
- Non-atómico — 5 pasos con try/catch, sin rollback, 207 parcial: puede dejar un partner vinculado sin tarifa o sin budget.
5 Reglas / overrides match_rules · el corazón del poder
- RateOverrideEditorBody (el más completo — flat + tiered + preview de impacto)
- CampaignMmpRateEditor (otro editor, flat-only, sin tiered)
- Editores natural-language (atribución/reclassify por campaña)
- Drawers del Control Panel (Budget/Pause/Rate)
- Ninguno se cruza — no ves las reglas del otro para el mismo (partner, segmento)
- REGRESIÓN 🔥: el viejo
RulesLibrarySÍ tenía CRUD completo + un tester que hacía visible la precedencia (segment→partner→reclassify→filter→rate→budget→commission). Se borró (5dfab4d) y el nuevo RulesEngine lo dejó READ-ONLY con un placeholder "chunk 2B" que nunca llegó. Tú hiciste reglas ahí — el rediseño lo empeoró. - La precedencia es invisible en TODA pantalla (frozen → tiered → flat CID vs partner-wide → PSC → default). Nadie te muestra la cadena resuelta.
- RulesEngine ordena por
priority— que el engine ni usa para estas reglas (usa tiered-vs-flat, especificidad de CID, yeffective_from). - 3 sistemas de reglas distintos (match_rules · Zen RuleBuilder · tablas single-purpose) como tabs hermanos, sin señal de cuál gobierna.
- El tab "Rates and caps" dice "Coming soon" — pero el tab de al lado (Partners) ya deja crear ese override hoy.
6 Onboarding /v2/clients/new
Wizard 6 pasos: Identity · Segments · Partners · Attribution · Commissions/Budgets · Review → "Create everything".
- La pantalla final es un recibo estático ("✓ Client created" + contadores de filas). Te dice qué se insertó, nunca si el cliente está vivo.
- Cero verificación de flujo de datos para clientes MMP (la mayoría) — solo los pixel tienen un "Verify installation". Los 2 botones de salida son navegación pura, no gated por salud.
- El checklist post-onboarding chequea presencia de config, no flujo — sale "Onboarding complete" en verde con el dashboard vacío para siempre.
7 Medir Home · ClientOverview · PartnerProfile
ClientOverview = scroll único (sin tabs): KPIs → tabla de partners (validado/gross) → Control Panel (Segment/Campaign/Partner) → Performance → Reconciliation waterfall (Attributed → −Paused → −No campaign → −Segment disabled → Billable) → Money flow.
- Para UN partner en UN mes, el admin puede ver 6 números distintos: all-clients gated (KPI) · all-clients gross-raw (subtítulo) · este-cliente gated (tab Deals) · este-cliente gated+gross (Overview) · por-segmento (Control Panel) · congelado posiblemente viejo (tab Pagos).
- 3 ejes cruzados (scope × gated/gross × live/frozen) y ninguno se cruza para explicar por qué difieren.
- El loop mensual está partido entre zonas de nav: Pagos es solo GLOBAL (ni se linkea desde el cliente), Planner enterrado en "More" → sin botón "cerrar el mes".
- 3 secciones de código muerto en ClientOverview (tablas viejas nunca borradas).