- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Actualizaciones de configuracion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
235 lines
4.8 KiB
Markdown
235 lines
4.8 KiB
Markdown
---
|
|
id: "SAAS-005"
|
|
title: "Planes y Limites"
|
|
type: "Module"
|
|
status: "Published"
|
|
priority: "P0"
|
|
module: "plans"
|
|
version: "1.0.0"
|
|
created_date: "2026-01-07"
|
|
updated_date: "2026-01-10"
|
|
---
|
|
|
|
# SAAS-005: Planes y Limites
|
|
|
|
## Metadata
|
|
- **Codigo:** SAAS-005
|
|
- **Modulo:** Plans
|
|
- **Prioridad:** P0
|
|
- **Estado:** Completado
|
|
- **Fase:** 2 - Billing
|
|
|
|
## Descripcion
|
|
|
|
Sistema de planes y limites: definicion de planes con features y limites, verificacion de limites en runtime, y feature gating basado en plan.
|
|
|
|
## Objetivos
|
|
|
|
1. Definir planes (Free, Starter, Pro, Enterprise)
|
|
2. Features por plan
|
|
3. Limites configurables
|
|
4. Verificacion en runtime
|
|
5. Feature gating
|
|
|
|
## Alcance
|
|
|
|
### Incluido
|
|
- 4 planes predefinidos
|
|
- Features booleanas por plan
|
|
- Limites numericos por plan
|
|
- Funciones de verificacion
|
|
- Middleware de plan
|
|
|
|
### Excluido
|
|
- Planes custom por tenant
|
|
- Addons/complementos
|
|
- Overage charges
|
|
|
|
## Planes Definidos
|
|
|
|
### Free
|
|
```yaml
|
|
price: $0/mes
|
|
features:
|
|
- basic_dashboard: true
|
|
- api_access: false
|
|
- ai_assistant: false
|
|
- webhooks: false
|
|
- custom_branding: false
|
|
limits:
|
|
users: 1
|
|
storage_mb: 100
|
|
api_calls_month: 1000
|
|
```
|
|
|
|
### Starter ($29/mes)
|
|
```yaml
|
|
price: $29/mes | $290/ano
|
|
features:
|
|
- basic_dashboard: true
|
|
- api_access: true
|
|
- ai_assistant: false
|
|
- webhooks: false
|
|
- custom_branding: false
|
|
limits:
|
|
users: 5
|
|
storage_mb: 1000
|
|
api_calls_month: 10000
|
|
```
|
|
|
|
### Pro ($79/mes)
|
|
```yaml
|
|
price: $79/mes | $790/ano
|
|
features:
|
|
- basic_dashboard: true
|
|
- api_access: true
|
|
- ai_assistant: true
|
|
- webhooks: true
|
|
- custom_branding: false
|
|
limits:
|
|
users: 20
|
|
storage_mb: 10000
|
|
api_calls_month: 100000
|
|
ai_tokens_month: 50000
|
|
```
|
|
|
|
### Enterprise ($199/mes)
|
|
```yaml
|
|
price: $199/mes | $1990/ano
|
|
features:
|
|
- basic_dashboard: true
|
|
- api_access: true
|
|
- ai_assistant: true
|
|
- webhooks: true
|
|
- custom_branding: true
|
|
- sso: true
|
|
- audit_logs: true
|
|
limits:
|
|
users: unlimited
|
|
storage_mb: unlimited
|
|
api_calls_month: unlimited
|
|
ai_tokens_month: 200000
|
|
```
|
|
|
|
## Modelo de Datos
|
|
|
|
### Tablas (schema: plans)
|
|
|
|
**plans**
|
|
- id, name, code, description
|
|
- price_monthly, price_yearly, currency
|
|
- features (JSONB), limits (JSONB)
|
|
- stripe_monthly_price_id, stripe_yearly_price_id
|
|
- is_active, sort_order
|
|
|
|
**plan_features** (opcional, para tracking)
|
|
- id, plan_id, feature_key
|
|
- enabled, config
|
|
|
|
## Funciones de Verificacion
|
|
|
|
### SQL Functions
|
|
```sql
|
|
-- Obtener limites del tenant
|
|
CREATE FUNCTION get_tenant_limits(p_tenant_id UUID)
|
|
RETURNS JSONB AS $$
|
|
SELECT p.limits
|
|
FROM subscriptions s
|
|
JOIN plans p ON s.plan_id = p.id
|
|
WHERE s.tenant_id = p_tenant_id
|
|
AND s.status = 'active';
|
|
$$ LANGUAGE SQL;
|
|
|
|
-- Verificar limite
|
|
CREATE FUNCTION check_limit(
|
|
p_tenant_id UUID,
|
|
p_limit_key TEXT,
|
|
p_current_value INT
|
|
) RETURNS BOOLEAN AS $$
|
|
SELECT CASE
|
|
WHEN (get_tenant_limits(p_tenant_id)->>p_limit_key)::INT = -1 THEN true
|
|
ELSE p_current_value < (get_tenant_limits(p_tenant_id)->>p_limit_key)::INT
|
|
END;
|
|
$$ LANGUAGE SQL;
|
|
```
|
|
|
|
### Backend Service
|
|
```typescript
|
|
class PlansService {
|
|
async hasFeature(tenantId: string, feature: string): Promise<boolean> {
|
|
const plan = await this.getTenantPlan(tenantId);
|
|
return plan.features[feature] === true;
|
|
}
|
|
|
|
async checkLimit(tenantId: string, limit: string, current: number): Promise<boolean> {
|
|
const plan = await this.getTenantPlan(tenantId);
|
|
const max = plan.limits[limit];
|
|
return max === -1 || current < max; // -1 = unlimited
|
|
}
|
|
}
|
|
```
|
|
|
|
## Endpoints API
|
|
|
|
| Metodo | Endpoint | Descripcion |
|
|
|--------|----------|-------------|
|
|
| GET | /plans | Listar planes |
|
|
| GET | /plans/:code | Obtener plan |
|
|
| GET | /plans/current | Plan actual del tenant |
|
|
| GET | /plans/current/limits | Limites actuales |
|
|
| GET | /plans/current/usage | Uso actual |
|
|
|
|
## Guards y Decorators
|
|
|
|
```typescript
|
|
// Guard de feature
|
|
@RequiresFeature('ai_assistant')
|
|
async askAI(question: string) {
|
|
// Solo ejecuta si tiene feature
|
|
}
|
|
|
|
// Guard de plan minimo
|
|
@RequiresPlan('pro')
|
|
async advancedReport() {
|
|
// Solo Pro o superior
|
|
}
|
|
|
|
// Verificacion de limite
|
|
@CheckLimit('users')
|
|
async createUser(dto: CreateUserDto) {
|
|
// Verifica antes de crear
|
|
}
|
|
```
|
|
|
|
## Entregables
|
|
|
|
| Entregable | Estado | Archivo |
|
|
|------------|--------|---------|
|
|
| plans.service.ts | Completado | `modules/plans/` |
|
|
| plan.guard.ts | Completado | `guards/` |
|
|
| Seeds de planes | Completado | `seeds/prod/plans.sql` |
|
|
| DDL plans schema | Completado | `ddl/schemas/plans/` |
|
|
|
|
## Dependencias
|
|
|
|
### Depende de
|
|
- SAAS-002 (Tenants)
|
|
- SAAS-004 (Billing - para suscripcion)
|
|
|
|
### Bloquea a
|
|
- SAAS-003 (Users - limite usuarios)
|
|
- SAAS-006 (AI - feature flag)
|
|
- SAAS-010 (Webhooks - feature flag)
|
|
|
|
## Criterios de Aceptacion
|
|
|
|
- [x] 4 planes creados en BD
|
|
- [x] Features se verifican correctamente
|
|
- [x] Limites se respetan
|
|
- [x] Upgrade desbloquea features
|
|
- [x] UI muestra plan actual
|
|
|
|
---
|
|
|
|
**Ultima actualizacion:** 2026-01-10
|