[SAAS-018-022] docs: Add specifications for advanced modules
Add complete specifications for 5 advanced modules: - SAAS-018 Sales Foundation (21 SP) - Leads, opportunities, pipeline - SAAS-019 Portfolio (13 SP) - Product/service catalog - SAAS-020 Commissions (13 SP) - Commission system for salespeople - SAAS-021 MLM (21 SP) - Multi-level marketing networks - SAAS-022 Goals (13 SP) - Goals and objectives tracking Each specification includes: - Complete DDL with RLS policies - Full API endpoint documentation - Frontend pages and components - Dependencies and integration points - Story point estimates Total new SP: 81 (bringing total to 260 SP) Core modules: 14 (100% complete) Advanced modules: 5 (specified, ready for implementation) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
56e9134e52
commit
7d05081b4d
333
docs/01-modulos/SAAS-018-sales.md
Normal file
333
docs/01-modulos/SAAS-018-sales.md
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
---
|
||||||
|
id: "SAAS-018"
|
||||||
|
title: "Sales Foundation"
|
||||||
|
type: "Module"
|
||||||
|
status: "Specified"
|
||||||
|
priority: "P2"
|
||||||
|
module: "sales"
|
||||||
|
version: "1.0.0"
|
||||||
|
created_date: "2026-01-24"
|
||||||
|
updated_date: "2026-01-24"
|
||||||
|
estimated_sp: 21
|
||||||
|
---
|
||||||
|
|
||||||
|
# SAAS-018: Sales Foundation
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
- **Codigo:** SAAS-018
|
||||||
|
- **Modulo:** Sales
|
||||||
|
- **Prioridad:** P2
|
||||||
|
- **Estado:** Especificado
|
||||||
|
- **Fase:** 6 - Advanced Features
|
||||||
|
- **Story Points:** 21
|
||||||
|
|
||||||
|
## Descripcion
|
||||||
|
|
||||||
|
Modulo base de ventas para plataformas SaaS. Proporciona gestion de leads, oportunidades, pipeline de ventas, y seguimiento de actividades comerciales. Diseñado para ser extendido por verticales ERP.
|
||||||
|
|
||||||
|
## Objetivos
|
||||||
|
|
||||||
|
1. Gestionar leads y contactos comerciales
|
||||||
|
2. Pipeline de oportunidades con etapas configurables
|
||||||
|
3. Seguimiento de actividades (llamadas, emails, reuniones)
|
||||||
|
4. Reportes de ventas y conversion
|
||||||
|
5. Integracion con billing para cerrar ventas
|
||||||
|
|
||||||
|
## Alcance
|
||||||
|
|
||||||
|
### Incluido
|
||||||
|
- CRUD de leads con scoring automatico
|
||||||
|
- Pipeline de oportunidades (kanban)
|
||||||
|
- Etapas configurables por tenant
|
||||||
|
- Actividades y seguimiento
|
||||||
|
- Conversion lead -> cliente
|
||||||
|
- Dashboard de ventas
|
||||||
|
- Reportes basicos (conversion, tiempo ciclo)
|
||||||
|
- Integracion con notifications
|
||||||
|
|
||||||
|
### Excluido
|
||||||
|
- CRM completo (erp-core)
|
||||||
|
- Cotizaciones/Propuestas (erp-core)
|
||||||
|
- Productos y catalogo (portfolio module)
|
||||||
|
- Facturacion (billing module existente)
|
||||||
|
|
||||||
|
## Modelo de Datos
|
||||||
|
|
||||||
|
### Schema: sales
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Leads
|
||||||
|
CREATE TABLE sales.leads (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
-- Contacto
|
||||||
|
first_name VARCHAR(100) NOT NULL,
|
||||||
|
last_name VARCHAR(100),
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
phone VARCHAR(50),
|
||||||
|
company VARCHAR(200),
|
||||||
|
job_title VARCHAR(100),
|
||||||
|
|
||||||
|
-- Origen y scoring
|
||||||
|
source sales.lead_source NOT NULL DEFAULT 'manual',
|
||||||
|
score INTEGER DEFAULT 0,
|
||||||
|
status sales.lead_status NOT NULL DEFAULT 'new',
|
||||||
|
|
||||||
|
-- Asignacion
|
||||||
|
assigned_to UUID REFERENCES users.users(id),
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
tags JSONB DEFAULT '[]',
|
||||||
|
custom_fields JSONB DEFAULT '{}',
|
||||||
|
notes TEXT,
|
||||||
|
|
||||||
|
-- Conversion
|
||||||
|
converted_at TIMESTAMPTZ,
|
||||||
|
converted_to_opportunity_id UUID,
|
||||||
|
|
||||||
|
-- Audit
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
created_by UUID REFERENCES users.users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Oportunidades
|
||||||
|
CREATE TABLE sales.opportunities (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
-- Info basica
|
||||||
|
name VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
|
||||||
|
-- Pipeline
|
||||||
|
stage_id UUID NOT NULL REFERENCES sales.pipeline_stages(id),
|
||||||
|
probability INTEGER DEFAULT 0 CHECK (probability >= 0 AND probability <= 100),
|
||||||
|
|
||||||
|
-- Valores
|
||||||
|
amount DECIMAL(15,2) DEFAULT 0,
|
||||||
|
currency VARCHAR(3) DEFAULT 'USD',
|
||||||
|
expected_close_date DATE,
|
||||||
|
|
||||||
|
-- Relaciones
|
||||||
|
lead_id UUID REFERENCES sales.leads(id),
|
||||||
|
contact_email VARCHAR(255),
|
||||||
|
company VARCHAR(200),
|
||||||
|
|
||||||
|
-- Asignacion
|
||||||
|
assigned_to UUID REFERENCES users.users(id),
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status sales.opportunity_status NOT NULL DEFAULT 'open',
|
||||||
|
won_at TIMESTAMPTZ,
|
||||||
|
lost_at TIMESTAMPTZ,
|
||||||
|
lost_reason VARCHAR(500),
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
tags JSONB DEFAULT '[]',
|
||||||
|
custom_fields JSONB DEFAULT '{}',
|
||||||
|
|
||||||
|
-- Audit
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Etapas del pipeline
|
||||||
|
CREATE TABLE sales.pipeline_stages (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
position INTEGER NOT NULL DEFAULT 0,
|
||||||
|
probability INTEGER DEFAULT 0,
|
||||||
|
color VARCHAR(7) DEFAULT '#3B82F6',
|
||||||
|
|
||||||
|
is_won BOOLEAN DEFAULT false,
|
||||||
|
is_lost BOOLEAN DEFAULT false,
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Actividades
|
||||||
|
CREATE TABLE sales.activities (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
-- Tipo y descripcion
|
||||||
|
type sales.activity_type NOT NULL,
|
||||||
|
subject VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
|
||||||
|
-- Relacion polimorfica
|
||||||
|
related_type VARCHAR(50) NOT NULL, -- 'lead' | 'opportunity'
|
||||||
|
related_id UUID NOT NULL,
|
||||||
|
|
||||||
|
-- Programacion
|
||||||
|
due_date TIMESTAMPTZ,
|
||||||
|
completed_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Asignacion
|
||||||
|
assigned_to UUID REFERENCES users.users(id),
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
outcome TEXT,
|
||||||
|
duration_minutes INTEGER,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
created_by UUID REFERENCES users.users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Enums
|
||||||
|
CREATE TYPE sales.lead_source AS ENUM (
|
||||||
|
'manual', 'website', 'referral', 'campaign',
|
||||||
|
'social', 'trade_show', 'cold_call', 'other'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE sales.lead_status AS ENUM (
|
||||||
|
'new', 'contacted', 'qualified', 'unqualified', 'converted'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE sales.opportunity_status AS ENUM (
|
||||||
|
'open', 'won', 'lost'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE sales.activity_type AS ENUM (
|
||||||
|
'call', 'email', 'meeting', 'task', 'note', 'demo'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### RLS Policies
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE sales.leads ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE sales.opportunities ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE sales.pipeline_stages ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE sales.activities ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
CREATE POLICY tenant_isolation ON sales.leads
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant_id')::UUID);
|
||||||
|
-- (Similar for other tables)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints API
|
||||||
|
|
||||||
|
### Leads
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /sales/leads | Listar leads con filtros |
|
||||||
|
| POST | /sales/leads | Crear lead |
|
||||||
|
| GET | /sales/leads/:id | Obtener lead |
|
||||||
|
| PATCH | /sales/leads/:id | Actualizar lead |
|
||||||
|
| DELETE | /sales/leads/:id | Eliminar lead |
|
||||||
|
| POST | /sales/leads/:id/convert | Convertir a oportunidad |
|
||||||
|
| POST | /sales/leads/import | Importar leads (CSV) |
|
||||||
|
|
||||||
|
### Opportunities
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /sales/opportunities | Listar oportunidades |
|
||||||
|
| POST | /sales/opportunities | Crear oportunidad |
|
||||||
|
| GET | /sales/opportunities/:id | Obtener oportunidad |
|
||||||
|
| PATCH | /sales/opportunities/:id | Actualizar oportunidad |
|
||||||
|
| DELETE | /sales/opportunities/:id | Eliminar oportunidad |
|
||||||
|
| PATCH | /sales/opportunities/:id/stage | Mover de etapa |
|
||||||
|
| POST | /sales/opportunities/:id/won | Marcar como ganada |
|
||||||
|
| POST | /sales/opportunities/:id/lost | Marcar como perdida |
|
||||||
|
|
||||||
|
### Pipeline
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /sales/pipeline/stages | Listar etapas |
|
||||||
|
| POST | /sales/pipeline/stages | Crear etapa |
|
||||||
|
| PATCH | /sales/pipeline/stages/:id | Actualizar etapa |
|
||||||
|
| DELETE | /sales/pipeline/stages/:id | Eliminar etapa |
|
||||||
|
| POST | /sales/pipeline/stages/reorder | Reordenar etapas |
|
||||||
|
|
||||||
|
### Activities
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /sales/activities | Listar actividades |
|
||||||
|
| POST | /sales/activities | Crear actividad |
|
||||||
|
| PATCH | /sales/activities/:id | Actualizar actividad |
|
||||||
|
| DELETE | /sales/activities/:id | Eliminar actividad |
|
||||||
|
| POST | /sales/activities/:id/complete | Marcar completada |
|
||||||
|
|
||||||
|
### Reports
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /sales/reports/pipeline | Reporte pipeline |
|
||||||
|
| GET | /sales/reports/conversion | Tasa de conversion |
|
||||||
|
| GET | /sales/reports/forecast | Forecast de ventas |
|
||||||
|
|
||||||
|
## Frontend
|
||||||
|
|
||||||
|
### Paginas
|
||||||
|
- `/sales` - Dashboard de ventas
|
||||||
|
- `/sales/leads` - Lista de leads
|
||||||
|
- `/sales/leads/:id` - Detalle de lead
|
||||||
|
- `/sales/opportunities` - Pipeline kanban
|
||||||
|
- `/sales/opportunities/:id` - Detalle de oportunidad
|
||||||
|
- `/sales/activities` - Calendario/lista de actividades
|
||||||
|
- `/sales/reports` - Reportes
|
||||||
|
|
||||||
|
### Componentes
|
||||||
|
- `LeadsList` - Tabla de leads con filtros
|
||||||
|
- `LeadForm` - Formulario crear/editar lead
|
||||||
|
- `LeadDetail` - Vista detalle con timeline
|
||||||
|
- `OpportunityKanban` - Pipeline drag & drop
|
||||||
|
- `OpportunityCard` - Tarjeta en kanban
|
||||||
|
- `OpportunityDetail` - Vista detalle con actividades
|
||||||
|
- `ActivityTimeline` - Timeline de actividades
|
||||||
|
- `ActivityForm` - Formulario de actividad
|
||||||
|
- `SalesDashboard` - Metricas y graficos
|
||||||
|
- `ConversionFunnel` - Visualizacion embudo
|
||||||
|
|
||||||
|
### Hooks
|
||||||
|
- `useLeads` - CRUD leads
|
||||||
|
- `useOpportunities` - CRUD oportunidades
|
||||||
|
- `usePipeline` - Gestion pipeline
|
||||||
|
- `useActivities` - CRUD actividades
|
||||||
|
- `useSalesReports` - Reportes
|
||||||
|
|
||||||
|
## Dependencias
|
||||||
|
|
||||||
|
### Modulos Requeridos
|
||||||
|
- SAAS-001 Auth (autenticacion)
|
||||||
|
- SAAS-002 Tenants (multi-tenancy)
|
||||||
|
- SAAS-003 Users (usuarios y asignacion)
|
||||||
|
- SAAS-007 Notifications (alertas de actividades)
|
||||||
|
|
||||||
|
### Modulos Opcionales
|
||||||
|
- SAAS-019 Portfolio (productos en oportunidades)
|
||||||
|
- SAAS-020 Commissions (comisiones por venta)
|
||||||
|
|
||||||
|
## Criterios de Aceptacion
|
||||||
|
|
||||||
|
1. [ ] CRUD completo de leads con validaciones
|
||||||
|
2. [ ] Pipeline kanban con drag & drop
|
||||||
|
3. [ ] Conversion lead -> oportunidad funcional
|
||||||
|
4. [ ] Sistema de actividades con recordatorios
|
||||||
|
5. [ ] Dashboard con metricas clave
|
||||||
|
6. [ ] Reportes de conversion y forecast
|
||||||
|
7. [ ] Tests unitarios (>70% coverage)
|
||||||
|
8. [ ] Documentacion API (Swagger)
|
||||||
|
|
||||||
|
## Estimacion
|
||||||
|
|
||||||
|
| Componente | SP |
|
||||||
|
|------------|-----|
|
||||||
|
| DDL + Entities | 3 |
|
||||||
|
| Backend Services | 5 |
|
||||||
|
| Controllers + DTOs | 3 |
|
||||||
|
| Frontend Pages | 5 |
|
||||||
|
| Frontend Components | 3 |
|
||||||
|
| Tests | 2 |
|
||||||
|
| **Total** | **21** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ultima actualizacion:** 2026-01-24
|
||||||
|
**Autor:** Claude Opus 4.5
|
||||||
296
docs/01-modulos/SAAS-019-portfolio.md
Normal file
296
docs/01-modulos/SAAS-019-portfolio.md
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
---
|
||||||
|
id: "SAAS-019"
|
||||||
|
title: "Portfolio"
|
||||||
|
type: "Module"
|
||||||
|
status: "Specified"
|
||||||
|
priority: "P2"
|
||||||
|
module: "portfolio"
|
||||||
|
version: "1.0.0"
|
||||||
|
created_date: "2026-01-24"
|
||||||
|
updated_date: "2026-01-24"
|
||||||
|
estimated_sp: 13
|
||||||
|
---
|
||||||
|
|
||||||
|
# SAAS-019: Portfolio
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
- **Codigo:** SAAS-019
|
||||||
|
- **Modulo:** Portfolio
|
||||||
|
- **Prioridad:** P2
|
||||||
|
- **Estado:** Especificado
|
||||||
|
- **Fase:** 6 - Advanced Features
|
||||||
|
- **Story Points:** 13
|
||||||
|
|
||||||
|
## Descripcion
|
||||||
|
|
||||||
|
Catalogo de productos y servicios para plataformas SaaS. Permite definir ofertas, precios, categorias y variantes. Se integra con Sales para cotizaciones y con Billing para suscripciones basadas en productos.
|
||||||
|
|
||||||
|
## Objetivos
|
||||||
|
|
||||||
|
1. Catalogo de productos/servicios configurable
|
||||||
|
2. Categorias y subcategorias jerarquicas
|
||||||
|
3. Precios con multiples monedas
|
||||||
|
4. Variantes de productos (tallas, colores, etc.)
|
||||||
|
5. Integracion con Sales y Billing
|
||||||
|
|
||||||
|
## Alcance
|
||||||
|
|
||||||
|
### Incluido
|
||||||
|
- CRUD de productos/servicios
|
||||||
|
- Categorias jerarquicas
|
||||||
|
- Precios por moneda
|
||||||
|
- Variantes basicas
|
||||||
|
- Imagenes de productos
|
||||||
|
- Productos activos/inactivos
|
||||||
|
- Busqueda y filtros
|
||||||
|
- Exportacion catalogo
|
||||||
|
|
||||||
|
### Excluido
|
||||||
|
- Inventario (erp-core)
|
||||||
|
- Ordenes de compra (erp-core)
|
||||||
|
- Proveedores (erp-core)
|
||||||
|
- Configurador de productos complejo
|
||||||
|
|
||||||
|
## Modelo de Datos
|
||||||
|
|
||||||
|
### Schema: portfolio
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Categorias
|
||||||
|
CREATE TABLE portfolio.categories (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
slug VARCHAR(100) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
parent_id UUID REFERENCES portfolio.categories(id),
|
||||||
|
|
||||||
|
image_url VARCHAR(500),
|
||||||
|
position INTEGER DEFAULT 0,
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
CONSTRAINT unique_category_slug UNIQUE (tenant_id, slug)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Productos
|
||||||
|
CREATE TABLE portfolio.products (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
-- Info basica
|
||||||
|
name VARCHAR(200) NOT NULL,
|
||||||
|
slug VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
short_description VARCHAR(500),
|
||||||
|
|
||||||
|
-- Clasificacion
|
||||||
|
type portfolio.product_type NOT NULL DEFAULT 'product',
|
||||||
|
category_id UUID REFERENCES portfolio.categories(id),
|
||||||
|
|
||||||
|
-- Codigo
|
||||||
|
sku VARCHAR(100),
|
||||||
|
barcode VARCHAR(100),
|
||||||
|
|
||||||
|
-- Precios
|
||||||
|
base_price DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||||||
|
currency VARCHAR(3) DEFAULT 'USD',
|
||||||
|
tax_rate DECIMAL(5,2) DEFAULT 0,
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status portfolio.product_status NOT NULL DEFAULT 'draft',
|
||||||
|
is_featured BOOLEAN DEFAULT false,
|
||||||
|
|
||||||
|
-- Media
|
||||||
|
images JSONB DEFAULT '[]',
|
||||||
|
thumbnail_url VARCHAR(500),
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
tags JSONB DEFAULT '[]',
|
||||||
|
attributes JSONB DEFAULT '{}',
|
||||||
|
meta_title VARCHAR(200),
|
||||||
|
meta_description VARCHAR(500),
|
||||||
|
|
||||||
|
-- Audit
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
CONSTRAINT unique_product_slug UNIQUE (tenant_id, slug),
|
||||||
|
CONSTRAINT unique_product_sku UNIQUE (tenant_id, sku)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Variantes
|
||||||
|
CREATE TABLE portfolio.variants (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
product_id UUID NOT NULL REFERENCES portfolio.products(id) ON DELETE CASCADE,
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
name VARCHAR(200) NOT NULL,
|
||||||
|
sku VARCHAR(100),
|
||||||
|
|
||||||
|
-- Precio diferencial
|
||||||
|
price_adjustment DECIMAL(15,2) DEFAULT 0,
|
||||||
|
price_type portfolio.price_type DEFAULT 'adjustment', -- 'adjustment' | 'fixed'
|
||||||
|
|
||||||
|
-- Atributos (color, talla, etc.)
|
||||||
|
attributes JSONB NOT NULL DEFAULT '{}',
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Precios por moneda
|
||||||
|
CREATE TABLE portfolio.prices (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
product_id UUID NOT NULL REFERENCES portfolio.products(id) ON DELETE CASCADE,
|
||||||
|
variant_id UUID REFERENCES portfolio.variants(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
currency VARCHAR(3) NOT NULL,
|
||||||
|
amount DECIMAL(15,2) NOT NULL,
|
||||||
|
|
||||||
|
-- Precios especiales
|
||||||
|
compare_at_price DECIMAL(15,2), -- Precio tachado
|
||||||
|
cost_price DECIMAL(15,2), -- Costo
|
||||||
|
|
||||||
|
-- Vigencia
|
||||||
|
starts_at TIMESTAMPTZ,
|
||||||
|
ends_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
CONSTRAINT unique_price UNIQUE (product_id, variant_id, currency)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Enums
|
||||||
|
CREATE TYPE portfolio.product_type AS ENUM (
|
||||||
|
'product', 'service', 'digital', 'subscription'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE portfolio.product_status AS ENUM (
|
||||||
|
'draft', 'active', 'inactive', 'archived'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE portfolio.price_type AS ENUM (
|
||||||
|
'adjustment', 'fixed'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### RLS Policies
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE portfolio.categories ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE portfolio.products ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE portfolio.variants ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE portfolio.prices ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
CREATE POLICY tenant_isolation ON portfolio.products
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant_id')::UUID);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints API
|
||||||
|
|
||||||
|
### Categories
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /portfolio/categories | Listar categorias |
|
||||||
|
| POST | /portfolio/categories | Crear categoria |
|
||||||
|
| GET | /portfolio/categories/:id | Obtener categoria |
|
||||||
|
| PATCH | /portfolio/categories/:id | Actualizar categoria |
|
||||||
|
| DELETE | /portfolio/categories/:id | Eliminar categoria |
|
||||||
|
| GET | /portfolio/categories/tree | Arbol jerarquico |
|
||||||
|
|
||||||
|
### Products
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /portfolio/products | Listar productos |
|
||||||
|
| POST | /portfolio/products | Crear producto |
|
||||||
|
| GET | /portfolio/products/:id | Obtener producto |
|
||||||
|
| PATCH | /portfolio/products/:id | Actualizar producto |
|
||||||
|
| DELETE | /portfolio/products/:id | Eliminar producto |
|
||||||
|
| POST | /portfolio/products/:id/duplicate | Duplicar producto |
|
||||||
|
| PATCH | /portfolio/products/:id/status | Cambiar estado |
|
||||||
|
|
||||||
|
### Variants
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /portfolio/products/:id/variants | Listar variantes |
|
||||||
|
| POST | /portfolio/products/:id/variants | Crear variante |
|
||||||
|
| PATCH | /portfolio/variants/:id | Actualizar variante |
|
||||||
|
| DELETE | /portfolio/variants/:id | Eliminar variante |
|
||||||
|
|
||||||
|
### Prices
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /portfolio/products/:id/prices | Listar precios |
|
||||||
|
| POST | /portfolio/products/:id/prices | Agregar precio |
|
||||||
|
| PATCH | /portfolio/prices/:id | Actualizar precio |
|
||||||
|
| DELETE | /portfolio/prices/:id | Eliminar precio |
|
||||||
|
|
||||||
|
## Frontend
|
||||||
|
|
||||||
|
### Paginas
|
||||||
|
- `/portfolio` - Dashboard catalogo
|
||||||
|
- `/portfolio/products` - Lista de productos
|
||||||
|
- `/portfolio/products/new` - Crear producto
|
||||||
|
- `/portfolio/products/:id` - Editar producto
|
||||||
|
- `/portfolio/categories` - Gestion categorias
|
||||||
|
|
||||||
|
### Componentes
|
||||||
|
- `ProductsList` - Tabla/grid de productos
|
||||||
|
- `ProductForm` - Formulario producto completo
|
||||||
|
- `ProductCard` - Tarjeta preview
|
||||||
|
- `VariantsManager` - Gestion variantes
|
||||||
|
- `PricesManager` - Gestion precios multi-moneda
|
||||||
|
- `CategoryTree` - Arbol de categorias
|
||||||
|
- `CategoryForm` - Formulario categoria
|
||||||
|
- `ImageUploader` - Subida de imagenes
|
||||||
|
- `ProductSearch` - Busqueda avanzada
|
||||||
|
|
||||||
|
### Hooks
|
||||||
|
- `useProducts` - CRUD productos
|
||||||
|
- `useCategories` - CRUD categorias
|
||||||
|
- `useVariants` - CRUD variantes
|
||||||
|
- `usePrices` - CRUD precios
|
||||||
|
|
||||||
|
## Dependencias
|
||||||
|
|
||||||
|
### Modulos Requeridos
|
||||||
|
- SAAS-001 Auth
|
||||||
|
- SAAS-002 Tenants
|
||||||
|
- SAAS-011 Storage (imagenes)
|
||||||
|
|
||||||
|
### Modulos Opcionales
|
||||||
|
- SAAS-018 Sales (productos en oportunidades)
|
||||||
|
- SAAS-004 Billing (suscripciones)
|
||||||
|
|
||||||
|
## Criterios de Aceptacion
|
||||||
|
|
||||||
|
1. [ ] CRUD productos con validaciones
|
||||||
|
2. [ ] Categorias jerarquicas funcionales
|
||||||
|
3. [ ] Variantes con atributos dinamicos
|
||||||
|
4. [ ] Precios multi-moneda
|
||||||
|
5. [ ] Subida de imagenes integrada
|
||||||
|
6. [ ] Busqueda y filtros avanzados
|
||||||
|
7. [ ] Tests unitarios (>70% coverage)
|
||||||
|
|
||||||
|
## Estimacion
|
||||||
|
|
||||||
|
| Componente | SP |
|
||||||
|
|------------|-----|
|
||||||
|
| DDL + Entities | 2 |
|
||||||
|
| Backend Services | 3 |
|
||||||
|
| Controllers + DTOs | 2 |
|
||||||
|
| Frontend Pages | 3 |
|
||||||
|
| Frontend Components | 2 |
|
||||||
|
| Tests | 1 |
|
||||||
|
| **Total** | **13** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ultima actualizacion:** 2026-01-24
|
||||||
|
**Autor:** Claude Opus 4.5
|
||||||
299
docs/01-modulos/SAAS-020-commissions.md
Normal file
299
docs/01-modulos/SAAS-020-commissions.md
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
---
|
||||||
|
id: "SAAS-020"
|
||||||
|
title: "Commissions"
|
||||||
|
type: "Module"
|
||||||
|
status: "Specified"
|
||||||
|
priority: "P2"
|
||||||
|
module: "commissions"
|
||||||
|
version: "1.0.0"
|
||||||
|
created_date: "2026-01-24"
|
||||||
|
updated_date: "2026-01-24"
|
||||||
|
estimated_sp: 13
|
||||||
|
---
|
||||||
|
|
||||||
|
# SAAS-020: Commissions
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
- **Codigo:** SAAS-020
|
||||||
|
- **Modulo:** Commissions
|
||||||
|
- **Prioridad:** P2
|
||||||
|
- **Estado:** Especificado
|
||||||
|
- **Fase:** 6 - Advanced Features
|
||||||
|
- **Story Points:** 13
|
||||||
|
|
||||||
|
## Descripcion
|
||||||
|
|
||||||
|
Sistema de comisiones para vendedores y afiliados. Soporta multiples esquemas de comision (porcentaje, fijo, escalonado), periodos de pago configurables, y reportes de earnings. Base para el modulo MLM.
|
||||||
|
|
||||||
|
## Objetivos
|
||||||
|
|
||||||
|
1. Definir esquemas de comision flexibles
|
||||||
|
2. Calcular comisiones automaticamente por venta
|
||||||
|
3. Gestionar periodos de pago
|
||||||
|
4. Reportes de comisiones por vendedor
|
||||||
|
5. Integracion con Billing para pagos
|
||||||
|
|
||||||
|
## Alcance
|
||||||
|
|
||||||
|
### Incluido
|
||||||
|
- Esquemas de comision configurables
|
||||||
|
- Tipos: porcentaje, fijo, escalonado
|
||||||
|
- Calculo automatico por transaccion
|
||||||
|
- Periodos de pago (semanal, quincenal, mensual)
|
||||||
|
- Estado de comisiones (pendiente, aprobada, pagada)
|
||||||
|
- Dashboard de earnings
|
||||||
|
- Reportes por vendedor/periodo
|
||||||
|
|
||||||
|
### Excluido
|
||||||
|
- Pago automatico (integracion bancaria)
|
||||||
|
- Estructuras MLM complejas (SAAS-021)
|
||||||
|
- Impuestos sobre comisiones
|
||||||
|
|
||||||
|
## Modelo de Datos
|
||||||
|
|
||||||
|
### Schema: commissions
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Esquemas de comision
|
||||||
|
CREATE TABLE commissions.schemes (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
|
||||||
|
-- Tipo de calculo
|
||||||
|
type commissions.scheme_type NOT NULL,
|
||||||
|
|
||||||
|
-- Configuracion
|
||||||
|
rate DECIMAL(10,4), -- Porcentaje (ej: 0.10 = 10%)
|
||||||
|
fixed_amount DECIMAL(15,2), -- Monto fijo
|
||||||
|
tiers JSONB DEFAULT '[]', -- Para escalonado
|
||||||
|
|
||||||
|
-- Aplicabilidad
|
||||||
|
applies_to commissions.applies_to DEFAULT 'all',
|
||||||
|
product_ids JSONB DEFAULT '[]', -- Si applies_to = 'products'
|
||||||
|
category_ids JSONB DEFAULT '[]', -- Si applies_to = 'categories'
|
||||||
|
|
||||||
|
-- Limites
|
||||||
|
min_amount DECIMAL(15,2),
|
||||||
|
max_amount DECIMAL(15,2),
|
||||||
|
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Asignacion vendedor-esquema
|
||||||
|
CREATE TABLE commissions.assignments (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
user_id UUID NOT NULL REFERENCES users.users(id),
|
||||||
|
scheme_id UUID NOT NULL REFERENCES commissions.schemes(id),
|
||||||
|
|
||||||
|
-- Vigencia
|
||||||
|
starts_at DATE NOT NULL,
|
||||||
|
ends_at DATE,
|
||||||
|
|
||||||
|
-- Override de rate
|
||||||
|
custom_rate DECIMAL(10,4),
|
||||||
|
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
CONSTRAINT unique_assignment UNIQUE (user_id, scheme_id, starts_at)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Comisiones generadas
|
||||||
|
CREATE TABLE commissions.entries (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
-- Beneficiario
|
||||||
|
user_id UUID NOT NULL REFERENCES users.users(id),
|
||||||
|
scheme_id UUID REFERENCES commissions.schemes(id),
|
||||||
|
|
||||||
|
-- Transaccion origen
|
||||||
|
reference_type VARCHAR(50) NOT NULL, -- 'sale', 'subscription', 'referral'
|
||||||
|
reference_id UUID NOT NULL,
|
||||||
|
|
||||||
|
-- Montos
|
||||||
|
base_amount DECIMAL(15,2) NOT NULL, -- Monto de la venta
|
||||||
|
rate_applied DECIMAL(10,4) NOT NULL,
|
||||||
|
commission_amount DECIMAL(15,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) DEFAULT 'USD',
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status commissions.entry_status NOT NULL DEFAULT 'pending',
|
||||||
|
|
||||||
|
-- Periodo de pago
|
||||||
|
period_id UUID REFERENCES commissions.periods(id),
|
||||||
|
paid_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
notes TEXT,
|
||||||
|
metadata JSONB DEFAULT '{}',
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Periodos de pago
|
||||||
|
CREATE TABLE commissions.periods (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
starts_at DATE NOT NULL,
|
||||||
|
ends_at DATE NOT NULL,
|
||||||
|
|
||||||
|
-- Totales
|
||||||
|
total_entries INTEGER DEFAULT 0,
|
||||||
|
total_amount DECIMAL(15,2) DEFAULT 0,
|
||||||
|
currency VARCHAR(3) DEFAULT 'USD',
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status commissions.period_status NOT NULL DEFAULT 'open',
|
||||||
|
closed_at TIMESTAMPTZ,
|
||||||
|
paid_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Enums
|
||||||
|
CREATE TYPE commissions.scheme_type AS ENUM (
|
||||||
|
'percentage', 'fixed', 'tiered'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE commissions.applies_to AS ENUM (
|
||||||
|
'all', 'products', 'categories'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE commissions.entry_status AS ENUM (
|
||||||
|
'pending', 'approved', 'rejected', 'paid', 'cancelled'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE commissions.period_status AS ENUM (
|
||||||
|
'open', 'closed', 'processing', 'paid'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ejemplo Tiers (escalonado)
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{ "min": 0, "max": 10000, "rate": 0.05 },
|
||||||
|
{ "min": 10001, "max": 50000, "rate": 0.07 },
|
||||||
|
{ "min": 50001, "max": null, "rate": 0.10 }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints API
|
||||||
|
|
||||||
|
### Schemes
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /commissions/schemes | Listar esquemas |
|
||||||
|
| POST | /commissions/schemes | Crear esquema |
|
||||||
|
| GET | /commissions/schemes/:id | Obtener esquema |
|
||||||
|
| PATCH | /commissions/schemes/:id | Actualizar esquema |
|
||||||
|
| DELETE | /commissions/schemes/:id | Eliminar esquema |
|
||||||
|
|
||||||
|
### Assignments
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /commissions/assignments | Listar asignaciones |
|
||||||
|
| POST | /commissions/assignments | Asignar esquema |
|
||||||
|
| PATCH | /commissions/assignments/:id | Actualizar asignacion |
|
||||||
|
| DELETE | /commissions/assignments/:id | Eliminar asignacion |
|
||||||
|
| GET | /commissions/users/:id/schemes | Esquemas de usuario |
|
||||||
|
|
||||||
|
### Entries
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /commissions/entries | Listar comisiones |
|
||||||
|
| GET | /commissions/entries/:id | Obtener comision |
|
||||||
|
| PATCH | /commissions/entries/:id/status | Cambiar estado |
|
||||||
|
| POST | /commissions/calculate | Calcular comision |
|
||||||
|
|
||||||
|
### Periods
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /commissions/periods | Listar periodos |
|
||||||
|
| POST | /commissions/periods | Crear periodo |
|
||||||
|
| GET | /commissions/periods/:id | Obtener periodo |
|
||||||
|
| POST | /commissions/periods/:id/close | Cerrar periodo |
|
||||||
|
| POST | /commissions/periods/:id/pay | Marcar como pagado |
|
||||||
|
|
||||||
|
### Reports
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /commissions/reports/summary | Resumen general |
|
||||||
|
| GET | /commissions/reports/by-user | Por vendedor |
|
||||||
|
| GET | /commissions/reports/by-period | Por periodo |
|
||||||
|
|
||||||
|
## Frontend
|
||||||
|
|
||||||
|
### Paginas
|
||||||
|
- `/commissions` - Dashboard comisiones
|
||||||
|
- `/commissions/schemes` - Gestion esquemas
|
||||||
|
- `/commissions/entries` - Lista comisiones
|
||||||
|
- `/commissions/periods` - Periodos de pago
|
||||||
|
- `/commissions/my-earnings` - Mis ganancias (vendedor)
|
||||||
|
|
||||||
|
### Componentes
|
||||||
|
- `CommissionsDashboard` - Metricas y graficos
|
||||||
|
- `SchemesList` - Lista de esquemas
|
||||||
|
- `SchemeForm` - Formulario esquema
|
||||||
|
- `TiersEditor` - Editor de niveles
|
||||||
|
- `EntriesList` - Lista de comisiones
|
||||||
|
- `PeriodManager` - Gestion periodos
|
||||||
|
- `EarningsCard` - Resumen ganancias
|
||||||
|
- `CommissionCalculator` - Simulador
|
||||||
|
|
||||||
|
### Hooks
|
||||||
|
- `useSchemes` - CRUD esquemas
|
||||||
|
- `useAssignments` - CRUD asignaciones
|
||||||
|
- `useEntries` - CRUD comisiones
|
||||||
|
- `usePeriods` - CRUD periodos
|
||||||
|
- `useMyEarnings` - Ganancias del usuario actual
|
||||||
|
|
||||||
|
## Dependencias
|
||||||
|
|
||||||
|
### Modulos Requeridos
|
||||||
|
- SAAS-001 Auth
|
||||||
|
- SAAS-002 Tenants
|
||||||
|
- SAAS-003 Users
|
||||||
|
- SAAS-018 Sales (transacciones origen)
|
||||||
|
|
||||||
|
### Modulos Opcionales
|
||||||
|
- SAAS-004 Billing (pagos automaticos)
|
||||||
|
- SAAS-021 MLM (estructuras multinivel)
|
||||||
|
|
||||||
|
## Criterios de Aceptacion
|
||||||
|
|
||||||
|
1. [ ] Esquemas porcentaje, fijo y escalonado
|
||||||
|
2. [ ] Asignacion esquema-vendedor funcional
|
||||||
|
3. [ ] Calculo automatico de comisiones
|
||||||
|
4. [ ] Gestion de periodos de pago
|
||||||
|
5. [ ] Dashboard de earnings
|
||||||
|
6. [ ] Reportes por vendedor y periodo
|
||||||
|
7. [ ] Tests unitarios (>70% coverage)
|
||||||
|
|
||||||
|
## Estimacion
|
||||||
|
|
||||||
|
| Componente | SP |
|
||||||
|
|------------|-----|
|
||||||
|
| DDL + Entities | 2 |
|
||||||
|
| Backend Services | 4 |
|
||||||
|
| Controllers + DTOs | 2 |
|
||||||
|
| Frontend Pages | 3 |
|
||||||
|
| Frontend Components | 2 |
|
||||||
|
| Tests | 1 |
|
||||||
|
| **Total** | **13** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ultima actualizacion:** 2026-01-24
|
||||||
|
**Autor:** Claude Opus 4.5
|
||||||
347
docs/01-modulos/SAAS-021-mlm.md
Normal file
347
docs/01-modulos/SAAS-021-mlm.md
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
---
|
||||||
|
id: "SAAS-021"
|
||||||
|
title: "MLM (Multi-Level Marketing)"
|
||||||
|
type: "Module"
|
||||||
|
status: "Specified"
|
||||||
|
priority: "P3"
|
||||||
|
module: "mlm"
|
||||||
|
version: "1.0.0"
|
||||||
|
created_date: "2026-01-24"
|
||||||
|
updated_date: "2026-01-24"
|
||||||
|
estimated_sp: 21
|
||||||
|
---
|
||||||
|
|
||||||
|
# SAAS-021: MLM (Multi-Level Marketing)
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
- **Codigo:** SAAS-021
|
||||||
|
- **Modulo:** MLM
|
||||||
|
- **Prioridad:** P3
|
||||||
|
- **Estado:** Especificado
|
||||||
|
- **Fase:** 7 - Enterprise Features
|
||||||
|
- **Story Points:** 21
|
||||||
|
|
||||||
|
## Descripcion
|
||||||
|
|
||||||
|
Sistema de marketing multinivel para redes de distribuidores/afiliados. Soporta estructuras jerarquicas (binario, unilevel, matriz), comisiones por niveles, bonos por objetivos, y visualizacion de red. Extiende el modulo de Commissions.
|
||||||
|
|
||||||
|
## Objetivos
|
||||||
|
|
||||||
|
1. Estructuras de red configurables
|
||||||
|
2. Comisiones por niveles (downline)
|
||||||
|
3. Bonos por rangos y objetivos
|
||||||
|
4. Visualizacion de arbol de red
|
||||||
|
5. Reportes de estructura y earnings
|
||||||
|
|
||||||
|
## Alcance
|
||||||
|
|
||||||
|
### Incluido
|
||||||
|
- Estructuras: Unilevel, Binario, Matriz
|
||||||
|
- Comisiones multinivel (N niveles)
|
||||||
|
- Sistema de rangos/calificaciones
|
||||||
|
- Bonos por rango y periodo
|
||||||
|
- Visualizacion de red (arbol)
|
||||||
|
- Dashboard de distribuidor
|
||||||
|
- Reportes de red y earnings
|
||||||
|
|
||||||
|
### Excluido
|
||||||
|
- Planes de compensacion predefinidos
|
||||||
|
- Integracion con pagos automaticos
|
||||||
|
- Compliance regulatorio automatico
|
||||||
|
|
||||||
|
## Modelo de Datos
|
||||||
|
|
||||||
|
### Schema: mlm
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Configuracion de estructura
|
||||||
|
CREATE TABLE mlm.structures (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
type mlm.structure_type NOT NULL,
|
||||||
|
|
||||||
|
-- Configuracion por tipo
|
||||||
|
config JSONB NOT NULL DEFAULT '{}',
|
||||||
|
-- Unilevel: { max_width: null, max_depth: 10 }
|
||||||
|
-- Binary: { spillover: 'left_first' | 'weak_leg' }
|
||||||
|
-- Matrix: { width: 3, depth: 7 }
|
||||||
|
|
||||||
|
-- Comisiones por nivel
|
||||||
|
level_rates JSONB NOT NULL DEFAULT '[]',
|
||||||
|
-- [{ level: 1, rate: 0.10 }, { level: 2, rate: 0.05 }, ...]
|
||||||
|
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Nodos de la red (distribuidores)
|
||||||
|
CREATE TABLE mlm.nodes (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
structure_id UUID NOT NULL REFERENCES mlm.structures(id),
|
||||||
|
|
||||||
|
user_id UUID NOT NULL REFERENCES users.users(id),
|
||||||
|
|
||||||
|
-- Jerarquia
|
||||||
|
parent_id UUID REFERENCES mlm.nodes(id),
|
||||||
|
sponsor_id UUID REFERENCES mlm.nodes(id), -- Quien lo refirio
|
||||||
|
position INTEGER, -- Para binario: 1=left, 2=right
|
||||||
|
|
||||||
|
-- Path materializado para consultas eficientes
|
||||||
|
path LTREE,
|
||||||
|
depth INTEGER DEFAULT 0,
|
||||||
|
|
||||||
|
-- Rango actual
|
||||||
|
rank_id UUID REFERENCES mlm.ranks(id),
|
||||||
|
highest_rank_id UUID REFERENCES mlm.ranks(id),
|
||||||
|
|
||||||
|
-- Metricas
|
||||||
|
personal_volume DECIMAL(15,2) DEFAULT 0,
|
||||||
|
group_volume DECIMAL(15,2) DEFAULT 0,
|
||||||
|
direct_referrals INTEGER DEFAULT 0,
|
||||||
|
total_downline INTEGER DEFAULT 0,
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status mlm.node_status NOT NULL DEFAULT 'active',
|
||||||
|
joined_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
CONSTRAINT unique_user_structure UNIQUE (structure_id, user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Rangos/Calificaciones
|
||||||
|
CREATE TABLE mlm.ranks (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
structure_id UUID NOT NULL REFERENCES mlm.structures(id),
|
||||||
|
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
level INTEGER NOT NULL, -- 1=Bronze, 2=Silver, etc.
|
||||||
|
badge_url VARCHAR(500),
|
||||||
|
|
||||||
|
-- Requisitos para alcanzar
|
||||||
|
requirements JSONB NOT NULL DEFAULT '{}',
|
||||||
|
-- {
|
||||||
|
-- personal_volume: 1000,
|
||||||
|
-- group_volume: 10000,
|
||||||
|
-- direct_referrals: 3,
|
||||||
|
-- active_legs: 2,
|
||||||
|
-- rank_in_legs: { rank_level: 2, count: 1 }
|
||||||
|
-- }
|
||||||
|
|
||||||
|
-- Beneficios
|
||||||
|
bonus_rate DECIMAL(10,4), -- Bono adicional por rango
|
||||||
|
benefits JSONB DEFAULT '{}',
|
||||||
|
|
||||||
|
is_active BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Comisiones MLM (extiende commissions.entries)
|
||||||
|
CREATE TABLE mlm.commissions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
node_id UUID NOT NULL REFERENCES mlm.nodes(id),
|
||||||
|
source_node_id UUID NOT NULL REFERENCES mlm.nodes(id), -- Quien genero
|
||||||
|
|
||||||
|
-- Tipo de comision
|
||||||
|
type mlm.commission_type NOT NULL,
|
||||||
|
|
||||||
|
-- Nivel de diferencia
|
||||||
|
level INTEGER NOT NULL, -- 1 = directo, 2 = segundo nivel, etc.
|
||||||
|
|
||||||
|
-- Montos
|
||||||
|
source_amount DECIMAL(15,2) NOT NULL,
|
||||||
|
rate_applied DECIMAL(10,4) NOT NULL,
|
||||||
|
commission_amount DECIMAL(15,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) DEFAULT 'USD',
|
||||||
|
|
||||||
|
-- Periodo
|
||||||
|
period_id UUID REFERENCES commissions.periods(id),
|
||||||
|
status mlm.commission_status NOT NULL DEFAULT 'pending',
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Bonos por rango
|
||||||
|
CREATE TABLE mlm.bonuses (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
node_id UUID NOT NULL REFERENCES mlm.nodes(id),
|
||||||
|
rank_id UUID NOT NULL REFERENCES mlm.ranks(id),
|
||||||
|
|
||||||
|
type mlm.bonus_type NOT NULL,
|
||||||
|
amount DECIMAL(15,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) DEFAULT 'USD',
|
||||||
|
|
||||||
|
period_id UUID REFERENCES commissions.periods(id),
|
||||||
|
status mlm.commission_status NOT NULL DEFAULT 'pending',
|
||||||
|
|
||||||
|
achieved_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Historial de rangos
|
||||||
|
CREATE TABLE mlm.rank_history (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
node_id UUID NOT NULL REFERENCES mlm.nodes(id),
|
||||||
|
rank_id UUID NOT NULL REFERENCES mlm.ranks(id),
|
||||||
|
achieved_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Enums
|
||||||
|
CREATE TYPE mlm.structure_type AS ENUM (
|
||||||
|
'unilevel', 'binary', 'matrix', 'hybrid'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE mlm.node_status AS ENUM (
|
||||||
|
'pending', 'active', 'inactive', 'suspended'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE mlm.commission_type AS ENUM (
|
||||||
|
'level', 'matching', 'infinity', 'leadership', 'pool'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE mlm.commission_status AS ENUM (
|
||||||
|
'pending', 'approved', 'paid', 'cancelled'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE mlm.bonus_type AS ENUM (
|
||||||
|
'rank_achievement', 'rank_maintenance', 'fast_start', 'pool_share'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Indices especiales
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Indice para LTREE (path materializado)
|
||||||
|
CREATE INDEX idx_nodes_path ON mlm.nodes USING GIST (path);
|
||||||
|
|
||||||
|
-- Para buscar downline
|
||||||
|
CREATE INDEX idx_nodes_parent ON mlm.nodes (parent_id);
|
||||||
|
CREATE INDEX idx_nodes_sponsor ON mlm.nodes (sponsor_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints API
|
||||||
|
|
||||||
|
### Structures
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /mlm/structures | Listar estructuras |
|
||||||
|
| POST | /mlm/structures | Crear estructura |
|
||||||
|
| GET | /mlm/structures/:id | Obtener estructura |
|
||||||
|
| PATCH | /mlm/structures/:id | Actualizar estructura |
|
||||||
|
|
||||||
|
### Nodes
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /mlm/nodes | Listar nodos |
|
||||||
|
| POST | /mlm/nodes | Crear nodo (registrar) |
|
||||||
|
| GET | /mlm/nodes/:id | Obtener nodo |
|
||||||
|
| GET | /mlm/nodes/:id/downline | Obtener downline |
|
||||||
|
| GET | /mlm/nodes/:id/upline | Obtener upline |
|
||||||
|
| GET | /mlm/nodes/:id/tree | Arbol visual |
|
||||||
|
| PATCH | /mlm/nodes/:id/status | Cambiar estado |
|
||||||
|
|
||||||
|
### Ranks
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /mlm/ranks | Listar rangos |
|
||||||
|
| POST | /mlm/ranks | Crear rango |
|
||||||
|
| GET | /mlm/ranks/:id | Obtener rango |
|
||||||
|
| PATCH | /mlm/ranks/:id | Actualizar rango |
|
||||||
|
| POST | /mlm/ranks/evaluate | Evaluar calificaciones |
|
||||||
|
|
||||||
|
### Commissions
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /mlm/commissions | Listar comisiones MLM |
|
||||||
|
| POST | /mlm/commissions/calculate | Calcular comisiones |
|
||||||
|
| GET | /mlm/commissions/by-level | Por nivel |
|
||||||
|
|
||||||
|
### My Network (Distribuidor)
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /mlm/my/dashboard | Dashboard personal |
|
||||||
|
| GET | /mlm/my/network | Mi red |
|
||||||
|
| GET | /mlm/my/earnings | Mis ganancias |
|
||||||
|
| GET | /mlm/my/rank | Mi rango y progreso |
|
||||||
|
| POST | /mlm/my/invite | Generar link de invitacion |
|
||||||
|
|
||||||
|
## Frontend
|
||||||
|
|
||||||
|
### Paginas
|
||||||
|
- `/mlm` - Dashboard MLM
|
||||||
|
- `/mlm/network` - Visualizacion de red
|
||||||
|
- `/mlm/structures` - Configuracion estructuras
|
||||||
|
- `/mlm/ranks` - Gestion de rangos
|
||||||
|
- `/mlm/commissions` - Comisiones MLM
|
||||||
|
- `/mlm/my` - Portal distribuidor
|
||||||
|
|
||||||
|
### Componentes
|
||||||
|
- `NetworkTree` - Arbol de red interactivo
|
||||||
|
- `BinaryTree` - Visualizacion binaria
|
||||||
|
- `UnivelTree` - Visualizacion unilevel
|
||||||
|
- `NodeCard` - Tarjeta de nodo
|
||||||
|
- `RankBadge` - Badge de rango
|
||||||
|
- `RankProgress` - Progreso hacia siguiente rango
|
||||||
|
- `DownlineList` - Lista de downline
|
||||||
|
- `EarningsBreakdown` - Desglose de ganancias
|
||||||
|
- `InviteLink` - Generador de link
|
||||||
|
- `StructureConfig` - Configuracion de estructura
|
||||||
|
- `LevelRatesEditor` - Editor de comisiones por nivel
|
||||||
|
|
||||||
|
### Hooks
|
||||||
|
- `useStructures` - CRUD estructuras
|
||||||
|
- `useNodes` - CRUD nodos
|
||||||
|
- `useRanks` - CRUD rangos
|
||||||
|
- `useMyNetwork` - Red del usuario actual
|
||||||
|
- `useNetworkTree` - Datos del arbol
|
||||||
|
- `useMLMCommissions` - Comisiones MLM
|
||||||
|
|
||||||
|
## Dependencias
|
||||||
|
|
||||||
|
### Modulos Requeridos
|
||||||
|
- SAAS-001 Auth
|
||||||
|
- SAAS-002 Tenants
|
||||||
|
- SAAS-003 Users
|
||||||
|
- SAAS-020 Commissions (base)
|
||||||
|
|
||||||
|
### Modulos Opcionales
|
||||||
|
- SAAS-018 Sales (ventas como fuente)
|
||||||
|
- SAAS-019 Portfolio (productos)
|
||||||
|
- SAAS-022 Goals (objetivos por rango)
|
||||||
|
|
||||||
|
## Criterios de Aceptacion
|
||||||
|
|
||||||
|
1. [ ] Estructuras unilevel y binario funcionales
|
||||||
|
2. [ ] Registro de nodos con sponsor
|
||||||
|
3. [ ] Calculo de comisiones por niveles
|
||||||
|
4. [ ] Sistema de rangos con requisitos
|
||||||
|
5. [ ] Visualizacion de arbol interactivo
|
||||||
|
6. [ ] Dashboard de distribuidor completo
|
||||||
|
7. [ ] Reportes de red y earnings
|
||||||
|
8. [ ] Tests unitarios (>70% coverage)
|
||||||
|
|
||||||
|
## Estimacion
|
||||||
|
|
||||||
|
| Componente | SP |
|
||||||
|
|------------|-----|
|
||||||
|
| DDL + Entities | 4 |
|
||||||
|
| Backend Services | 6 |
|
||||||
|
| Controllers + DTOs | 3 |
|
||||||
|
| Frontend Pages | 4 |
|
||||||
|
| Frontend Components (Tree) | 3 |
|
||||||
|
| Tests | 1 |
|
||||||
|
| **Total** | **21** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ultima actualizacion:** 2026-01-24
|
||||||
|
**Autor:** Claude Opus 4.5
|
||||||
356
docs/01-modulos/SAAS-022-goals.md
Normal file
356
docs/01-modulos/SAAS-022-goals.md
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
---
|
||||||
|
id: "SAAS-022"
|
||||||
|
title: "Goals"
|
||||||
|
type: "Module"
|
||||||
|
status: "Specified"
|
||||||
|
priority: "P2"
|
||||||
|
module: "goals"
|
||||||
|
version: "1.0.0"
|
||||||
|
created_date: "2026-01-24"
|
||||||
|
updated_date: "2026-01-24"
|
||||||
|
estimated_sp: 13
|
||||||
|
---
|
||||||
|
|
||||||
|
# SAAS-022: Goals
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
- **Codigo:** SAAS-022
|
||||||
|
- **Modulo:** Goals
|
||||||
|
- **Prioridad:** P2
|
||||||
|
- **Estado:** Especificado
|
||||||
|
- **Fase:** 6 - Advanced Features
|
||||||
|
- **Story Points:** 13
|
||||||
|
|
||||||
|
## Descripcion
|
||||||
|
|
||||||
|
Sistema de metas y objetivos para equipos y usuarios individuales. Permite definir OKRs, KPIs, metas de ventas, y trackear progreso en tiempo real. Se integra con Sales para metas comerciales y con Commissions para bonos por cumplimiento.
|
||||||
|
|
||||||
|
## Objetivos
|
||||||
|
|
||||||
|
1. Definir metas con periodos y metricas
|
||||||
|
2. Asignar metas a usuarios/equipos
|
||||||
|
3. Tracking de progreso automatico
|
||||||
|
4. Notificaciones de hitos
|
||||||
|
5. Reportes de cumplimiento
|
||||||
|
|
||||||
|
## Alcance
|
||||||
|
|
||||||
|
### Incluido
|
||||||
|
- Tipos de metas: numerica, porcentual, booleana
|
||||||
|
- Periodos: diario, semanal, mensual, trimestral, anual
|
||||||
|
- Metas individuales y de equipo
|
||||||
|
- Tracking automatico (integracion con fuentes)
|
||||||
|
- Actualizacion manual de progreso
|
||||||
|
- Dashboard de metas
|
||||||
|
- Notificaciones de progreso
|
||||||
|
- Reportes de cumplimiento
|
||||||
|
|
||||||
|
### Excluido
|
||||||
|
- OKRs jerarquicos complejos
|
||||||
|
- Metas en cascada automaticas
|
||||||
|
- Gamificacion avanzada (puntos, badges)
|
||||||
|
|
||||||
|
## Modelo de Datos
|
||||||
|
|
||||||
|
### Schema: goals
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Definiciones de metas
|
||||||
|
CREATE TABLE goals.definitions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
|
||||||
|
-- Info basica
|
||||||
|
name VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
category VARCHAR(100),
|
||||||
|
|
||||||
|
-- Tipo de meta
|
||||||
|
type goals.goal_type NOT NULL,
|
||||||
|
metric goals.metric_type NOT NULL,
|
||||||
|
|
||||||
|
-- Objetivo
|
||||||
|
target_value DECIMAL(15,2) NOT NULL,
|
||||||
|
unit VARCHAR(50), -- 'USD', 'units', '%', etc.
|
||||||
|
|
||||||
|
-- Periodo
|
||||||
|
period goals.period_type NOT NULL,
|
||||||
|
starts_at DATE NOT NULL,
|
||||||
|
ends_at DATE NOT NULL,
|
||||||
|
|
||||||
|
-- Fuente de datos (para tracking automatico)
|
||||||
|
source goals.data_source,
|
||||||
|
source_config JSONB DEFAULT '{}',
|
||||||
|
-- {
|
||||||
|
-- module: 'sales',
|
||||||
|
-- entity: 'opportunities',
|
||||||
|
-- filter: { status: 'won' },
|
||||||
|
-- aggregation: 'sum',
|
||||||
|
-- field: 'amount'
|
||||||
|
-- }
|
||||||
|
|
||||||
|
-- Hitos
|
||||||
|
milestones JSONB DEFAULT '[]',
|
||||||
|
-- [{ percentage: 25, notify: true }, { percentage: 50, notify: true }]
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status goals.goal_status NOT NULL DEFAULT 'draft',
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
tags JSONB DEFAULT '[]',
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
created_by UUID REFERENCES users.users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Asignaciones de metas
|
||||||
|
CREATE TABLE goals.assignments (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
|
||||||
|
definition_id UUID NOT NULL REFERENCES goals.definitions(id),
|
||||||
|
|
||||||
|
-- Asignado a
|
||||||
|
assignee_type goals.assignee_type NOT NULL,
|
||||||
|
user_id UUID REFERENCES users.users(id),
|
||||||
|
team_id UUID, -- Si hay modulo de teams
|
||||||
|
|
||||||
|
-- Objetivo personalizado (override)
|
||||||
|
custom_target DECIMAL(15,2),
|
||||||
|
|
||||||
|
-- Progreso
|
||||||
|
current_value DECIMAL(15,2) DEFAULT 0,
|
||||||
|
progress_percentage DECIMAL(5,2) DEFAULT 0,
|
||||||
|
last_updated_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Estado
|
||||||
|
status goals.assignment_status NOT NULL DEFAULT 'active',
|
||||||
|
achieved_at TIMESTAMPTZ,
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
notes TEXT,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Historial de progreso
|
||||||
|
CREATE TABLE goals.progress_log (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
assignment_id UUID NOT NULL REFERENCES goals.assignments(id),
|
||||||
|
|
||||||
|
-- Valores
|
||||||
|
previous_value DECIMAL(15,2),
|
||||||
|
new_value DECIMAL(15,2) NOT NULL,
|
||||||
|
change_amount DECIMAL(15,2),
|
||||||
|
|
||||||
|
-- Fuente del cambio
|
||||||
|
source goals.progress_source NOT NULL,
|
||||||
|
source_reference VARCHAR(200), -- ID de la transaccion origen
|
||||||
|
|
||||||
|
notes TEXT,
|
||||||
|
logged_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
logged_by UUID REFERENCES users.users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Notificaciones de hitos
|
||||||
|
CREATE TABLE goals.milestone_notifications (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
assignment_id UUID NOT NULL REFERENCES goals.assignments(id),
|
||||||
|
|
||||||
|
milestone_percentage INTEGER NOT NULL,
|
||||||
|
achieved_value DECIMAL(15,2) NOT NULL,
|
||||||
|
|
||||||
|
notified_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Enums
|
||||||
|
CREATE TYPE goals.goal_type AS ENUM (
|
||||||
|
'target', 'limit', 'maintain'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE goals.metric_type AS ENUM (
|
||||||
|
'number', 'currency', 'percentage', 'boolean', 'count'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE goals.period_type AS ENUM (
|
||||||
|
'daily', 'weekly', 'monthly', 'quarterly', 'yearly', 'custom'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE goals.data_source AS ENUM (
|
||||||
|
'manual', 'sales', 'billing', 'commissions', 'custom'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE goals.goal_status AS ENUM (
|
||||||
|
'draft', 'active', 'paused', 'completed', 'cancelled'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE goals.assignee_type AS ENUM (
|
||||||
|
'user', 'team', 'tenant'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE goals.assignment_status AS ENUM (
|
||||||
|
'active', 'achieved', 'failed', 'cancelled'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE goals.progress_source AS ENUM (
|
||||||
|
'manual', 'automatic', 'import', 'api'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### RLS Policies
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE goals.definitions ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE goals.assignments ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE goals.progress_log ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
CREATE POLICY tenant_isolation ON goals.definitions
|
||||||
|
USING (tenant_id = current_setting('app.current_tenant_id')::UUID);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints API
|
||||||
|
|
||||||
|
### Definitions
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /goals | Listar definiciones |
|
||||||
|
| POST | /goals | Crear meta |
|
||||||
|
| GET | /goals/:id | Obtener meta |
|
||||||
|
| PATCH | /goals/:id | Actualizar meta |
|
||||||
|
| DELETE | /goals/:id | Eliminar meta |
|
||||||
|
| POST | /goals/:id/activate | Activar meta |
|
||||||
|
| POST | /goals/:id/duplicate | Duplicar meta |
|
||||||
|
|
||||||
|
### Assignments
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /goals/:id/assignments | Listar asignaciones |
|
||||||
|
| POST | /goals/:id/assignments | Asignar meta |
|
||||||
|
| PATCH | /goals/assignments/:id | Actualizar asignacion |
|
||||||
|
| DELETE | /goals/assignments/:id | Eliminar asignacion |
|
||||||
|
| POST | /goals/assignments/:id/progress | Actualizar progreso |
|
||||||
|
|
||||||
|
### Progress
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /goals/assignments/:id/history | Historial progreso |
|
||||||
|
| POST | /goals/sync | Sincronizar con fuentes |
|
||||||
|
|
||||||
|
### My Goals
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /goals/my | Mis metas |
|
||||||
|
| GET | /goals/my/summary | Resumen de progreso |
|
||||||
|
| POST | /goals/my/:id/update | Actualizar mi progreso |
|
||||||
|
|
||||||
|
### Reports
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /goals/reports/completion | Tasa de cumplimiento |
|
||||||
|
| GET | /goals/reports/by-user | Por usuario |
|
||||||
|
| GET | /goals/reports/by-period | Por periodo |
|
||||||
|
|
||||||
|
## Frontend
|
||||||
|
|
||||||
|
### Paginas
|
||||||
|
- `/goals` - Dashboard de metas
|
||||||
|
- `/goals/new` - Crear meta
|
||||||
|
- `/goals/:id` - Detalle de meta
|
||||||
|
- `/goals/:id/assignments` - Asignaciones
|
||||||
|
- `/goals/my` - Mis metas
|
||||||
|
|
||||||
|
### Componentes
|
||||||
|
- `GoalsDashboard` - Overview con metricas
|
||||||
|
- `GoalsList` - Lista de metas
|
||||||
|
- `GoalForm` - Formulario de meta
|
||||||
|
- `GoalCard` - Tarjeta de meta con progreso
|
||||||
|
- `GoalProgress` - Barra/indicador de progreso
|
||||||
|
- `AssignmentsList` - Lista de asignados
|
||||||
|
- `AssignmentForm` - Formulario de asignacion
|
||||||
|
- `ProgressUpdater` - Actualizar progreso manual
|
||||||
|
- `ProgressChart` - Grafico de progreso temporal
|
||||||
|
- `MilestoneTimeline` - Timeline de hitos
|
||||||
|
- `GoalFilters` - Filtros por periodo/estado/categoria
|
||||||
|
|
||||||
|
### Hooks
|
||||||
|
- `useGoals` - CRUD metas
|
||||||
|
- `useAssignments` - CRUD asignaciones
|
||||||
|
- `useMyGoals` - Metas del usuario actual
|
||||||
|
- `useProgress` - Historial de progreso
|
||||||
|
- `useGoalReports` - Reportes
|
||||||
|
|
||||||
|
## Integraciones
|
||||||
|
|
||||||
|
### Tracking Automatico
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Configuracion de fuente de datos
|
||||||
|
interface SourceConfig {
|
||||||
|
module: 'sales' | 'billing' | 'commissions';
|
||||||
|
entity: string;
|
||||||
|
filter: Record<string, any>;
|
||||||
|
aggregation: 'sum' | 'count' | 'avg';
|
||||||
|
field: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ejemplo: Meta de ventas
|
||||||
|
{
|
||||||
|
module: 'sales',
|
||||||
|
entity: 'opportunities',
|
||||||
|
filter: { status: 'won' },
|
||||||
|
aggregation: 'sum',
|
||||||
|
field: 'amount'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notificaciones
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Eventos de notificacion
|
||||||
|
- goal.milestone_reached (25%, 50%, 75%, 100%)
|
||||||
|
- goal.achieved
|
||||||
|
- goal.at_risk (< 50% progreso en > 75% tiempo)
|
||||||
|
- goal.failed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependencias
|
||||||
|
|
||||||
|
### Modulos Requeridos
|
||||||
|
- SAAS-001 Auth
|
||||||
|
- SAAS-002 Tenants
|
||||||
|
- SAAS-003 Users
|
||||||
|
- SAAS-007 Notifications
|
||||||
|
|
||||||
|
### Modulos Opcionales
|
||||||
|
- SAAS-018 Sales (fuente de datos)
|
||||||
|
- SAAS-004 Billing (fuente de datos)
|
||||||
|
- SAAS-020 Commissions (bonos por cumplimiento)
|
||||||
|
|
||||||
|
## Criterios de Aceptacion
|
||||||
|
|
||||||
|
1. [ ] CRUD de metas con todos los tipos
|
||||||
|
2. [ ] Asignacion a usuarios y equipos
|
||||||
|
3. [ ] Tracking automatico funcional
|
||||||
|
4. [ ] Actualizacion manual de progreso
|
||||||
|
5. [ ] Notificaciones de hitos
|
||||||
|
6. [ ] Dashboard con progreso visual
|
||||||
|
7. [ ] Reportes de cumplimiento
|
||||||
|
8. [ ] Tests unitarios (>70% coverage)
|
||||||
|
|
||||||
|
## Estimacion
|
||||||
|
|
||||||
|
| Componente | SP |
|
||||||
|
|------------|-----|
|
||||||
|
| DDL + Entities | 2 |
|
||||||
|
| Backend Services | 4 |
|
||||||
|
| Controllers + DTOs | 2 |
|
||||||
|
| Frontend Pages | 3 |
|
||||||
|
| Frontend Components | 2 |
|
||||||
|
| Tests | 1 |
|
||||||
|
| **Total** | **13** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ultima actualizacion:** 2026-01-24
|
||||||
|
**Autor:** Claude Opus 4.5
|
||||||
@ -1,26 +1,30 @@
|
|||||||
---
|
---
|
||||||
# MASTER INVENTORY - Template SaaS
|
# MASTER INVENTORY - Template SaaS
|
||||||
# Version: 4.0.0
|
# Version: 5.0.0
|
||||||
# Ultima actualizacion: 2026-01-10
|
# Ultima actualizacion: 2026-01-24
|
||||||
# Nota: Reestructuracion SIMCO v3.7 aplicada
|
# Nota: Modulos avanzados SAAS-018 a SAAS-022 especificados
|
||||||
|
|
||||||
metadata:
|
metadata:
|
||||||
proyecto: "template-saas"
|
proyecto: "template-saas"
|
||||||
tipo: "MASTER"
|
tipo: "MASTER"
|
||||||
version: "4.0.0"
|
version: "5.0.0"
|
||||||
updated: "2026-01-10"
|
updated: "2026-01-24"
|
||||||
descripcion: "Template base para plataformas SaaS multi-tenant"
|
descripcion: "Template base para plataformas SaaS multi-tenant"
|
||||||
estado: "release-candidate"
|
estado: "release-candidate"
|
||||||
fecha_inicio: "2026-01-07"
|
fecha_inicio: "2026-01-07"
|
||||||
|
|
||||||
resumen:
|
resumen:
|
||||||
total_sp: 179
|
total_sp: 260
|
||||||
completados_sp: 179
|
completados_sp: 179
|
||||||
porcentaje: 100
|
especificados_sp: 81
|
||||||
fase_actual: "Release Candidate"
|
porcentaje_core: 100
|
||||||
|
porcentaje_total: 69
|
||||||
|
fase_actual: "Release Candidate + Advanced Modules Specified"
|
||||||
sprints_completados: 5
|
sprints_completados: 5
|
||||||
sprints_pendientes: 0
|
sprints_pendientes: 0
|
||||||
progreso_mvp: "100%"
|
progreso_mvp: "100%"
|
||||||
|
modulos_core: 14
|
||||||
|
modulos_avanzados: 5
|
||||||
|
|
||||||
metricas:
|
metricas:
|
||||||
backend_tests: 798
|
backend_tests: 798
|
||||||
@ -189,6 +193,46 @@ modulos:
|
|||||||
dependencias: ["SAAS-002", "SAAS-007"]
|
dependencias: ["SAAS-002", "SAAS-007"]
|
||||||
cobertura: 90
|
cobertura: 90
|
||||||
|
|
||||||
|
- id: "SAAS-018"
|
||||||
|
nombre: "sales"
|
||||||
|
descripcion: "Sales Foundation - Leads, Oportunidades, Pipeline"
|
||||||
|
estado: "especificado"
|
||||||
|
sp: 21
|
||||||
|
dependencias: ["SAAS-001", "SAAS-002", "SAAS-003", "SAAS-007"]
|
||||||
|
nota: "Modulo avanzado - especificacion completa disponible"
|
||||||
|
|
||||||
|
- id: "SAAS-019"
|
||||||
|
nombre: "portfolio"
|
||||||
|
descripcion: "Catalogo de productos y servicios"
|
||||||
|
estado: "especificado"
|
||||||
|
sp: 13
|
||||||
|
dependencias: ["SAAS-001", "SAAS-002", "SAAS-011"]
|
||||||
|
nota: "Modulo avanzado - especificacion completa disponible"
|
||||||
|
|
||||||
|
- id: "SAAS-020"
|
||||||
|
nombre: "commissions"
|
||||||
|
descripcion: "Sistema de comisiones para vendedores"
|
||||||
|
estado: "especificado"
|
||||||
|
sp: 13
|
||||||
|
dependencias: ["SAAS-001", "SAAS-002", "SAAS-003", "SAAS-018"]
|
||||||
|
nota: "Modulo avanzado - especificacion completa disponible"
|
||||||
|
|
||||||
|
- id: "SAAS-021"
|
||||||
|
nombre: "mlm"
|
||||||
|
descripcion: "Multi-Level Marketing - Redes de distribuidores"
|
||||||
|
estado: "especificado"
|
||||||
|
sp: 21
|
||||||
|
dependencias: ["SAAS-001", "SAAS-002", "SAAS-003", "SAAS-020"]
|
||||||
|
nota: "Modulo enterprise - requiere commissions"
|
||||||
|
|
||||||
|
- id: "SAAS-022"
|
||||||
|
nombre: "goals"
|
||||||
|
descripcion: "Sistema de metas y objetivos"
|
||||||
|
estado: "especificado"
|
||||||
|
sp: 13
|
||||||
|
dependencias: ["SAAS-001", "SAAS-002", "SAAS-003", "SAAS-007"]
|
||||||
|
nota: "Modulo avanzado - tracking automatico disponible"
|
||||||
|
|
||||||
portales:
|
portales:
|
||||||
- id: "portal-user"
|
- id: "portal-user"
|
||||||
nombre: "Portal Usuario"
|
nombre: "Portal Usuario"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user