erp-core/docs/01-fase-foundation/MGN-004-tenants/requerimientos/RF-TENANT-004.md

14 KiB

RF-TENANT-004: Subscripciones y Limites

Identificacion

Campo Valor
ID RF-TENANT-004
Modulo MGN-004 Tenants
Prioridad P1 - Alta
Estado Ready
Fecha 2025-12-05

Descripcion

El sistema debe gestionar planes de subscripcion para los tenants, controlando los limites de uso (usuarios, storage, modulos) y el ciclo de facturacion. Cada plan define que funcionalidades y recursos estan disponibles para el tenant.


Actores

Actor Descripcion
Platform Admin Gestiona planes y subscripciones
Tenant Admin Ve su subscripcion y puede solicitar upgrades
Sistema Aplica limites automaticamente
Billing System Procesa pagos y renovaciones

Planes de Subscripcion

Planes Disponibles

Plan Usuarios Storage Modulos Precio/mes
Trial 5 1 GB Basicos Gratis (14 dias)
Starter 10 5 GB Basicos $29 USD
Professional 50 25 GB Todos Standard $99 USD
Enterprise Ilimitado 100 GB Todos + Premium $299 USD
Custom Configurable Configurable Configurable Cotizacion

Modulos por Plan

Modulo Trial Starter Professional Enterprise
Auth
Users
Roles
Inventory
Financial -
Reports - Basic Full Full
CRM - -
Advanced Analytics - - -
API Access - -
White Label - - -
Priority Support - - -

Flujo Principal

Ver Subscripcion Actual

1. Tenant Admin accede a Configuracion > Subscripcion
2. Sistema muestra:
   - Plan actual
   - Fecha de inicio
   - Proxima renovacion
   - Uso actual vs limites
   - Historial de facturacion
3. Admin puede ver planes disponibles para upgrade

Solicitar Upgrade

1. Tenant Admin click en "Cambiar Plan"
2. Sistema muestra comparativa de planes
3. Admin selecciona nuevo plan
4. Sistema calcula costo prorrateado
5. Admin confirma y procede al pago
6. Sistema procesa pago
7. Sistema actualiza subscripcion
8. Nuevos limites aplican inmediatamente
9. Sistema envia confirmacion por email

Renovacion Automatica

1. Sistema detecta subscripcion por vencer (3 dias)
2. Sistema envia recordatorio de renovacion
3. En fecha de renovacion:
   a. Sistema intenta cobrar metodo de pago guardado
   b. Si exitoso: renueva subscripcion
   c. Si falla: marca como "payment_pending"
4. Si pago pendiente por 7 dias:
   a. Sistema envia advertencias
   b. Sistema suspende tenant

Cancelar Subscripcion

1. Tenant Admin solicita cancelacion
2. Sistema muestra encuesta de salida
3. Admin confirma cancelacion
4. Sistema programa cancelacion para fin de periodo
5. Tenant sigue activo hasta fin de periodo pagado
6. Al terminar periodo: downgrade a Trial o suspension

Limites y Enforcement

Tipos de Limites

Tipo Comportamiento
Hard Limit Bloquea la accion inmediatamente
Soft Limit Permite con advertencia, bloquea al 110%
Usage Based Cobra extra por exceso

Enforcement de Limites

// Verificacion de limite de usuarios
async canCreateUser(tenantId: string): Promise<boolean> {
  const subscription = await this.getSubscription(tenantId);
  const currentUsers = await this.countUsers(tenantId);

  if (currentUsers >= subscription.limits.maxUsers) {
    throw new PaymentRequiredException(
      `Limite de usuarios alcanzado (${subscription.limits.maxUsers}). ` +
      `Actualiza tu plan para agregar mas usuarios.`
    );
  }
  return true;
}

// Verificacion de acceso a modulo
async canAccessModule(tenantId: string, module: string): Promise<boolean> {
  const subscription = await this.getSubscription(tenantId);

  if (!subscription.modules.includes(module)) {
    throw new PaymentRequiredException(
      `El modulo "${module}" no esta incluido en tu plan. ` +
      `Actualiza a ${this.getMinPlanForModule(module)} para acceder.`
    );
  }
  return true;
}

Reglas de Negocio

ID Regla
RN-001 Trial expira en 14 dias sin opcion de extension
RN-002 Downgrade no permitido durante periodo de facturacion
RN-003 Upgrade aplica inmediatamente con prorrateo
RN-004 Cancelacion efectiva al fin del periodo pagado
RN-005 Datos se conservan 30 dias despues de cancelacion
RN-006 Exceso de storage: soft limit + cargos adicionales
RN-007 Pago fallido: 7 dias de gracia antes de suspension
RN-008 Enterprise puede negociar limites custom

Criterios de Aceptacion

Escenario 1: Ver uso actual vs limites

Given tenant con plan Professional (50 usuarios, 25GB)
  And 35 usuarios activos
  And 18GB de storage usado
When Tenant Admin ve la subscripcion
Then muestra "Usuarios: 35/50 (70%)"
  And muestra "Storage: 18GB/25GB (72%)"
  And muestra grafico de uso

Escenario 2: Bloqueo por limite de usuarios

Given tenant con plan Starter (10 usuarios)
  And 10 usuarios activos (100%)
When Admin intenta crear usuario #11
Then el sistema responde con status 402
  And el mensaje indica limite alcanzado
  And sugiere upgrade a Professional

Escenario 3: Bloqueo por modulo no incluido

Given tenant con plan Starter (sin CRM)
When usuario intenta acceder a /api/v1/crm/contacts
Then el sistema responde con status 402
  And el mensaje indica modulo no disponible
  And sugiere planes que incluyen CRM

Escenario 4: Upgrade de plan

Given tenant en Starter ($29/mes) al dia 15 del mes
When solicita upgrade a Professional ($99/mes)
Then sistema calcula prorrateo: $35 (15 dias de diferencia)
  And usuario paga $35
  And plan cambia inmediatamente
  And nuevos limites aplican
  And siguiente factura: $99 el dia 1

Escenario 5: Trial expirado

Given tenant en Trial por 14 dias
When han pasado los 14 dias sin subscription
Then el estado cambia a "trial_expired"
  And usuarios no pueden acceder
  And datos se conservan
  And Admin puede acceder solo para suscribirse

Escenario 6: Advertencia de renovacion

Given subscripcion que vence en 3 dias
When el sistema ejecuta job de notificaciones
Then envia email "Tu subscripcion vence en 3 dias"
  And incluye link para verificar metodo de pago

Mockup / Wireframe

+------------------------------------------------------------------+
|  [Logo]   Mi Subscripcion                                         |
+------------------------------------------------------------------+
|                                                                   |
|  ┌─────────────────────────────────────────────────────────────┐ |
|  │ PLAN ACTUAL: Professional                    [Cambiar Plan] │ |
|  │                                                              │ |
|  │ $99 USD / mes        Proxima renovacion: 01/01/2026         │ |
|  │ Facturacion mensual  Metodo de pago: •••• 4242              │ |
|  └─────────────────────────────────────────────────────────────┘ |
|                                                                   |
|  USO ACTUAL                                                      |
|  ┌─────────────────────────────────────────────────────────────┐ |
|  │                                                              │ |
|  │ Usuarios      ████████████████████░░░░░░░░░░  35/50 (70%)   │ |
|  │                                                              │ |
|  │ Storage       █████████████████████████░░░░░  18/25GB (72%) │ |
|  │                                                              │ |
|  │ API Calls     ██████████░░░░░░░░░░░░░░░░░░░░  5K/50K (10%)  │ |
|  │                                                              │ |
|  └─────────────────────────────────────────────────────────────┘ |
|                                                                   |
|  MODULOS INCLUIDOS                                               |
|  ┌─────────────────────────────────────────────────────────────┐ |
|  │ ✓ Auth    ✓ Users   ✓ Roles   ✓ Inventory                  │ |
|  │ ✓ Financial  ✓ Reports (Full)  ✓ CRM  ✓ API Access         │ |
|  │                                                              │ |
|  │ No incluidos: Advanced Analytics, White Label               │ |
|  │               [Ver Enterprise para estas funciones]         │ |
|  └─────────────────────────────────────────────────────────────┘ |
|                                                                   |
|  HISTORIAL DE FACTURACION                                        |
|  ┌─────────────────────────────────────────────────────────────┐ |
|  │ Fecha      | Descripcion           | Monto   | Estado       │ |
|  │------------|----------------------|---------|-------------- │ |
|  │ 01/12/2025 | Professional - Dic   | $99.00  | ✓ Pagado     │ |
|  │ 01/11/2025 | Professional - Nov   | $99.00  | ✓ Pagado     │ |
|  │ 15/10/2025 | Upgrade Starter->Pro | $35.00  | ✓ Pagado     │ |
|  │ 01/10/2025 | Starter - Oct        | $29.00  | ✓ Pagado     │ |
|  └─────────────────────────────────────────────────────────────┘ |
|                                                                   |
|  [Descargar Facturas]              [Cancelar Subscripcion]       |
+------------------------------------------------------------------+

Notas Tecnicas

API Endpoints

// Ver subscripcion actual
GET /api/v1/tenant/subscription

// Response 200
{
  "plan": {
    "id": "plan-professional",
    "name": "Professional",
    "price": 99,
    "currency": "USD",
    "interval": "monthly"
  },
  "status": "active",
  "currentPeriodStart": "2025-12-01",
  "currentPeriodEnd": "2025-12-31",
  "cancelAtPeriodEnd": false,
  "usage": {
    "users": { "current": 35, "limit": 50, "percentage": 70 },
    "storage": { "current": 18000000000, "limit": 25000000000, "percentage": 72 },
    "apiCalls": { "current": 5000, "limit": 50000, "percentage": 10 }
  },
  "modules": ["auth", "users", "roles", "inventory", "financial", "reports", "crm", "api"],
  "paymentMethod": { "type": "card", "last4": "4242", "brand": "visa" }
}

// Ver planes disponibles
GET /api/v1/subscription/plans

// Solicitar upgrade
POST /api/v1/tenant/subscription/upgrade
{ "planId": "plan-enterprise" }

// Cancelar subscripcion
POST /api/v1/tenant/subscription/cancel
{ "reason": "too_expensive", "feedback": "..." }

// Verificar limite
GET /api/v1/tenant/subscription/check-limit?type=users

// Response 200
{
  "type": "users",
  "current": 35,
  "limit": 50,
  "canAdd": true,
  "remaining": 15
}

// Response 402 (limite alcanzado)
{
  "statusCode": 402,
  "error": "Payment Required",
  "message": "Limite de usuarios alcanzado",
  "upgradeOptions": [
    { "planId": "plan-enterprise", "name": "Enterprise", "newLimit": "unlimited" }
  ]
}

Modelos de Datos

interface Subscription {
  id: string;
  tenantId: string;
  planId: string;
  status: 'trial' | 'active' | 'past_due' | 'canceled' | 'unpaid';
  currentPeriodStart: Date;
  currentPeriodEnd: Date;
  cancelAtPeriodEnd: boolean;
  trialEnd?: Date;
  paymentMethodId?: string;
}

interface Plan {
  id: string;
  name: string;
  price: number;
  currency: string;
  interval: 'monthly' | 'yearly';
  limits: {
    maxUsers: number;
    maxStorageBytes: number;
    maxApiCalls: number;
  };
  modules: string[];
  features: string[];
  isPublic: boolean;
}

Limit Enforcement Guard

@Injectable()
export class LimitGuard implements CanActivate {
  constructor(
    private subscriptionService: SubscriptionService,
    private reflector: Reflector,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const limitType = this.reflector.get<string>('checkLimit', context.getHandler());
    if (!limitType) return true;

    const request = context.switchToHttp().getRequest();
    const tenantId = request.tenantId;

    const check = await this.subscriptionService.checkLimit(tenantId, limitType);

    if (!check.canAdd) {
      throw new PaymentRequiredException({
        message: `Limite de ${limitType} alcanzado`,
        upgradeOptions: check.upgradeOptions,
      });
    }

    return true;
  }
}

// Uso en controller
@Post()
@CheckLimit('users')
create(@Body() dto: CreateUserDto) { }

Dependencias

ID Descripcion
RF-TENANT-001 Tenants existentes
Payment Gateway Stripe/PayPal para pagos
Scheduler Jobs para renovaciones y notificaciones

Estimacion

Tarea Puntos
Backend: Subscription service 4
Backend: Limit enforcement 4
Backend: Billing integration 5
Backend: Webhooks de pago 3
Backend: Tests 3
Frontend: SubscriptionPage 4
Frontend: PlanComparison 3
Frontend: CheckoutFlow 4
Frontend: Tests 2
Total 32 SP

Historial

Version Fecha Autor Cambios
1.0 2025-12-05 System Creacion inicial