18 KiB
18 KiB
Modelo de Dominio: Billing (MGN-015)
Módulo: MGN-015 - Billing y Suscripciones SaaS Fecha: 2025-12-06 Estado: ✅ Implementado
Diagrama de Entidades
┌─────────────────────────────────────────────────────────────────────────────┐
│ BILLING DOMAIN │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ subscription_plans │ │ tenants │ │
│ │ (Global) │ │ (from auth) │ │
│ ├──────────────────────┤ ├──────────────────────┤ │
│ │ id │ │ id │ │
│ │ code │◄────────│ │ │
│ │ name │ └──────────┬───────────┘ │
│ │ price_monthly │ │ │
│ │ price_yearly │ │ 1 │
│ │ max_users │ │ │
│ │ max_companies │ ▼ │
│ │ features (JSONB) │ ┌──────────────────────┐ │
│ └──────────┬───────────┘ │ subscriptions │ │
│ │ ├──────────────────────┤ │
│ │ 1 │ id │ │
│ │ │ tenant_id │──┐ │
│ ▼ │ plan_id │ │ │
│ ┌──────────────────────┐ │ status │ │ │
│ │ subscriptions │◄────────│ billing_cycle │ │ │
│ │ │ │ current_period_start │ │ │
│ └──────────────────────┘ │ current_period_end │ │ │
│ │ stripe_subscription_id│ │ │
│ └──────────┬───────────┘ │ │
│ │ │ │
│ │ 1 │ │
│ ▼ │ │
│ ┌──────────────────────┐ │ │
│ │ subscription_history │ │ │
│ ├──────────────────────┤ │ │
│ │ id │ │ │
│ │ subscription_id │ │ │
│ │ event_type │ │ │
│ │ previous_plan_id │ │ │
│ │ new_plan_id │ │ │
│ │ metadata (JSONB) │ │ │
│ └──────────────────────┘ │ │
│ │ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │ │
│ │ tenant_owners │ │ payment_methods │ │ │
│ ├──────────────────────┤ ├──────────────────────┤ │ │
│ │ id │ │ id │ │ │
│ │ tenant_id │◄────────│ tenant_id │◄─┤ │
│ │ user_id │ │ type │ │ │
│ │ ownership_type │ │ card_last_four │ │ │
│ │ billing_email │ │ card_brand │ │ │
│ └──────────────────────┘ │ is_default │ │ │
│ │ stripe_payment_method_id│ │ │
│ └──────────────────────┘ │ │
│ │ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │ │
│ │ invoices │ │ payments │ │ │
│ ├──────────────────────┤ ├──────────────────────┤ │ │
│ │ id │◄────────│ id │ │ │
│ │ tenant_id │◄────────│ tenant_id │◄─┤ │
│ │ subscription_id │ │ invoice_id │ │ │
│ │ invoice_number │ │ payment_method_id │ │ │
│ │ status │ │ amount │ │ │
│ │ subtotal │ │ status │ │ │
│ │ tax_amount │ │ paid_at │ │ │
│ │ total │ │ stripe_payment_intent_id│ │ │
│ │ cfdi_uuid │ └──────────────────────┘ │ │
│ └──────────┬───────────┘ │ │
│ │ │ │
│ │ 1..* │ │
│ ▼ │ │
│ ┌──────────────────────┐ │ │
│ │ invoice_lines │ │ │
│ ├──────────────────────┤ │ │
│ │ id │ │ │
│ │ invoice_id │ │ │
│ │ description │ │ │
│ │ quantity │ │ │
│ │ unit_price │ │ │
│ │ amount │ │ │
│ └──────────────────────┘ │ │
│ │ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │ │
│ │ coupons │ │ coupon_redemptions │ │ │
│ │ (Global) │ ├──────────────────────┤ │ │
│ ├──────────────────────┤ │ id │ │ │
│ │ id │◄────────│ coupon_id │ │ │
│ │ code │ │ tenant_id │◄─┤ │
│ │ discount_type │ │ subscription_id │ │ │
│ │ discount_value │ │ redeemed_at │ │ │
│ │ max_redemptions │ └──────────────────────┘ │ │
│ │ valid_from │ │ │
│ │ valid_until │ │ │
│ └──────────────────────┘ │ │
│ │ │
│ ┌──────────────────────┐ │ │
│ │ usage_records │ │ │
│ ├──────────────────────┤ │ │
│ │ id │ │ │
│ │ tenant_id │◄──────────────────────────────────┘ │
│ │ subscription_id │ │
│ │ metric_type │ │
│ │ quantity │ │
│ │ billing_period │ │
│ └──────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Entidades
1. subscription_plans (Planes de Suscripción)
Propósito: Define los planes disponibles para los tenants. Alcance: Global (no tiene tenant_id)
| Atributo | Tipo | Descripción |
|---|---|---|
| id | UUID | Identificador único |
| code | VARCHAR(50) | Código único (free, basic, professional, enterprise) |
| name | VARCHAR(100) | Nombre del plan |
| price_monthly | DECIMAL | Precio mensual |
| price_yearly | DECIMAL | Precio anual |
| max_users | INTEGER | Límite de usuarios (NULL = ilimitado) |
| max_companies | INTEGER | Límite de empresas |
| max_storage_gb | INTEGER | Límite de almacenamiento |
| features | JSONB | Features habilitadas |
| trial_days | INTEGER | Días de prueba |
| is_default | BOOLEAN | Plan por defecto |
2. subscriptions (Suscripciones)
Propósito: Suscripción activa de cada tenant. Restricción: Solo 1 suscripción por tenant.
| Atributo | Tipo | Descripción |
|---|---|---|
| id | UUID | Identificador único |
| tenant_id | UUID | FK a auth.tenants |
| plan_id | UUID | FK a subscription_plans |
| status | ENUM | trialing, active, past_due, paused, cancelled, suspended, expired |
| billing_cycle | ENUM | monthly, quarterly, semi_annual, annual |
| current_period_start | TIMESTAMP | Inicio del período actual |
| current_period_end | TIMESTAMP | Fin del período actual |
| stripe_subscription_id | VARCHAR | ID de Stripe |
3. tenant_owners (Propietarios)
Propósito: Usuarios que pueden gestionar billing del tenant.
| Atributo | Tipo | Descripción |
|---|---|---|
| tenant_id | UUID | FK a auth.tenants |
| user_id | UUID | FK a auth.users |
| ownership_type | VARCHAR | owner, billing_admin |
| billing_email | VARCHAR | Email de facturación |
4. payment_methods (Métodos de Pago)
Propósito: Métodos de pago registrados por tenant.
| Atributo | Tipo | Descripción |
|---|---|---|
| tenant_id | UUID | FK a auth.tenants |
| type | ENUM | card, bank_transfer, paypal, oxxo, spei |
| card_last_four | VARCHAR(4) | Últimos 4 dígitos |
| card_brand | VARCHAR | visa, mastercard, amex |
| is_default | BOOLEAN | Método por defecto |
| stripe_payment_method_id | VARCHAR | ID de Stripe |
5. invoices (Facturas)
Propósito: Facturas de suscripción.
| Atributo | Tipo | Descripción |
|---|---|---|
| tenant_id | UUID | FK a auth.tenants |
| invoice_number | VARCHAR | Número de factura |
| status | ENUM | draft, open, paid, void, uncollectible |
| subtotal | DECIMAL | Subtotal |
| tax_amount | DECIMAL | Impuestos |
| total | DECIMAL | Total |
| cfdi_uuid | VARCHAR | UUID del CFDI (México) |
6. payments (Pagos)
Propósito: Pagos recibidos.
| Atributo | Tipo | Descripción |
|---|---|---|
| tenant_id | UUID | FK a auth.tenants |
| invoice_id | UUID | FK a invoices |
| amount | DECIMAL | Monto pagado |
| status | ENUM | pending, processing, succeeded, failed, cancelled, refunded |
| stripe_payment_intent_id | VARCHAR | ID de Stripe |
7. coupons (Cupones)
Propósito: Cupones de descuento. Alcance: Global
| Atributo | Tipo | Descripción |
|---|---|---|
| code | VARCHAR | Código del cupón |
| discount_type | VARCHAR | percent, fixed |
| discount_value | DECIMAL | Valor del descuento |
| max_redemptions | INTEGER | Máximo de usos |
| valid_from | TIMESTAMP | Válido desde |
| valid_until | TIMESTAMP | Válido hasta |
8. usage_records (Registros de Uso)
Propósito: Tracking de uso para billing por consumo.
| Atributo | Tipo | Descripción |
|---|---|---|
| tenant_id | UUID | FK a auth.tenants |
| metric_type | VARCHAR | users, storage_gb, api_calls |
| quantity | DECIMAL | Cantidad consumida |
| billing_period | DATE | Período de facturación |
Estados de Suscripción
┌─────────┐
│ trialing│
└────┬────┘
│ (trial ends)
▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ paused │◄───│ active │───►│past_due │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
│ │ │ (payment fails)
│ ▼ ▼
│ ┌─────────┐ ┌─────────┐
└───────►│cancelled│ │suspended│
└─────────┘ └────┬────┘
│
▼
┌─────────┐
│ expired │
└─────────┘
Funciones de Negocio
get_tenant_plan(tenant_id)
SELECT plan_code, plan_name, max_users, features, subscription_status
FROM billing.get_tenant_plan(tenant_id);
can_add_user(tenant_id)
SELECT billing.can_add_user(tenant_id);
-- Returns: true/false
has_feature(tenant_id, feature)
SELECT billing.has_feature(tenant_id, 'crm');
-- Returns: true/false
Integración con Stripe
| Campo | Propósito |
|---|---|
| stripe_customer_id | ID del customer en Stripe |
| stripe_subscription_id | ID de la suscripción en Stripe |
| stripe_payment_method_id | ID del método de pago |
| stripe_payment_intent_id | ID del payment intent |
| stripe_invoice_id | ID de la factura en Stripe |
Features JSONB Structure
{
"inventory": true,
"sales": true,
"financial": true,
"purchase": true,
"crm": false,
"projects": false,
"reports_basic": true,
"reports_advanced": false,
"api_access": false,
"white_label": false,
"priority_support": false
}
Generado por: Requirements-Analyst Fecha: 2025-12-06