# 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)
```sql
SELECT plan_code, plan_name, max_users, features, subscription_status
FROM billing.get_tenant_plan(tenant_id);
```

### can_add_user(tenant_id)
```sql
SELECT billing.can_add_user(tenant_id);
-- Returns: true/false
```

### has_feature(tenant_id, feature)
```sql
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

```json
{
  "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
