Diagnóstico de Facturación e Ingresos

NutriTrack Pro SaaS — Investigación con evidencia de código y datos Stripe
● Live data 2 anomalías críticas snapshot: 2026-06-17T09:00:00Z
📊
SNAPSHOT — Estado de Facturación Stripe · 2026-06-17 09:00 UTC
MRR Actual
12.340 €
47 suscripciones activas
Cobros 30d
8.920 €
38 pagos completados
Pagos fallidos
1.450 €
6 intentos · tarjetas caducadas
Reembolsos
580 €
2 reembolsos emitidos
Disputas abiertas
290 €
1 disputa · BioWellness SL
Checkouts incompletos
14
Potencial ~2.030 € perdido

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)

Pagos completados 8.920 €
Reembolsos emitidos −580 €
En disputa −290 €
Ingresos netos reales 8.050 €
👥
CUSTOMER IMPACT — Análisis por Incidente
🔴

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 €/mes
🔴

BioWellness 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-24
🟡

6 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
🔍
PRODUCT TRUTH — Código vs. Marketing
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)

// checkout.js — 2026-05-20 const session = await stripe.checkout.sessions.create({ mode: 'subscription', line_items: [{ price: PRICE_ID, quantity: req.body.seats }], // TODO: implement seat validation pre-checkout success_url: `${BASE_URL}/onboarding`, });

Evidencia de código — entitlement.js (commit 4f2a1b3)

// entitlement.js exports.canAddUser = async (orgId) => { return true; // TEMP: seat enforcement disabled pending v2.1 }; // Consecuencia: cualquier org puede añadir // usuarios sin límite, independientemente // del plan contratado.
DECISION — Acciones por Caso

🔴 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.
🛠
PRODUCT GAP — Backlog Técnico Requerido
# 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 realcanAddUser() 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