- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Actualizaciones de configuracion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
7.2 KiB
7.2 KiB
| id | title | type | status | priority | module | version | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|
| SAAS-004 | Billing y Suscripciones | Module | Published | P0 | billing | 1.0.0 | 2026-01-07 | 2026-01-10 |
SAAS-004: Billing y Suscripciones
Metadata
- Codigo: SAAS-004
- Modulo: Billing
- Prioridad: P0
- Estado: Completado
- Fase: 2 - Billing
Descripcion
Sistema de facturacion completo con Stripe: suscripciones recurrentes, trials, upgrades/downgrades, facturas, y webhooks para sincronizacion.
Objetivos
- Integracion completa con Stripe
- Suscripciones mensuales/anuales
- Trial period (14 dias)
- Upgrade/downgrade de plan
- Facturas y recibos
Alcance
Incluido
- Stripe Checkout
- Suscripciones recurrentes
- Trial gratuito
- Cambio de plan (prorateo)
- Portal de cliente Stripe
- Webhooks de Stripe
- Historial de facturas
Excluido
- Metered billing - fase posterior
- Multiples metodos de pago guardados
- Facturacion fiscal mexicana
Modelo de Datos
Tablas (schema: billing)
subscriptions
| Columna | Tipo | Descripcion |
|---|---|---|
| id | UUID | PK |
| tenant_id | UUID | FK -> tenants.tenants (unique) |
| plan_id | UUID | FK -> plans.plans |
| stripe_subscription_id | VARCHAR | ID en Stripe |
| stripe_customer_id | VARCHAR | Customer ID Stripe |
| status | subscription_status | Estado (ver enums) |
| current_period_start | TIMESTAMP | Inicio periodo |
| current_period_end | TIMESTAMP | Fin periodo |
| trial_start | TIMESTAMP | Inicio trial |
| trial_end | TIMESTAMP | Fin trial |
| cancel_at | TIMESTAMP | Fecha programada cancelacion |
| canceled_at | TIMESTAMP | Fecha real cancelacion |
| cancel_reason | VARCHAR | Razon cancelacion |
| price_amount | DECIMAL | Precio del plan |
| currency | VARCHAR | Moneda (USD, MXN) |
| metadata | JSONB | Metadata adicional |
invoices
| Columna | Tipo | Descripcion |
|---|---|---|
| id | UUID | PK |
| tenant_id | UUID | FK -> tenants.tenants |
| subscription_id | UUID | FK -> billing.subscriptions |
| stripe_invoice_id | VARCHAR | ID en Stripe |
| invoice_number | VARCHAR | Numero (INV-YYYYMM-XXXXXX) |
| subtotal | DECIMAL | Subtotal |
| tax | DECIMAL | Impuestos |
| discount | DECIMAL | Descuento aplicado |
| total | DECIMAL | Total |
| amount_paid | DECIMAL | Monto pagado |
| amount_due | DECIMAL | Monto pendiente |
| currency | VARCHAR | Moneda |
| status | invoice_status | draft, open, paid, void, uncollectible |
| invoice_date | DATE | Fecha factura |
| due_date | DATE | Fecha vencimiento |
| period_start | TIMESTAMP | Inicio periodo facturado |
| period_end | TIMESTAMP | Fin periodo facturado |
| paid_at | TIMESTAMP | Fecha de pago |
| invoice_pdf_url | VARCHAR | URL PDF factura |
| hosted_invoice_url | VARCHAR | URL Stripe hosted |
| customer_name | VARCHAR | Nombre cliente |
| customer_email | VARCHAR | Email cliente |
| billing_address | JSONB | Direccion facturacion |
payment_methods
| Columna | Tipo | Descripcion |
|---|---|---|
| id | UUID | PK |
| tenant_id | UUID | FK -> tenants.tenants |
| type | payment_method_type | card, bank_transfer, oxxo |
| provider | VARCHAR | stripe, conekta, etc. |
| external_payment_method_id | VARCHAR | ID en proveedor |
| card_brand | VARCHAR | Visa, Mastercard, Amex |
| card_last4 | VARCHAR | Ultimos 4 digitos |
| card_exp_month | INTEGER | Mes expiracion |
| card_exp_year | INTEGER | Año expiracion |
| is_default | BOOLEAN | Metodo por defecto |
| created_at | TIMESTAMP | Fecha creacion |
Enums de Billing
tenants.subscription_status
Estado general del tenant respecto a su suscripcion (usado en tenant context):
| Valor | Descripcion |
|---|---|
| trialing | En periodo de prueba |
| active | Suscripcion activa |
| past_due | Pago atrasado |
| cancelled | Cancelado |
| unpaid | Sin pago |
billing.subscription_status
Estado interno del sistema de billing:
| Valor | Descripcion |
|---|---|
| trial | En trial |
| active | Activo |
| past_due | Pago atrasado |
| cancelled | Cancelado |
| expired | Expirado |
Nota: El tenant usa tenants.subscription_status para el estado visible.
El modulo billing usa billing.subscription_status internamente.
Integracion Stripe
Productos y Precios
// Configurados en Stripe Dashboard
const STRIPE_PRODUCTS = {
starter: {
monthly: 'price_xxx_monthly',
yearly: 'price_xxx_yearly'
},
pro: {
monthly: 'price_yyy_monthly',
yearly: 'price_yyy_yearly'
}
};
Webhooks Manejados
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.paidinvoice.payment_failedcustomer.updated
Endpoints API
| Metodo | Endpoint | Descripcion |
|---|---|---|
| GET | /billing/plans | Planes disponibles |
| GET | /billing/subscription | Suscripcion actual |
| POST | /billing/checkout | Crear sesion checkout |
| POST | /billing/portal | URL portal de cliente |
| PUT | /billing/change-plan | Cambiar plan |
| POST | /billing/cancel | Cancelar suscripcion |
| POST | /billing/resume | Reanudar suscripcion |
| GET | /billing/invoices | Historial facturas |
| GET | /billing/invoices/:id/pdf | Descargar factura |
| POST | /billing/webhook | Webhook Stripe |
Flujos
Nueva Suscripcion
1. Usuario selecciona plan
2. Click "Suscribirse"
3. Backend crea Checkout Session
4. Usuario redirigido a Stripe Checkout
5. Usuario completa pago
6. Stripe envia webhook
7. Backend actualiza suscripcion
8. Usuario redirigido a app
Upgrade de Plan
1. Usuario en plan Starter
2. Click "Upgrade a Pro"
3. Backend llama Stripe API
4. Stripe calcula prorateo
5. Se cobra diferencia
6. Plan actualizado inmediatamente
7. Features Pro desbloqueadas
Trial Expirando
Dia -3: Email "Tu trial termina en 3 dias"
Dia -1: Email "Tu trial termina manana"
Dia 0: Email "Tu trial ha terminado"
Si no hay pago: downgrade a Free
Estados de Suscripcion
trialing ──► active ──► past_due ──► cancelled
│
└──► paused
| Estado | Acceso | Descripcion |
|---|---|---|
| trialing | Completo | En periodo de prueba |
| active | Completo | Pagando |
| past_due | Limitado | Pago fallido (grace) |
| cancelled | Sin acceso | Cancelada |
| paused | Sin acceso | Pausada |
Entregables
| Entregable | Estado | Archivo |
|---|---|---|
| billing.module.ts | Completado | modules/billing/ |
| stripe.service.ts | Completado | services/ |
| billing.controller.ts | Completado | controllers/ |
| DDL billing schema | Completado | ddl/schemas/billing/ |
Dependencias
Depende de
- SAAS-001 (Auth)
- SAAS-002 (Tenants)
- SAAS-005 (Plans)
Bloquea a
- Ninguno (pero habilita features por plan)
Criterios de Aceptacion
- Checkout funciona
- Webhooks se procesan
- Upgrade/downgrade funciona
- Facturas se generan
- Trial funciona
- Cancelacion funciona
Configuracion
{
stripe: {
secretKey: process.env.STRIPE_SECRET_KEY,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
portalReturnUrl: 'https://app.example.com/settings/billing'
},
trial: {
days: 14,
requiresCard: false
}
}
Ultima actualizacion: 2026-01-10