# 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 ```typescript // Verificacion de limite de usuarios async canCreateUser(tenantId: string): Promise { 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 { 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 ```gherkin 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 ```gherkin 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 ```gherkin 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 ```gherkin 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 ```gherkin 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 ```gherkin 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 ```typescript // 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 ```typescript 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 ```typescript @Injectable() export class LimitGuard implements CanActivate { constructor( private subscriptionService: SubscriptionService, private reflector: Reflector, ) {} async canActivate(context: ExecutionContext): Promise { const limitType = this.reflector.get('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 |