537 lines
15 KiB
YAML
537 lines
15 KiB
YAML
# TRACEABILITY-MGN-015: Billing y Suscripciones
|
|
# Matriz de trazabilidad entre requerimientos, especificaciones, y artefactos
|
|
# Fecha: 2025-11-24
|
|
|
|
module:
|
|
id: MGN-015
|
|
name: Billing y Suscripciones
|
|
description: Gestión de suscripciones, pagos, facturación y límites para SaaS multi-tenant
|
|
priority: P0
|
|
total_story_points: 55
|
|
|
|
# Requerimientos Funcionales
|
|
requirements:
|
|
- id: RF-MGN-015-001
|
|
name: Gestión de Planes de Suscripción
|
|
priority: P0
|
|
story_points: 8
|
|
document: ../requerimientos-funcionales/mgn-015/RF-MGN-015-001-gestion-planes-suscripcion.md
|
|
specifications:
|
|
backend:
|
|
- ET-MGN-015-001
|
|
database:
|
|
tables:
|
|
- billing.subscription_plans
|
|
functions: []
|
|
triggers: []
|
|
api_endpoints:
|
|
- GET /api/v1/billing/plans
|
|
- GET /api/v1/billing/plans/:id
|
|
- POST /api/v1/billing/plans
|
|
- PUT /api/v1/billing/plans/:id
|
|
- DELETE /api/v1/billing/plans/:id
|
|
- PATCH /api/v1/billing/plans/:id/toggle
|
|
actors:
|
|
- super_admin
|
|
- platform_admin
|
|
dependencies:
|
|
requires: []
|
|
blocks:
|
|
- RF-MGN-015-002
|
|
|
|
- id: RF-MGN-015-002
|
|
name: Gestión de Suscripciones de Tenant
|
|
priority: P0
|
|
story_points: 13
|
|
document: ../requerimientos-funcionales/mgn-015/RF-MGN-015-002-gestion-suscripciones-tenant.md
|
|
specifications:
|
|
backend:
|
|
- ET-MGN-015-002
|
|
database:
|
|
tables:
|
|
- billing.subscriptions
|
|
- billing.subscription_history
|
|
- billing.tenant_owners
|
|
functions:
|
|
- billing.get_tenant_plan(tenant_id)
|
|
triggers:
|
|
- log_subscription_change
|
|
api_endpoints:
|
|
- GET /api/v1/billing/subscription
|
|
- GET /api/v1/billing/subscriptions (admin)
|
|
- POST /api/v1/billing/subscription/upgrade
|
|
- POST /api/v1/billing/subscription/downgrade
|
|
- POST /api/v1/billing/subscription/cancel
|
|
- POST /api/v1/billing/subscription/reactivate
|
|
- PUT /api/v1/billing/subscription/billing-cycle
|
|
- GET /api/v1/billing/subscription/history
|
|
actors:
|
|
- tenant_owner
|
|
- super_admin
|
|
- system (renovaciones)
|
|
dependencies:
|
|
requires:
|
|
- RF-MGN-015-001
|
|
blocks:
|
|
- RF-MGN-015-003
|
|
jobs:
|
|
- subscription-renewal.job.ts (diario)
|
|
|
|
- id: RF-MGN-015-003
|
|
name: Gestión de Métodos de Pago
|
|
priority: P0
|
|
story_points: 8
|
|
document: ../requerimientos-funcionales/mgn-015/RF-MGN-015-003-metodos-pago.md
|
|
specifications:
|
|
backend:
|
|
- ET-MGN-015-003
|
|
database:
|
|
tables:
|
|
- billing.payment_methods
|
|
functions: []
|
|
triggers: []
|
|
api_endpoints:
|
|
- GET /api/v1/billing/payment-methods
|
|
- POST /api/v1/billing/payment-methods/setup-intent
|
|
- POST /api/v1/billing/payment-methods
|
|
- PATCH /api/v1/billing/payment-methods/:id/default
|
|
- DELETE /api/v1/billing/payment-methods/:id
|
|
actors:
|
|
- tenant_owner
|
|
integrations:
|
|
- name: Stripe
|
|
type: payment_gateway
|
|
endpoints:
|
|
- PaymentMethods
|
|
- SetupIntents
|
|
- Customers
|
|
webhooks:
|
|
- POST /api/v1/webhooks/stripe
|
|
dependencies:
|
|
requires:
|
|
- RF-MGN-015-002
|
|
blocks:
|
|
- RF-MGN-015-004
|
|
|
|
- id: RF-MGN-015-004
|
|
name: Facturación y Cobros
|
|
priority: P0
|
|
story_points: 13
|
|
document: ../requerimientos-funcionales/mgn-015/RF-MGN-015-004-facturacion-cobros.md
|
|
specifications:
|
|
backend:
|
|
- ET-MGN-015-004
|
|
database:
|
|
tables:
|
|
- billing.invoices
|
|
- billing.invoice_lines
|
|
- billing.payments
|
|
functions: []
|
|
triggers:
|
|
- update_invoice_totals
|
|
api_endpoints:
|
|
- GET /api/v1/billing/invoices
|
|
- GET /api/v1/billing/invoices/:id
|
|
- GET /api/v1/billing/invoices/:id/pdf
|
|
- GET /api/v1/billing/invoices/:id/xml
|
|
- POST /api/v1/billing/invoices/:id/request-cfdi
|
|
- POST /api/v1/billing/invoices/:id/retry-payment
|
|
- POST /api/v1/billing/invoices/:id/credit-note (admin)
|
|
actors:
|
|
- tenant_owner
|
|
- super_admin
|
|
- system (generación automática)
|
|
integrations:
|
|
- name: Stripe
|
|
type: payment_gateway
|
|
endpoints:
|
|
- PaymentIntents
|
|
- name: PAC
|
|
type: cfdi_provider
|
|
options:
|
|
- Facturama
|
|
- SW Sapien
|
|
- Finkok
|
|
dependencies:
|
|
requires:
|
|
- RF-MGN-015-002
|
|
- RF-MGN-015-003
|
|
blocks:
|
|
- RF-MGN-015-005
|
|
jobs:
|
|
- invoice-generation.job.ts (diario)
|
|
- payment-retry.job.ts (cada hora)
|
|
|
|
- id: RF-MGN-015-005
|
|
name: Registro de Uso y Métricas
|
|
priority: P1
|
|
story_points: 8
|
|
document: ../requerimientos-funcionales/mgn-015/RF-MGN-015-005-registro-uso-metricas.md
|
|
specifications:
|
|
backend:
|
|
- ET-MGN-015-005
|
|
database:
|
|
tables:
|
|
- billing.usage_records
|
|
functions:
|
|
- billing.can_add_user(tenant_id)
|
|
- billing.can_add_company(tenant_id)
|
|
- billing.has_feature(tenant_id, feature)
|
|
- billing.get_current_usage(tenant_id)
|
|
triggers: []
|
|
api_endpoints:
|
|
- GET /api/v1/billing/usage
|
|
- GET /api/v1/billing/usage/history
|
|
- GET /api/v1/billing/usage/check
|
|
- GET /api/v1/billing/features
|
|
- GET /api/v1/billing/features/:feature
|
|
- GET /api/v1/admin/billing/usage (admin)
|
|
actors:
|
|
- tenant_owner
|
|
- admin
|
|
- any_authenticated_user
|
|
- super_admin
|
|
middlewares:
|
|
- checkUserLimit
|
|
- checkCompanyLimit
|
|
- requireFeature
|
|
dependencies:
|
|
requires:
|
|
- RF-MGN-015-001
|
|
- RF-MGN-015-002
|
|
blocks: []
|
|
jobs:
|
|
- record-usage.job.ts (cada 6 horas)
|
|
|
|
- id: RF-MGN-015-006
|
|
name: Modo Single-Tenant
|
|
priority: P1
|
|
story_points: 5
|
|
document: ../requerimientos-funcionales/mgn-015/RF-MGN-015-006-modo-single-tenant.md
|
|
specifications:
|
|
backend: []
|
|
database:
|
|
tables: []
|
|
functions: []
|
|
triggers: []
|
|
api_endpoints: []
|
|
actors:
|
|
- system_admin (on-premise)
|
|
configuration:
|
|
env_vars:
|
|
- DEPLOYMENT_MODE=single_tenant
|
|
- DISABLE_PUBLIC_REGISTRATION=true
|
|
- DISABLE_BILLING_UI=true
|
|
dependencies:
|
|
requires:
|
|
- RF-MGN-015-001
|
|
blocks: []
|
|
|
|
# Especificaciones Técnicas
|
|
specifications:
|
|
backend:
|
|
- id: ET-MGN-015-001
|
|
name: API de Planes de Suscripción
|
|
document: ../especificaciones-tecnicas/backend/mgn-015/ET-MGN-015-001-api-planes-suscripcion.md
|
|
implements:
|
|
- RF-MGN-015-001
|
|
components:
|
|
- src/modules/billing/plans/plans.controller.ts
|
|
- src/modules/billing/plans/plans.service.ts
|
|
- src/modules/billing/plans/plans.routes.ts
|
|
- src/modules/billing/plans/plans.validation.ts
|
|
|
|
- id: ET-MGN-015-002
|
|
name: API de Suscripciones
|
|
document: ../especificaciones-tecnicas/backend/mgn-015/ET-MGN-015-002-api-suscripciones.md
|
|
implements:
|
|
- RF-MGN-015-002
|
|
components:
|
|
- src/modules/billing/subscriptions/subscriptions.controller.ts
|
|
- src/modules/billing/subscriptions/subscriptions.service.ts
|
|
- src/modules/billing/subscriptions/subscriptions.routes.ts
|
|
- src/modules/billing/subscriptions/subscriptions.validation.ts
|
|
|
|
- id: ET-MGN-015-003
|
|
name: API de Métodos de Pago
|
|
document: ../especificaciones-tecnicas/backend/mgn-015/ET-MGN-015-003-api-metodos-pago.md
|
|
implements:
|
|
- RF-MGN-015-003
|
|
components:
|
|
- src/modules/billing/payment-methods/payment-methods.controller.ts
|
|
- src/modules/billing/payment-methods/payment-methods.service.ts
|
|
- src/modules/billing/payment-methods/payment-methods.routes.ts
|
|
- src/modules/billing/payment-methods/payment-methods.validation.ts
|
|
|
|
- id: ET-MGN-015-004
|
|
name: API de Facturación
|
|
document: ../especificaciones-tecnicas/backend/mgn-015/ET-MGN-015-004-api-facturacion.md
|
|
implements:
|
|
- RF-MGN-015-004
|
|
components:
|
|
- src/modules/billing/invoices/invoices.controller.ts
|
|
- src/modules/billing/invoices/invoices.service.ts
|
|
- src/modules/billing/invoices/invoices.routes.ts
|
|
- src/modules/billing/invoices/invoices.validation.ts
|
|
- src/modules/billing/services/pac.service.ts
|
|
|
|
- id: ET-MGN-015-005
|
|
name: API de Uso y Métricas
|
|
document: ../especificaciones-tecnicas/backend/mgn-015/ET-MGN-015-005-api-uso-metricas.md
|
|
implements:
|
|
- RF-MGN-015-005
|
|
components:
|
|
- src/modules/billing/usage/usage.controller.ts
|
|
- src/modules/billing/usage/usage.service.ts
|
|
- src/modules/billing/usage/usage.routes.ts
|
|
- src/shared/middleware/usage-limit.middleware.ts
|
|
|
|
# Base de Datos
|
|
database:
|
|
schema: billing
|
|
ddl_file: ../../../../apps/database/ddl/10-billing.sql
|
|
|
|
tables:
|
|
- name: billing.subscription_plans
|
|
description: Definición de planes disponibles
|
|
rls: false
|
|
tenant_scoped: false
|
|
columns_count: 17
|
|
references:
|
|
- RF-MGN-015-001
|
|
|
|
- name: billing.tenant_owners
|
|
description: Propietarios de cuenta por tenant
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 10
|
|
references:
|
|
- RF-MGN-015-002
|
|
|
|
- name: billing.subscriptions
|
|
description: Suscripciones activas por tenant
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 18
|
|
references:
|
|
- RF-MGN-015-002
|
|
|
|
- name: billing.payment_methods
|
|
description: Métodos de pago tokenizados
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 14
|
|
references:
|
|
- RF-MGN-015-003
|
|
|
|
- name: billing.invoices
|
|
description: Facturas generadas
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 22
|
|
references:
|
|
- RF-MGN-015-004
|
|
|
|
- name: billing.invoice_lines
|
|
description: Líneas de detalle de factura
|
|
rls: true
|
|
tenant_scoped: false
|
|
columns_count: 10
|
|
references:
|
|
- RF-MGN-015-004
|
|
|
|
- name: billing.payments
|
|
description: Registro de pagos/transacciones
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 13
|
|
references:
|
|
- RF-MGN-015-004
|
|
|
|
- name: billing.usage_records
|
|
description: Métricas de uso por período
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 9
|
|
references:
|
|
- RF-MGN-015-005
|
|
|
|
- name: billing.coupons
|
|
description: Cupones de descuento
|
|
rls: false
|
|
tenant_scoped: false
|
|
columns_count: 14
|
|
references:
|
|
- RF-MGN-015-004
|
|
|
|
- name: billing.coupon_redemptions
|
|
description: Cupones canjeados por tenant
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 6
|
|
references:
|
|
- RF-MGN-015-004
|
|
|
|
- name: billing.subscription_history
|
|
description: Historial de cambios de suscripción
|
|
rls: true
|
|
tenant_scoped: true
|
|
columns_count: 10
|
|
references:
|
|
- RF-MGN-015-002
|
|
|
|
enums:
|
|
- billing.subscription_status
|
|
- billing.billing_cycle
|
|
- billing.payment_method_type
|
|
- billing.invoice_status
|
|
- billing.payment_status
|
|
- billing.discount_type
|
|
|
|
functions:
|
|
- name: billing.get_tenant_plan
|
|
params: "(tenant_id UUID)"
|
|
returns: "billing.subscription_plans"
|
|
description: Obtiene el plan actual del tenant
|
|
references:
|
|
- RF-MGN-015-002
|
|
|
|
- name: billing.can_add_user
|
|
params: "(tenant_id UUID)"
|
|
returns: "BOOLEAN"
|
|
description: Verifica si puede agregar usuario
|
|
references:
|
|
- RF-MGN-015-005
|
|
|
|
- name: billing.can_add_company
|
|
params: "(tenant_id UUID)"
|
|
returns: "BOOLEAN"
|
|
description: Verifica si puede agregar empresa
|
|
references:
|
|
- RF-MGN-015-005
|
|
|
|
- name: billing.has_feature
|
|
params: "(tenant_id UUID, feature VARCHAR)"
|
|
returns: "BOOLEAN"
|
|
description: Verifica si feature está habilitada
|
|
references:
|
|
- RF-MGN-015-005
|
|
|
|
- name: billing.get_current_usage
|
|
params: "(tenant_id UUID)"
|
|
returns: "JSONB"
|
|
description: Obtiene uso actual del tenant
|
|
references:
|
|
- RF-MGN-015-005
|
|
|
|
# Integraciones Externas
|
|
integrations:
|
|
- id: INT-001
|
|
name: Stripe
|
|
type: payment_gateway
|
|
required_for:
|
|
- RF-MGN-015-003
|
|
- RF-MGN-015-004
|
|
config:
|
|
env_vars:
|
|
- STRIPE_SECRET_KEY
|
|
- STRIPE_PUBLISHABLE_KEY
|
|
- STRIPE_WEBHOOK_SECRET
|
|
webhooks:
|
|
- payment_method.updated
|
|
- payment_method.card_automatically_updated
|
|
- customer.source.expiring
|
|
|
|
- id: INT-002
|
|
name: PAC (CFDI)
|
|
type: fiscal_provider
|
|
required_for:
|
|
- RF-MGN-015-004
|
|
config:
|
|
env_vars:
|
|
- PAC_PROVIDER
|
|
- PAC_USER
|
|
- PAC_PASSWORD
|
|
- PAC_SANDBOX
|
|
options:
|
|
- Facturama
|
|
- SW Sapien
|
|
- Finkok
|
|
|
|
# Jobs Programados
|
|
scheduled_jobs:
|
|
- id: JOB-001
|
|
name: subscription-renewal
|
|
schedule: "0 1 * * *" # Diario 01:00
|
|
description: Procesa renovaciones de suscripciones
|
|
references:
|
|
- RF-MGN-015-002
|
|
|
|
- id: JOB-002
|
|
name: invoice-generation
|
|
schedule: "0 0 * * *" # Diario 00:00
|
|
description: Genera facturas 1 día antes de renovación
|
|
references:
|
|
- RF-MGN-015-004
|
|
|
|
- id: JOB-003
|
|
name: payment-retry
|
|
schedule: "0 * * * *" # Cada hora
|
|
description: Reintenta pagos fallidos (días 1, 3, 7)
|
|
references:
|
|
- RF-MGN-015-004
|
|
|
|
- id: JOB-004
|
|
name: record-usage
|
|
schedule: "0 */6 * * *" # Cada 6 horas
|
|
description: Registra métricas de uso por tenant
|
|
references:
|
|
- RF-MGN-015-005
|
|
|
|
# Matriz de Trazabilidad Resumida
|
|
traceability_matrix:
|
|
RF-MGN-015-001:
|
|
specifications: [ET-MGN-015-001]
|
|
tables: [billing.subscription_plans]
|
|
endpoints: 6
|
|
|
|
RF-MGN-015-002:
|
|
specifications: [ET-MGN-015-002]
|
|
tables: [billing.subscriptions, billing.subscription_history, billing.tenant_owners]
|
|
endpoints: 8
|
|
jobs: 1
|
|
|
|
RF-MGN-015-003:
|
|
specifications: [ET-MGN-015-003]
|
|
tables: [billing.payment_methods]
|
|
endpoints: 5
|
|
integrations: [Stripe]
|
|
|
|
RF-MGN-015-004:
|
|
specifications: [ET-MGN-015-004]
|
|
tables: [billing.invoices, billing.invoice_lines, billing.payments, billing.coupons, billing.coupon_redemptions]
|
|
endpoints: 7
|
|
jobs: 2
|
|
integrations: [Stripe, PAC]
|
|
|
|
RF-MGN-015-005:
|
|
specifications: [ET-MGN-015-005]
|
|
tables: [billing.usage_records]
|
|
endpoints: 6
|
|
jobs: 1
|
|
functions: 4
|
|
|
|
RF-MGN-015-006:
|
|
specifications: []
|
|
tables: []
|
|
endpoints: 0
|
|
config: [DEPLOYMENT_MODE, DISABLE_PUBLIC_REGISTRATION, DISABLE_BILLING_UI]
|
|
|
|
# Notas
|
|
notes:
|
|
- Los planes (subscription_plans) son globales, no tienen tenant_id ni RLS
|
|
- Todas las demás tablas tienen RLS y requieren tenant_id en el contexto
|
|
- El modo single_tenant usa el plan "single_tenant" con todos los features habilitados
|
|
- Las facturas y XMLs de CFDI deben mantenerse por mínimo 5 años
|
|
- Nunca almacenar datos sensibles de tarjetas (PCI-DSS)
|