--- id: EPIC-MCH-018 type: Epic title: "MCH-018: Planes y Suscripciones" code: MCH-018 status: Completado phase: 5 priority: P0 story_points: 21 created_at: 2026-01-06 updated_at: 2026-01-17 simco_version: "4.0.1" dependencies: blocks: [] depends_on: [] --- # MCH-018: Planes y Suscripciones ## Metadata - **Codigo:** MCH-018 - **Fase:** 5 - Monetizacion - **Prioridad:** P0 - **Estado:** Completado - **Story Points:** 21 - **Fecha inicio:** 2026-01-06 - **Fecha fin:** 2026-01-07 ## Descripcion Sistema de planes de suscripcion para monetizar MiChangarrito: dos planes principales (Changarrito y Tiendita), facturacion mensual, y gestion de ciclos de pago. ## Objetivos 1. Definir planes disponibles 2. Proceso de suscripcion 3. Facturacion recurrente 4. Gestion de ciclo de vida 5. Upgrade/downgrade de plan ## Alcance ### Incluido - Plan Changarrito ($99/mes) - Plan Tiendita ($199/mes) - Trial de 14 dias - Facturacion via Stripe - Cancelacion y pausas - Historial de facturacion ### Excluido - Planes anuales (fase posterior) - Planes enterprise personalizados - Facturacion fiscal mexicana (MCH-027) ## Planes ### Plan Changarrito - $99/mes ``` ✓ App movil completa ✓ Punto de venta basico ✓ Hasta 500 productos ✓ 1 usuario ✓ 500 tokens IA/mes ✓ Soporte por WhatsApp ✗ WhatsApp Business propio ✗ Predicciones de inventario ``` ### Plan Tiendita - $199/mes ``` ✓ Todo de Changarrito ✓ Productos ilimitados ✓ Hasta 5 usuarios ✓ 2,000 tokens IA/mes ✓ WhatsApp Business propio ✓ Predicciones de inventario ✓ Reportes avanzados ✓ Entregas a domicilio ✓ Soporte prioritario ``` ## Modelo de Datos ### Tablas (schema: subscriptions) **plans** - id, name, code, price - currency, interval (month/year) - features (JSONB), token_quota - max_products, max_users - stripe_price_id, status **subscriptions** - id, tenant_id, plan_id - status (trialing/active/past_due/cancelled) - stripe_subscription_id - current_period_start, current_period_end - trial_end, cancelled_at **invoices** - id, subscription_id, amount - status, stripe_invoice_id - paid_at, pdf_url ## Endpoints API | Metodo | Endpoint | Descripcion | |--------|----------|-------------| | GET | /subscriptions/plans | Listar planes | | GET | /subscriptions/current | Suscripcion actual | | POST | /subscriptions/subscribe | Suscribirse | | POST | /subscriptions/cancel | Cancelar | | POST | /subscriptions/resume | Reanudar | | PUT | /subscriptions/change-plan | Cambiar plan | | GET | /subscriptions/invoices | Historial facturas | | POST | /subscriptions/webhook | Webhook Stripe | ## Flujos ### Nueva Suscripcion ``` 1. Usuario selecciona plan 2. Ingresa metodo de pago (Stripe) 3. Se crea suscripcion con trial 4. Usuario tiene acceso inmediato 5. Al terminar trial, se cobra automaticamente ``` ### Cancelacion ``` 1. Usuario solicita cancelar 2. Confirmacion requerida 3. Suscripcion marcada para cancelar 4. Acceso hasta fin del periodo 5. Datos preservados 30 dias ``` ### Upgrade ``` 1. Usuario en Changarrito 2. Solicita upgrade a Tiendita 3. Se calcula prorateo 4. Pago de diferencia 5. Features activadas inmediatamente ``` ## Estados de Suscripcion ``` trialing ──► active ──► past_due ──► cancelled │ │ └───────────┴──► paused ``` | Estado | Descripcion | Acceso | |--------|-------------|--------| | trialing | En periodo de prueba | Completo | | active | Pagando normalmente | Completo | | past_due | Pago fallido (grace period) | Limitado | | cancelled | Cancelada | Sin acceso | | paused | Pausada temporalmente | Sin acceso | ## Integracion Stripe ### Subscription Billing ```typescript const subscription = await stripe.subscriptions.create({ customer: customer.stripe_id, items: [{ price: plan.stripe_price_id }], trial_period_days: 14, payment_behavior: 'default_incomplete', expand: ['latest_invoice.payment_intent'] }); ``` ### Webhooks Manejados - `customer.subscription.created` - `customer.subscription.updated` - `customer.subscription.deleted` - `invoice.payment_succeeded` - `invoice.payment_failed` ## Historias de Usuario ### MCH-US-170: Catalogo de Planes de Suscripcion **Story Points:** 3 **Como** visitante o usuario registrado **Quiero** ver el catalogo de planes disponibles con sus caracteristicas y precios **Para** tomar una decision informada sobre cual plan contratar #### Criterios de Aceptacion - [CA-170-1] Se muestran los planes Changarrito ($99/mes) y Tiendita ($199/mes) - [CA-170-2] Cada plan muestra claramente sus caracteristicas incluidas y excluidas - [CA-170-3] Se indica el periodo de prueba gratuito de 14 dias - [CA-170-4] Existe boton de CTA para iniciar suscripcion en cada plan - [CA-170-5] La comparativa entre planes es clara y visual #### Tareas | ID | Tarea | Estimacion | |----|-------|------------| | MCH-TT-170-01 | Crear componente PlanCard con features | 2h | | MCH-TT-170-02 | Implementar pagina Plans.tsx con comparativa | 3h | | MCH-TT-170-03 | Integrar endpoint GET /subscriptions/plans | 1h | | MCH-TT-170-04 | Agregar tests unitarios de componentes | 2h | --- ### MCH-US-171: Proceso de Suscripcion con Trial **Story Points:** 5 **Como** usuario nuevo **Quiero** suscribirme a un plan con un periodo de prueba gratuito **Para** probar el sistema antes de comprometerme con el pago #### Criterios de Aceptacion - [CA-171-1] El usuario puede seleccionar un plan y registrar metodo de pago via Stripe - [CA-171-2] Se crea suscripcion en estado "trialing" con 14 dias de trial - [CA-171-3] El usuario tiene acceso completo a features del plan durante el trial - [CA-171-4] Se notifica por email la activacion del trial y fecha de primer cobro - [CA-171-5] El tenant se configura con los limites del plan seleccionado #### Tareas | ID | Tarea | Estimacion | |----|-------|------------| | MCH-TT-171-01 | Implementar flujo de checkout con Stripe Elements | 4h | | MCH-TT-171-02 | Crear endpoint POST /subscriptions/subscribe | 3h | | MCH-TT-171-03 | Configurar trial_period_days en Stripe | 1h | | MCH-TT-171-04 | Implementar notificaciones email de trial | 2h | | MCH-TT-171-05 | Tests de integracion del flujo completo | 2h | --- ### MCH-US-172: Facturacion Recurrente Automatica **Story Points:** 5 **Como** suscriptor activo **Quiero** que mi pago mensual se procese automaticamente **Para** mantener mi suscripcion activa sin intervencion manual #### Criterios de Aceptacion - [CA-172-1] Stripe cobra automaticamente al terminar el trial o periodo actual - [CA-172-2] Se genera invoice y se almacena en tabla invoices - [CA-172-3] El webhook invoice.payment_succeeded actualiza estado a "active" - [CA-172-4] El webhook invoice.payment_failed marca como "past_due" con grace period - [CA-172-5] Se envia email de confirmacion de pago con link al recibo #### Tareas | ID | Tarea | Estimacion | |----|-------|------------| | MCH-TT-172-01 | Implementar handler webhook invoice.payment_succeeded | 2h | | MCH-TT-172-02 | Implementar handler webhook invoice.payment_failed | 2h | | MCH-TT-172-03 | Crear servicio de sincronizacion de invoices | 3h | | MCH-TT-172-04 | Implementar emails transaccionales de facturacion | 2h | | MCH-TT-172-05 | Configurar retry policy para pagos fallidos | 1h | --- ### MCH-US-173: Upgrade y Downgrade de Plan **Story Points:** 3 **Como** suscriptor del plan Changarrito **Quiero** poder cambiar a plan Tiendita (o viceversa) **Para** ajustar mi suscripcion a las necesidades de mi negocio #### Criterios de Aceptacion - [CA-173-1] El usuario puede solicitar cambio de plan desde su dashboard - [CA-173-2] Se calcula y muestra el prorateo antes de confirmar - [CA-173-3] En upgrade: se cobra diferencia y activan features inmediatamente - [CA-173-4] En downgrade: se ajusta al siguiente ciclo de facturacion - [CA-173-5] Los limites del tenant se actualizan segun nuevo plan #### Tareas | ID | Tarea | Estimacion | |----|-------|------------| | MCH-TT-173-01 | Implementar endpoint PUT /subscriptions/change-plan | 3h | | MCH-TT-173-02 | Calcular prorateo con Stripe proration_behavior | 2h | | MCH-TT-173-03 | Crear UI de cambio de plan con preview de costos | 2h | | MCH-TT-173-04 | Actualizar limites de tenant post-cambio | 1h | --- ### MCH-US-174: Cancelacion y Pausas de Suscripcion **Story Points:** 3 **Como** suscriptor **Quiero** poder cancelar o pausar mi suscripcion **Para** gestionar el ciclo de vida segun mis circunstancias #### Criterios de Aceptacion - [CA-174-1] El usuario puede solicitar cancelacion con confirmacion requerida - [CA-174-2] La cancelacion es efectiva al final del periodo pagado - [CA-174-3] Los datos se preservan 30 dias despues de cancelar - [CA-174-4] El usuario puede reanudar suscripcion cancelada antes de perder datos - [CA-174-5] Se puede pausar temporalmente con estado "paused" #### Tareas | ID | Tarea | Estimacion | |----|-------|------------| | MCH-TT-174-01 | Implementar endpoint POST /subscriptions/cancel | 2h | | MCH-TT-174-02 | Implementar endpoint POST /subscriptions/resume | 2h | | MCH-TT-174-03 | Crear UI de cancelacion con encuesta de salida | 2h | | MCH-TT-174-04 | Implementar job de limpieza de datos post-30 dias | 2h | | MCH-TT-174-05 | Manejar webhook customer.subscription.deleted | 1h | --- ### MCH-US-175: Historial de Facturacion **Story Points:** 2 **Como** suscriptor **Quiero** ver mi historial de facturas y descargar recibos **Para** tener control de mis gastos y documentacion fiscal #### Criterios de Aceptacion - [CA-175-1] Se muestra lista de invoices con fecha, monto y estado - [CA-175-2] Cada invoice tiene link para descargar PDF desde Stripe - [CA-175-3] Se pueden filtrar invoices por rango de fechas - [CA-175-4] Se muestra informacion de la suscripcion actual y proximo cobro - [CA-175-5] El historial es accesible desde pagina Billing.tsx #### Tareas | ID | Tarea | Estimacion | |----|-------|------------| | MCH-TT-175-01 | Implementar endpoint GET /subscriptions/invoices | 2h | | MCH-TT-175-02 | Crear pagina Billing.tsx con historial | 3h | | MCH-TT-175-03 | Integrar descarga de PDF via Stripe invoice URL | 1h | | MCH-TT-175-04 | Agregar filtros y paginacion al historial | 2h | --- ### Resumen de Historias de Usuario | ID | Historia | Story Points | Estado | |----|----------|--------------|--------| | MCH-US-170 | Catalogo de Planes de Suscripcion | 3 | Completado | | MCH-US-171 | Proceso de Suscripcion con Trial | 5 | Completado | | MCH-US-172 | Facturacion Recurrente Automatica | 5 | Completado | | MCH-US-173 | Upgrade y Downgrade de Plan | 3 | En Progreso | | MCH-US-174 | Cancelacion y Pausas de Suscripcion | 3 | Completado | | MCH-US-175 | Historial de Facturacion | 2 | Pendiente | | **TOTAL** | | **21** | | ## Entregables | Entregable | Estado | Archivo | |------------|--------|---------| | DDL subscriptions | Completado | `10-subscriptions.sql` | | subscriptions.module | Completado | `modules/subscriptions/` | | Stripe integration | Completado | `providers/stripe.provider.ts` | | Plans UI | Pendiente | `pages/Plans.tsx` | | Billing UI | Pendiente | `pages/Billing.tsx` | ## Dependencias ### Depende de - MCH-005 (Stripe integration base) - MCH-002 (Auth) ### Bloquea a - MCH-019 (Tokens) - MCH-020 (Pagos online) ## Criterios de Aceptacion - [x] Planes se muestran correctamente - [x] Suscripcion se crea en Stripe - [x] Trial de 14 dias funciona - [x] Cobro recurrente funciona - [x] Cancelacion funciona - [ ] Upgrade/downgrade funciona ## Configuracion ```typescript // plans seed [ { name: 'Changarrito', code: 'changarrito', price: 99, currency: 'MXN', token_quota: 500, max_products: 500, max_users: 1, stripe_price_id: 'price_xxx' }, { name: 'Tiendita', code: 'tiendita', price: 199, currency: 'MXN', token_quota: 2000, max_products: null, // unlimited max_users: 5, stripe_price_id: 'price_yyy' } ] ``` --- **Ultima actualizacion:** 2026-01-17