Anomalías detectadas
| Empresa | Tipo | Impacto | Estado |
|---|---|---|---|
| AlimentaSano SA | Doble suscripción | 2 × 290 € = 580 €/mes | Crítico |
| BioWellness SL | Disputa Stripe | 290 € en riesgo | Urgente |
| 6 clientes | Pago fallido | 1.450 € bloqueados | Recuperable |
| 14 checkouts | Abandonados | ~2.030 € estimados | No confirmado |
Distribución de ingresos netos (30d)
AlimentaSano SA — Doble suscripción (checkout duplicado)
El cliente inició el checkout dos veces (probablemente doble clic o timeout de red) y ambas sesiones completaron el pago. No hay lógica idempotente en el checkout: no se verifica si la empresa ya tiene suscripción activa antes de crear una nueva. Resultado: se les cobra 580 €/mes por 20 seats cuando solo necesitan 10.
sub_abc123 + sub_def456 · Plan Pro 10-seats · 2 × 290 €/mesBioWellness SL — Disputa Stripe por seats no asignables
Compraron un plan de 10 seats pero el portal no les permitió asignar usuarios manualmente. El botón "Gestionar Asientos" aparece en la UI pero apunta a una ruta no implementada (/settings/seats devuelve 404). Cliente escala a disputa alegando publicidad engañosa. Tiene fundamento: la web promete gestión de asientos, el código no la tiene.
Chargeback 290 € · Motivo: "servicio no prestado" · Deadline: 2026-06-246 clientes con pago fallido — Tarjetas caducadas
Representan 1.450 € en ingresos diferidos. Stripe Dunning está activado pero los emails de actualización de tarjeta tienen 28% de apertura. Se puede recuperar aprox. 60-70% con una secuencia dedicada. Ninguno ha solicitado cancelación activamente.
retry_schedule: 3/5/7 días · 4 sin respuesta · 2 en proceso| Feature | Lo que dice la web / ventas | Lo que hace el código | Veredicto |
|---|---|---|---|
| Seats por empresa | "Paga por usuario, controla quién accede" | canAddUser() → siempre true | NO implementado |
| Gestión de asientos | "Panel de gestión de equipo incluido" | /settings/seats → 404 · sin ruta | NO existe |
| Cantidad en checkout | "Elige el número de usuarios al contratar" | quantity se pasa a Stripe · se cobra correctamente | OK (cobra bien) |
| Validación pre-checkout | (implícito: una suscripción por empresa) | // TODO: sin validación de duplicado | Gap — duplicados posibles |
| Enterprise "seats ilimitados" | Pitch de ventas: "ilimitados en plan Enterprise" | No hay plan Enterprise en Stripe Products | Solo en pitch, no en código |
Evidencia de código — checkout.js (commit 4f2a1b3)
Evidencia de código — entitlement.js (commit 4f2a1b3)
🔴 AlimentaSano SA — REEMBOLSO PARCIAL
- Cancelar sub_def456 (la segunda suscripción) inmediatamente desde Stripe Dashboard.
- Emitir reembolso proporcional por los días cobrados de la suscripción duplicada (~145 € si se detectó a mitad de ciclo).
- Email proactivo disculpándose y explicando el error técnico antes de que el cliente lo note.
- Registrar como bug de checkout — no como decisión de negocio.
🟡 BioWellness SL — REFUND + RESPUESTA DISPUTA
- No luchar la disputa: el cliente tiene razón técnica (la feature prometida no existe).
- Emitir reembolso voluntario de 290 € ANTES del deadline (2026-06-24) para evitar pérdida del caso y penalización Stripe.
- Respuesta a disputa: adjuntar evidencia del reembolso voluntario y plan de implementación.
- Ofrecer acceso gratuito 3 meses cuando la feature esté disponible.
🟢 6 Pagos fallidos — RECUPERAR
- Activar campaña manual de recuperación (email personalizado, no solo Stripe Dunning).
- Llamada de CS a los 2 que llevan más de 5 días sin respuesta.
- Estimación de recuperación: 870–1.015 € (60-70% de 1.450 €).
🟠 Checkouts incompletos — INVESTIGAR
- 14 sesiones incompletas requieren análisis de Stripe Funnel antes de actuar.
- Distinguir: precio (abandono real) vs. bug UX vs. ya tenían cuenta.
- No asumir que los 14 son revenue perdido — clasificar primero.
| # | Gap | Archivo / Ruta | Prioridad | Impacto en ingresos |
|---|---|---|---|---|
| GAP-01 | Idempotencia en checkout — verificar si la org ya tiene suscripción activa antes de crear sesión nueva | checkout.js · pre-session hook | P0 — Urgente | Elimina duplicados · evita fraude involuntario |
| GAP-02 | Seat enforcement real — canAddUser() debe consultar el conteo de seats activos vs. quota del plan | entitlement.js · canAddUser() | P0 — Antes de vender más | Sin esto, todos los planes son "ilimitados" de facto |
| GAP-03 | Panel /settings/seats — UI para asignar, eliminar y ver usuarios del equipo | Ruta nueva · settings/seats.tsx | P1 — Esta sprint | Bloquea disputas como BioWellness; mejora retención de equipos |
| GAP-04 | Plan Enterprise en Stripe Products — crear el producto/precio y eliminar del pitch hasta que exista | Stripe Dashboard · pricing-page.tsx | P1 | Ventas cerradas en Enterprise ahora no tienen respaldo técnico |
| GAP-05 | Retries de pago mejorados — email personalizado + smart dunning con link directo a update-card | billing/dunning.ts · email-templates/ | P2 | Recupera ~870 € inmediato; mejora LTV |