docs: Add ET-SAAS-018 to ET-SAAS-022 technical specifications
Some checks are pending
CI / Backend CI (push) Waiting to run
CI / Frontend CI (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / CI Summary (push) Blocked by required conditions

- ET-SAAS-018-sales.md: Sales pipeline/CRM module
- ET-SAAS-019-portfolio.md: Product catalog module
- ET-SAAS-020-commissions.md: Commissions system
- ET-SAAS-021-mlm.md: Multi-Level Marketing module
- ET-SAAS-022-goals.md: Goals and objectives system
- Update _MAP.md with all 9 specifications

All specs document:
- Data model (DDL, enums, tables)
- Backend architecture (endpoints, services)
- Security (RLS, RBAC permissions)
- Frontend status and hooks
- Module integrations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Adrian Flores Cortes 2026-02-03 13:14:48 -06:00
parent ae092a9bb1
commit 2825b3d5fd
6 changed files with 1855 additions and 15 deletions

View File

@ -0,0 +1,289 @@
---
id: "ET-SAAS-018"
title: "Especificacion Tecnica Sales Pipeline"
type: "TechnicalSpec"
status: "Implemented"
priority: "P1"
module: "sales"
version: "1.0.0"
created_date: "2026-02-03"
updated_date: "2026-02-03"
story_points: 8
---
# ET-SAAS-018: Especificacion Tecnica - Sistema de Ventas (Sales Pipeline)
## Metadata
- **Codigo:** ET-SAAS-018
- **Modulo:** Sales
- **Version:** 1.0.0
- **Estado:** Implementado
- **Fecha:** 2026-02-03
- **Basado en:** SAAS-018
---
## 1. Resumen Ejecutivo
### 1.1 Estado Actual
Sistema de ventas completamente implementado con CRM basico.
| Capacidad | Estado | Notas |
|-----------|--------|-------|
| Pipeline Stages | SI | Etapas configurables por tenant |
| Leads Management | SI | Prospectos con scoring |
| Opportunities | SI | Oportunidades con probabilidad |
| Activities | SI | Llamadas, reuniones, tareas |
| RLS | SI | Row Level Security por tenant |
### 1.2 Funcionalidades v1.0
Sistema CRM con:
- **4 Entidades**: Pipeline Stages, Leads, Opportunities, Activities
- **Pipeline configurable**: Etapas personalizables por tenant
- **Lead Scoring**: Puntuacion 0-100 automatica
- **Activity Tracking**: Llamadas, reuniones, tareas, emails, notas
- **Conversion Flow**: Lead → Opportunity → Won/Lost
---
## 2. Modelo de Datos
### 2.1 Schema: sales
#### Tabla: pipeline_stages
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| name | VARCHAR(100) | Nombre de la etapa |
| position | INT | Orden en el pipeline |
| color | VARCHAR(7) | Color hex |
| is_won | BOOLEAN | Etapa de cierre ganado |
| is_lost | BOOLEAN | Etapa de cierre perdido |
| is_active | BOOLEAN | Estado activo |
#### Tabla: leads
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| first_name, last_name | VARCHAR(100) | Nombre completo |
| email, phone | VARCHAR | Contacto |
| company, job_title | VARCHAR | Empresa |
| source | ENUM | website, referral, cold_call, event, advertisement, social_media, other |
| status | ENUM | new, contacted, qualified, unqualified, converted |
| score | INT | 0-100 lead scoring |
| assigned_to | UUID | FK users |
| converted_at | TIMESTAMPTZ | Fecha conversion |
| custom_fields | JSONB | Campos personalizados |
#### Tabla: opportunities
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| name | VARCHAR(255) | Nombre de la oportunidad |
| lead_id | UUID | FK leads (opcional) |
| stage | ENUM | prospecting, qualification, proposal, negotiation, closed_won, closed_lost |
| stage_id | UUID | FK pipeline_stages |
| amount | DECIMAL(15,2) | Valor monetario |
| currency | VARCHAR(3) | Moneda (default USD) |
| probability | INT | 0-100 probabilidad de cierre |
| expected_close_date | DATE | Fecha esperada de cierre |
| assigned_to | UUID | FK users |
| won_at, lost_at | TIMESTAMPTZ | Fechas de cierre |
| lost_reason | VARCHAR(500) | Razon de perdida |
#### Tabla: activities
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| type | ENUM | call, meeting, task, email, note |
| status | ENUM | pending, completed, cancelled |
| subject | VARCHAR(255) | Titulo |
| lead_id / opportunity_id | UUID | Referencia |
| due_date | TIMESTAMPTZ | Fecha limite |
| completed_at | TIMESTAMPTZ | Fecha completado |
| assigned_to | UUID | FK users |
| reminder_at | TIMESTAMPTZ | Recordatorio |
### 2.2 Enums
```sql
sales.lead_status: new, contacted, qualified, unqualified, converted
sales.lead_source: website, referral, cold_call, event, advertisement, social_media, other
sales.opportunity_stage: prospecting, qualification, proposal, negotiation, closed_won, closed_lost
sales.activity_type: call, meeting, task, email, note
sales.activity_status: pending, completed, cancelled
```
---
## 3. Arquitectura Backend
### 3.1 Estructura de Archivos
```
backend/src/modules/sales/
├── sales.module.ts
├── controllers/
│ ├── leads.controller.ts
│ ├── opportunities.controller.ts
│ ├── activities.controller.ts
│ └── pipeline-stages.controller.ts
├── services/
│ ├── leads.service.ts
│ ├── opportunities.service.ts
│ ├── activities.service.ts
│ └── pipeline-stages.service.ts
├── entities/
│ ├── lead.entity.ts
│ ├── opportunity.entity.ts
│ ├── activity.entity.ts
│ └── pipeline-stage.entity.ts
├── dto/
│ ├── create-lead.dto.ts
│ ├── update-lead.dto.ts
│ ├── create-opportunity.dto.ts
│ └── ...
└── __tests__/
```
### 3.2 Endpoints API
#### Leads
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /sales/leads | Listar leads |
| GET | /sales/leads/:id | Obtener lead |
| POST | /sales/leads | Crear lead |
| PATCH | /sales/leads/:id | Actualizar lead |
| DELETE | /sales/leads/:id | Eliminar lead |
| POST | /sales/leads/:id/convert | Convertir a oportunidad |
#### Opportunities
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /sales/opportunities | Listar oportunidades |
| GET | /sales/opportunities/:id | Obtener oportunidad |
| POST | /sales/opportunities | Crear oportunidad |
| PATCH | /sales/opportunities/:id | Actualizar |
| PATCH | /sales/opportunities/:id/stage | Cambiar etapa |
| POST | /sales/opportunities/:id/won | Marcar como ganada |
| POST | /sales/opportunities/:id/lost | Marcar como perdida |
| DELETE | /sales/opportunities/:id | Eliminar |
#### Activities
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /sales/activities | Listar actividades |
| GET | /sales/activities/:id | Obtener actividad |
| POST | /sales/activities | Crear actividad |
| PATCH | /sales/activities/:id | Actualizar |
| POST | /sales/activities/:id/complete | Marcar completada |
| DELETE | /sales/activities/:id | Eliminar |
#### Pipeline Stages
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /sales/pipeline-stages | Listar etapas |
| POST | /sales/pipeline-stages | Crear etapa |
| PATCH | /sales/pipeline-stages/:id | Actualizar |
| PATCH | /sales/pipeline-stages/reorder | Reordenar |
| DELETE | /sales/pipeline-stages/:id | Eliminar |
---
## 4. Seguridad
### 4.1 Row Level Security (RLS)
Todas las tablas tienen RLS habilitado con politicas por tenant_id.
```sql
-- Ejemplo para leads
CREATE POLICY leads_tenant_isolation ON sales.leads
USING (tenant_id = current_setting('app.tenant_id')::uuid);
```
### 4.2 Permisos RBAC
| Permiso | Descripcion |
|---------|-------------|
| sales:read | Ver leads, oportunidades, actividades |
| sales:write | Crear/editar |
| sales:delete | Eliminar |
| sales:assign | Asignar a usuarios |
| sales:manage | Configurar pipeline |
---
## 5. Integraciones
### 5.1 Modulos Relacionados
| Modulo | Integracion |
|--------|-------------|
| users | Asignacion de leads/opportunities |
| notifications | Alertas de actividades |
| audit | Log de cambios |
| commissions | Calculo de comisiones en won |
| goals | Tracking de metas de ventas |
### 5.2 Eventos Emitidos
```typescript
// Eventos del modulo sales
LeadCreated, LeadUpdated, LeadConverted
OpportunityCreated, OpportunityStageChanged, OpportunityWon, OpportunityLost
ActivityCreated, ActivityCompleted
```
---
## 6. Frontend
### 6.1 Paginas
| Ruta | Componente | Estado |
|------|------------|--------|
| /dashboard/sales | SalesDashboard | Pendiente |
| /dashboard/sales/leads | LeadsPage | Pendiente |
| /dashboard/sales/opportunities | OpportunitiesPage | Pendiente |
| /dashboard/sales/pipeline | PipelinePage | Pendiente |
| /dashboard/sales/activities | ActivitiesPage | Pendiente |
### 6.2 Hooks
```typescript
// frontend/src/hooks/useSales.ts
useLeads, useLead, useCreateLead, useUpdateLead, useDeleteLead, useConvertLead
useOpportunities, useOpportunity, useCreateOpportunity, useUpdateOpportunityStage
useActivities, useCreateActivity, useCompleteActivity
usePipelineStages
```
---
## 7. Metricas y Dashboard
### 7.1 KPIs Propuestos
- Total Leads por periodo
- Conversion Rate (Lead → Opportunity)
- Win Rate (Opportunity → Won)
- Pipeline Value (suma de amounts)
- Average Deal Size
- Sales Velocity (tiempo promedio de cierre)
---
## 8. Referencias
- DDL: `database/ddl/schemas/sales/`
- Backend: `backend/src/modules/sales/`
- Frontend: `frontend/src/services/sales/`

View File

@ -0,0 +1,318 @@
---
id: "ET-SAAS-019"
title: "Especificacion Tecnica Portfolio (Product Catalog)"
type: "TechnicalSpec"
status: "Implemented"
priority: "P1"
module: "portfolio"
version: "1.0.0"
created_date: "2026-02-03"
updated_date: "2026-02-03"
story_points: 8
---
# ET-SAAS-019: Especificacion Tecnica - Portfolio (Catalogo de Productos)
## Metadata
- **Codigo:** ET-SAAS-019
- **Modulo:** Portfolio
- **Version:** 1.0.0
- **Estado:** Implementado
- **Fecha:** 2026-02-03
- **Basado en:** SAAS-019
---
## 1. Resumen Ejecutivo
### 1.1 Estado Actual
Sistema de catalogo de productos completamente implementado.
| Capacidad | Estado | Notas |
|-----------|--------|-------|
| Categories | SI | Jerarquicas con arbol |
| Products | SI | Multi-tipo, inventario |
| Variants | SI | Atributos configurables |
| Prices | SI | Multi-moneda, tiered |
| RLS | SI | Row Level Security |
### 1.2 Funcionalidades v1.0
Catalogo completo con:
- **4 Entidades**: Categories, Products, Variants, Prices
- **Categorias jerarquicas**: Arbol ilimitado con parent_id
- **5 Tipos de producto**: physical, digital, service, subscription, bundle
- **Variantes**: Atributos dinamicos (color, size, etc.)
- **Precios flexibles**: one_time, recurring, usage_based, tiered
---
## 2. Modelo de Datos
### 2.1 Schema: portfolio
#### Tabla: categories
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| parent_id | UUID | FK categories (jerarquia) |
| name | VARCHAR(100) | Nombre categoria |
| slug | VARCHAR(120) | URL-friendly (unique per tenant) |
| description | TEXT | Descripcion |
| position | INT | Orden dentro del padre |
| image_url | VARCHAR(500) | Imagen |
| color | VARCHAR(7) | Color hex |
| icon | VARCHAR(50) | Icono |
| is_active | BOOLEAN | Estado |
| meta_title, meta_description | VARCHAR/TEXT | SEO |
| custom_fields | JSONB | Campos personalizados |
#### Tabla: products
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| category_id | UUID | FK categories |
| name | VARCHAR(255) | Nombre producto |
| slug | VARCHAR(280) | URL-friendly |
| sku | VARCHAR(100) | Stock Keeping Unit |
| barcode | VARCHAR(100) | Codigo de barras |
| description | TEXT | Descripcion larga |
| short_description | VARCHAR(500) | Descripcion corta |
| product_type | ENUM | physical, digital, service, subscription, bundle |
| status | ENUM | draft, active, inactive, discontinued, out_of_stock |
| base_price | DECIMAL(15,2) | Precio base |
| cost_price | DECIMAL(15,2) | Costo |
| compare_at_price | DECIMAL(15,2) | Precio tachado |
| currency | VARCHAR(3) | Moneda (default USD) |
| track_inventory | BOOLEAN | Trackear inventario |
| stock_quantity | INT | Cantidad en stock |
| low_stock_threshold | INT | Umbral de stock bajo |
| allow_backorder | BOOLEAN | Permitir backorder |
| weight, length, width, height | DECIMAL | Dimensiones |
| images | JSONB | Array de URLs |
| featured_image_url | VARCHAR(500) | Imagen principal |
| tags | JSONB | Array de tags |
| is_visible | BOOLEAN | Visible en frontend |
| is_featured | BOOLEAN | Producto destacado |
| has_variants | BOOLEAN | Tiene variantes |
| variant_attributes | JSONB | Atributos para variantes |
#### Tabla: variants
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| product_id | UUID | FK products |
| sku | VARCHAR(100) | SKU de variante |
| barcode | VARCHAR(100) | Codigo de barras |
| name | VARCHAR(255) | Nombre (e.g., "Rojo - XL") |
| attributes | JSONB | {"color": "red", "size": "XL"} |
| price | DECIMAL(15,2) | Override de precio |
| cost_price | DECIMAL(15,2) | Costo variante |
| stock_quantity | INT | Stock de variante |
| weight | DECIMAL(10,3) | Peso (override) |
| image_url | VARCHAR(500) | Imagen de variante |
| is_active | BOOLEAN | Estado |
| position | INT | Orden |
#### Tabla: prices
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| product_id | UUID | FK products (o variant_id) |
| variant_id | UUID | FK variants (o product_id) |
| price_type | ENUM | one_time, recurring, usage_based, tiered |
| currency | VARCHAR(3) | Moneda |
| amount | DECIMAL(15,2) | Precio |
| compare_at_amount | DECIMAL(15,2) | Precio comparativo |
| billing_period | VARCHAR(20) | day, week, month, year |
| billing_interval | INT | Intervalo (e.g., 1 = mensual) |
| min_quantity, max_quantity | INT | Rango para tiered |
| valid_from, valid_until | TIMESTAMPTZ | Validez |
| priority | INT | Prioridad (0 = default) |
| is_active | BOOLEAN | Estado |
### 2.2 Enums
```sql
portfolio.product_type: physical, digital, service, subscription, bundle
portfolio.product_status: draft, active, inactive, discontinued, out_of_stock
portfolio.price_type: one_time, recurring, usage_based, tiered
portfolio.attribute_type: color, size, material, style, capacity, custom
```
---
## 3. Arquitectura Backend
### 3.1 Estructura de Archivos
```
backend/src/modules/portfolio/
├── portfolio.module.ts
├── controllers/
│ ├── categories.controller.ts
│ └── products.controller.ts
├── services/
│ ├── categories.service.ts
│ └── products.service.ts
├── entities/
│ ├── category.entity.ts
│ ├── product.entity.ts
│ ├── variant.entity.ts
│ └── price.entity.ts
├── dto/
│ ├── create-category.dto.ts
│ ├── create-product.dto.ts
│ └── ...
└── __tests__/
```
### 3.2 Endpoints API
#### Categories
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/categories | Listar (paginado) |
| GET | /portfolio/categories/tree | Arbol jerarquico |
| GET | /portfolio/categories/:id | Obtener |
| POST | /portfolio/categories | Crear |
| PUT | /portfolio/categories/:id | Actualizar |
| DELETE | /portfolio/categories/:id | Eliminar |
#### Products
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products | Listar (paginado, filtros) |
| GET | /portfolio/products/:id | Obtener con variantes |
| POST | /portfolio/products | Crear |
| PUT | /portfolio/products/:id | Actualizar |
| PATCH | /portfolio/products/:id/status | Cambiar status |
| POST | /portfolio/products/:id/duplicate | Duplicar |
| DELETE | /portfolio/products/:id | Eliminar |
#### Variants
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products/:id/variants | Listar variantes |
| POST | /portfolio/products/:id/variants | Crear variante |
| PATCH | /portfolio/products/:id/variants/:vid | Actualizar |
| DELETE | /portfolio/products/:id/variants/:vid | Eliminar |
#### Prices
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products/:id/prices | Listar precios |
| POST | /portfolio/products/:id/prices | Crear precio |
| PATCH | /portfolio/products/:id/prices/:pid | Actualizar |
| DELETE | /portfolio/products/:id/prices/:pid | Eliminar |
---
## 4. Seguridad
### 4.1 Row Level Security (RLS)
```sql
-- Aislamiento por tenant
CREATE POLICY categories_tenant_isolation ON portfolio.categories
USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY products_tenant_isolation ON portfolio.products
USING (tenant_id = current_setting('app.tenant_id')::uuid);
```
### 4.2 Permisos RBAC
| Permiso | Descripcion |
|---------|-------------|
| portfolio:read | Ver catalogo |
| portfolio:write | Crear/editar productos |
| portfolio:delete | Eliminar productos |
| portfolio:publish | Publicar/despublicar |
| portfolio:manage | Configuracion avanzada |
---
## 5. Frontend
### 5.1 Paginas Implementadas
| Ruta | Componente | Estado |
|------|------------|--------|
| /dashboard/portfolio | PortfolioPage | Implementado |
| /dashboard/portfolio/products | ProductsPage | Implementado |
| /dashboard/portfolio/categories | CategoriesPage | Implementado |
| /dashboard/portfolio/products/:id | ProductDetailPage | Pendiente |
| /dashboard/portfolio/products/new | ProductFormPage | Pendiente |
### 5.2 Hooks
```typescript
// frontend/src/hooks/usePortfolio.ts
useCategories, useCategory, useCategoryTree
useCreateCategory, useUpdateCategory, useDeleteCategory
useProducts, useProduct
useCreateProduct, useUpdateProduct, useDeleteProduct, useDuplicateProduct
useProductVariants, useCreateVariant, useUpdateVariant, useDeleteVariant
useProductPrices, useCreatePrice, useUpdatePrice, useDeletePrice
```
---
## 6. Integraciones
### 6.1 Modulos Relacionados
| Modulo | Integracion |
|--------|-------------|
| sales | Productos en oportunidades |
| commissions | Comisiones por producto/categoria |
| storage | Imagenes de productos |
| audit | Log de cambios |
### 6.2 Eventos Emitidos
```typescript
ProductCreated, ProductUpdated, ProductStatusChanged
CategoryCreated, CategoryUpdated
VariantCreated, PriceUpdated
LowStockAlert // Cuando stock < threshold
```
---
## 7. Filtros y Busqueda
### 7.1 Filtros Disponibles
```typescript
interface ProductFilters {
category_id?: string;
product_type?: ProductType;
status?: ProductStatus;
is_visible?: boolean;
is_featured?: boolean;
min_price?: number;
max_price?: number;
search?: string; // Busca en name, sku, description
tags?: string[];
sort_by?: 'name' | 'price' | 'created_at' | 'stock';
sort_order?: 'ASC' | 'DESC';
}
```
---
## 8. Referencias
- DDL: `database/ddl/schemas/portfolio/`
- Backend: `backend/src/modules/portfolio/`
- Frontend Services: `frontend/src/services/portfolio/`
- Frontend Hooks: `frontend/src/hooks/usePortfolio.ts`
- Frontend Pages: `frontend/src/pages/dashboard/portfolio/`

View File

@ -0,0 +1,375 @@
---
id: "ET-SAAS-020"
title: "Especificacion Tecnica Commissions"
type: "TechnicalSpec"
status: "Implemented"
priority: "P1"
module: "commissions"
version: "1.0.0"
created_date: "2026-02-03"
updated_date: "2026-02-03"
story_points: 8
---
# ET-SAAS-020: Especificacion Tecnica - Sistema de Comisiones
## Metadata
- **Codigo:** ET-SAAS-020
- **Modulo:** Commissions
- **Version:** 1.0.0
- **Estado:** Implementado
- **Fecha:** 2026-02-03
- **Basado en:** SAAS-020
---
## 1. Resumen Ejecutivo
### 1.1 Estado Actual
Sistema de comisiones completamente implementado.
| Capacidad | Estado | Notas |
|-----------|--------|-------|
| Schemes | SI | Esquemas configurables |
| Assignments | SI | Asignacion usuario-esquema |
| Entries | SI | Entradas de comision |
| Periods | SI | Periodos de pago |
| Dashboard | SI | Metricas y reportes |
| RLS | SI | Row Level Security |
### 1.2 Funcionalidades v1.0
Sistema completo con:
- **4 Entidades**: Schemes, Assignments, Entries, Periods
- **3 Tipos de esquema**: percentage, fixed, tiered
- **Workflow completo**: pending → approved → paid
- **Periodos de pago**: Ciclos configurables
- **Dashboard**: Metricas por usuario, periodo, esquema
---
## 2. Modelo de Datos
### 2.1 Schema: commissions
#### Tabla: schemes
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| name | VARCHAR(100) | Nombre del esquema |
| description | TEXT | Descripcion |
| type | ENUM | percentage, fixed, tiered |
| rate | DECIMAL(5,2) | Tasa porcentual (0-100) |
| fixed_amount | DECIMAL(15,2) | Monto fijo |
| tiers | JSONB | [{from, to, rate}] |
| applies_to | ENUM | all, products, categories |
| product_ids | UUID[] | IDs de productos |
| category_ids | UUID[] | IDs de categorias |
| min_amount | DECIMAL(15,2) | Monto minimo para calificar |
| max_amount | DECIMAL(15,2) | Cap maximo por comision |
| is_active | BOOLEAN | Estado |
**Ejemplo tiers:**
```json
[
{"from": 0, "to": 1000, "rate": 5},
{"from": 1001, "to": 5000, "rate": 7},
{"from": 5001, "to": null, "rate": 10}
]
```
#### Tabla: assignments
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| user_id | UUID | FK users |
| scheme_id | UUID | FK schemes |
| starts_at | TIMESTAMPTZ | Inicio de vigencia |
| ends_at | TIMESTAMPTZ | Fin de vigencia (null = sin fin) |
| custom_rate | DECIMAL(5,2) | Override de tasa para este usuario |
| is_active | BOOLEAN | Estado |
#### Tabla: entries
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| user_id | UUID | FK users (quien gana) |
| scheme_id | UUID | FK schemes |
| assignment_id | UUID | FK assignments |
| reference_type | VARCHAR(50) | sale, opportunity, order |
| reference_id | UUID | ID del registro origen |
| base_amount | DECIMAL(15,2) | Monto base de la venta |
| rate_applied | DECIMAL(5,2) | Tasa aplicada |
| commission_amount | DECIMAL(15,2) | Comision calculada |
| currency | VARCHAR(3) | Moneda |
| status | ENUM | pending, approved, rejected, paid, cancelled |
| period_id | UUID | FK periods |
| paid_at | TIMESTAMPTZ | Fecha de pago |
| payment_reference | VARCHAR(255) | Referencia externa |
| notes | TEXT | Notas |
| metadata | JSONB | Datos adicionales |
| approved_by | UUID | FK users |
| approved_at | TIMESTAMPTZ | Fecha aprobacion |
#### Tabla: periods
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| name | VARCHAR(100) | "January 2026" |
| starts_at | TIMESTAMPTZ | Inicio del periodo |
| ends_at | TIMESTAMPTZ | Fin del periodo |
| total_entries | INT | Total de entradas |
| total_amount | DECIMAL(15,2) | Monto total |
| currency | VARCHAR(3) | Moneda |
| status | ENUM | open, closed, processing, paid |
| closed_at | TIMESTAMPTZ | Fecha cierre |
| closed_by | UUID | FK users |
| paid_at | TIMESTAMPTZ | Fecha pago |
| paid_by | UUID | FK users |
| payment_reference | VARCHAR(255) | Referencia |
| payment_notes | TEXT | Notas de pago |
### 2.2 Enums
```sql
commissions.scheme_type: percentage, fixed, tiered
commissions.applies_to: all, products, categories
commissions.entry_status: pending, approved, rejected, paid, cancelled
commissions.period_status: open, closed, processing, paid
```
---
## 3. Arquitectura Backend
### 3.1 Estructura de Archivos
```
backend/src/modules/commissions/
├── commissions.module.ts
├── controllers/
│ ├── schemes.controller.ts
│ ├── assignments.controller.ts
│ ├── entries.controller.ts
│ ├── periods.controller.ts
│ └── dashboard.controller.ts
├── services/
│ ├── schemes.service.ts
│ ├── assignments.service.ts
│ ├── entries.service.ts
│ ├── periods.service.ts
│ ├── calculation.service.ts
│ └── dashboard.service.ts
├── entities/
│ ├── scheme.entity.ts
│ ├── assignment.entity.ts
│ ├── entry.entity.ts
│ └── period.entity.ts
└── dto/
```
### 3.2 Endpoints API
#### Schemes
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /commissions/schemes | Listar esquemas |
| GET | /commissions/schemes/active | Solo activos |
| GET | /commissions/schemes/:id | Obtener |
| POST | /commissions/schemes | Crear |
| PUT | /commissions/schemes/:id | Actualizar |
| DELETE | /commissions/schemes/:id | Eliminar |
| POST | /commissions/schemes/:id/duplicate | Duplicar |
| POST | /commissions/schemes/:id/toggle | Activar/desactivar |
#### Assignments
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /commissions/assignments | Listar |
| GET | /commissions/assignments/user/:userId | Por usuario |
| GET | /commissions/assignments/user/:userId/active | Esquema activo |
| GET | /commissions/assignments/scheme/:schemeId | Por esquema |
| POST | /commissions/assignments | Asignar |
| PUT | /commissions/assignments/:id | Actualizar |
| DELETE | /commissions/assignments/:id | Remover |
| POST | /commissions/assignments/:id/deactivate | Desactivar |
#### Entries
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /commissions/entries | Listar |
| GET | /commissions/entries/pending | Pendientes |
| GET | /commissions/entries/:id | Obtener |
| GET | /commissions/entries/user/:userId | Por usuario |
| GET | /commissions/entries/period/:periodId | Por periodo |
| POST | /commissions/entries/calculate | Calcular comision |
| POST | /commissions/entries/simulate | Simular (sin guardar) |
| PATCH | /commissions/entries/:id/status | Cambiar status |
| POST | /commissions/entries/bulk-approve | Aprobar multiples |
| POST | /commissions/entries/bulk-reject | Rechazar multiples |
#### Periods
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /commissions/periods | Listar |
| GET | /commissions/periods/open | Periodo abierto |
| GET | /commissions/periods/:id | Obtener |
| GET | /commissions/periods/:id/summary | Resumen |
| POST | /commissions/periods | Crear |
| POST | /commissions/periods/:id/close | Cerrar |
| POST | /commissions/periods/:id/reopen | Reabrir |
| POST | /commissions/periods/:id/mark-paid | Marcar pagado |
#### Dashboard
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /commissions/dashboard | Resumen general |
| GET | /commissions/dashboard/by-user | Por usuario |
| GET | /commissions/dashboard/by-period | Por periodo |
| GET | /commissions/dashboard/top-earners | Top ganadores |
| GET | /commissions/dashboard/me | Mis ganancias |
| GET | /commissions/dashboard/user/:userId | Ganancias de usuario |
| GET | /commissions/dashboard/scheme/:schemeId | Performance de esquema |
---
## 4. Logica de Calculo
### 4.1 Algoritmo de Calculo
```typescript
async calculateCommission(dto: CalculateCommissionDto): Promise<CommissionEntry> {
// 1. Obtener asignacion activa del usuario
const assignment = await this.getActiveAssignment(dto.userId);
// 2. Obtener esquema
const scheme = await this.getScheme(assignment.schemeId);
// 3. Verificar monto minimo
if (dto.amount < scheme.minAmount) {
throw new Error('Amount below minimum threshold');
}
// 4. Calcular tasa segun tipo
let rate: number;
switch (scheme.type) {
case 'percentage':
rate = assignment.customRate ?? scheme.rate;
break;
case 'fixed':
return this.createEntry({
...dto,
rateApplied: 0,
commissionAmount: scheme.fixedAmount
});
case 'tiered':
rate = this.getTieredRate(scheme.tiers, dto.amount);
break;
}
// 5. Calcular comision
let commissionAmount = dto.amount * (rate / 100);
// 6. Aplicar cap si existe
if (scheme.maxAmount && commissionAmount > scheme.maxAmount) {
commissionAmount = scheme.maxAmount;
}
// 7. Crear entrada
return this.createEntry({
...dto,
schemeId: scheme.id,
assignmentId: assignment.id,
rateApplied: rate,
commissionAmount
});
}
```
### 4.2 Ejemplo Tiered
```
Tiers: [{from:0, to:1000, rate:5}, {from:1001, to:5000, rate:7}, {from:5001, to:null, rate:10}]
Venta: $3,500
Calculo:
- Primeros $1,000: $1,000 × 5% = $50
- Siguientes $2,500: $2,500 × 7% = $175
- Total comision: $225
```
---
## 5. Frontend
### 5.1 Paginas
| Ruta | Componente | Estado |
|------|------------|--------|
| /dashboard/commissions | CommissionsDashboard | Pendiente |
| /dashboard/commissions/schemes | SchemesPage | Pendiente |
| /dashboard/commissions/entries | EntriesPage | Pendiente |
| /dashboard/commissions/periods | PeriodsPage | Pendiente |
| /dashboard/commissions/my-earnings | MyEarningsPage | Pendiente |
### 5.2 Hooks
```typescript
// frontend/src/hooks/useCommissions.ts
useSchemes, useScheme, useCreateScheme, useUpdateScheme, useDeleteScheme
useAssignments, useUserAssignments, useCreateAssignment
useEntries, usePendingEntries, useCalculateCommission, useUpdateEntryStatus
usePeriods, useOpenPeriod, useClosePeriod, useMarkPeriodPaid
useCommissionsDashboard, useMyEarnings, useTopEarners
```
---
## 6. Seguridad
### 6.1 RLS
```sql
CREATE POLICY schemes_tenant_isolation ON commissions.schemes
USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY entries_tenant_isolation ON commissions.entries
USING (tenant_id = current_setting('app.tenant_id')::uuid);
```
### 6.2 Permisos RBAC
| Permiso | Descripcion |
|---------|-------------|
| commissions:read | Ver comisiones |
| commissions:write | Crear/editar esquemas |
| commissions:approve | Aprobar comisiones |
| commissions:pay | Marcar como pagadas |
| commissions:manage | Administrar todo |
---
## 7. Integraciones
| Modulo | Integracion |
|--------|-------------|
| sales | Trigger en OpportunityWon |
| goals | Tracking de metas de comision |
| mlm | Comisiones MLM |
| notifications | Alertas de aprobacion/pago |
| audit | Log de cambios |
---
## 8. Referencias
- DDL: `database/ddl/schemas/commissions/`
- Backend: `backend/src/modules/commissions/`
- Frontend: `frontend/src/services/commissions/`
- Hooks: `frontend/src/hooks/useCommissions.ts`

View File

@ -0,0 +1,434 @@
---
id: "ET-SAAS-021"
title: "Especificacion Tecnica MLM (Multi-Level Marketing)"
type: "TechnicalSpec"
status: "Implemented"
priority: "P1"
module: "mlm"
version: "1.0.0"
created_date: "2026-02-03"
updated_date: "2026-02-03"
story_points: 13
---
# ET-SAAS-021: Especificacion Tecnica - MLM (Multi-Level Marketing)
## Metadata
- **Codigo:** ET-SAAS-021
- **Modulo:** MLM
- **Version:** 1.0.0
- **Estado:** Implementado (Backend)
- **Fecha:** 2026-02-03
- **Basado en:** SAAS-021
---
## 1. Resumen Ejecutivo
### 1.1 Estado Actual
Sistema MLM con backend implementado, UI pendiente.
| Capacidad | Estado | Notas |
|-----------|--------|-------|
| Structures | SI | Unilevel, Binary, Matrix |
| Ranks | SI | Rangos con requisitos |
| Nodes | SI | Arbol de distribuidores |
| Commissions | SI | Comisiones multinivel |
| Bonuses | SI | Bonos de rango |
| LTREE | SI | Consultas eficientes |
| RLS | SI | Row Level Security |
| UI | NO | Frontend pendiente |
### 1.2 Funcionalidades v1.0
Sistema completo con:
- **6 Entidades**: Structures, Ranks, Nodes, Commissions, Bonuses, RankHistory
- **4 Tipos de estructura**: unilevel, binary, matrix, hybrid
- **5 Tipos de comision**: level, matching, infinity, leadership, pool
- **4 Tipos de bono**: rank_achievement, rank_maintenance, fast_start, pool_share
- **LTREE**: Para consultas eficientes de upline/downline
---
## 2. Modelo de Datos
### 2.1 Schema: mlm
#### Tabla: structures
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| name | VARCHAR(100) | Nombre estructura |
| description | TEXT | Descripcion |
| type | ENUM | unilevel, binary, matrix, hybrid |
| config | JSONB | Configuracion especifica |
| level_rates | JSONB | Tasas por nivel |
| matching_rates | JSONB | Tasas de matching bonus |
| is_active | BOOLEAN | Estado |
**Configuracion por tipo:**
```json
// Unilevel
{"max_width": null, "max_depth": 10}
// Binary
{"spillover": "left_first" | "weak_leg" | "balanced"}
// Matrix
{"width": 3, "depth": 7}
```
**Level rates:**
```json
[
{"level": 1, "rate": 0.10},
{"level": 2, "rate": 0.05},
{"level": 3, "rate": 0.03}
]
```
#### Tabla: ranks
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| structure_id | UUID | FK structures |
| name | VARCHAR(100) | "Silver", "Gold", etc. |
| level | INT | 1, 2, 3... (orden) |
| badge_url | VARCHAR(500) | Imagen de badge |
| color | VARCHAR(7) | Color hex |
| requirements | JSONB | Requisitos |
| bonus_rate | DECIMAL(10,4) | Tasa de bono adicional |
| benefits | JSONB | Beneficios del rango |
| is_active | BOOLEAN | Estado |
**Requisitos ejemplo:**
```json
{
"personal_volume": 1000,
"group_volume": 10000,
"direct_referrals": 3,
"active_legs": 2,
"rank_in_legs": {"rank_level": 2, "count": 1}
}
```
#### Tabla: nodes
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| structure_id | UUID | FK structures |
| user_id | UUID | FK users |
| parent_id | UUID | FK nodes (padre directo) |
| sponsor_id | UUID | FK nodes (patrocinador) |
| position | INT | 1=left, 2=right (binary) |
| path | LTREE | Ruta materializada |
| depth | INT | Profundidad en el arbol |
| rank_id | UUID | FK ranks (rango actual) |
| highest_rank_id | UUID | FK ranks (maximo alcanzado) |
| personal_volume | DECIMAL(15,2) | Volumen personal |
| group_volume | DECIMAL(15,2) | Volumen de grupo |
| direct_referrals | INT | Referidos directos |
| total_downline | INT | Total de linea descendente |
| total_earnings | DECIMAL(15,2) | Ganancias totales |
| status | ENUM | pending, active, inactive, suspended |
| joined_at | TIMESTAMPTZ | Fecha de ingreso |
| invite_code | VARCHAR(20) | Codigo de invitacion |
#### Tabla: commissions
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| node_id | UUID | FK nodes (receptor) |
| source_node_id | UUID | FK nodes (origen) |
| type | ENUM | level, matching, infinity, leadership, pool |
| level | INT | Nivel de profundidad |
| source_amount | DECIMAL(15,2) | Monto origen |
| rate_applied | DECIMAL(10,4) | Tasa aplicada |
| commission_amount | DECIMAL(15,2) | Comision final |
| currency | VARCHAR(3) | Moneda |
| period_id | UUID | FK commissions.periods |
| source_reference | VARCHAR(200) | Referencia a transaccion |
| status | ENUM | pending, approved, paid, cancelled |
| paid_at | TIMESTAMPTZ | Fecha de pago |
#### Tabla: bonuses
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| node_id | UUID | FK nodes |
| rank_id | UUID | FK ranks |
| type | ENUM | rank_achievement, rank_maintenance, fast_start, pool_share |
| amount | DECIMAL(15,2) | Monto del bono |
| currency | VARCHAR(3) | Moneda |
| period_id | UUID | FK commissions.periods |
| status | ENUM | pending, approved, paid, cancelled |
| paid_at | TIMESTAMPTZ | Fecha de pago |
| achieved_at | TIMESTAMPTZ | Fecha de logro |
#### Tabla: rank_history
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| node_id | UUID | FK nodes |
| rank_id | UUID | FK ranks (nuevo rango) |
| previous_rank_id | UUID | FK ranks (rango anterior) |
| personal_volume_at | DECIMAL(15,2) | Snapshot |
| group_volume_at | DECIMAL(15,2) | Snapshot |
| direct_referrals_at | INT | Snapshot |
| achieved_at | TIMESTAMPTZ | Fecha de logro |
### 2.2 Enums
```sql
mlm.structure_type: unilevel, binary, matrix, hybrid
mlm.node_status: pending, active, inactive, suspended
mlm.commission_type: level, matching, infinity, leadership, pool
mlm.commission_status: pending, approved, paid, cancelled
mlm.bonus_type: rank_achievement, rank_maintenance, fast_start, pool_share
```
---
## 3. LTREE para Consultas Eficientes
### 3.1 Estructura del Path
```
Ejemplo: root.node1.node2.node3
└── Ruta desde la raiz hasta el nodo
```
### 3.2 Consultas Comunes
```sql
-- Obtener todos los ancestros (upline)
SELECT * FROM mlm.nodes WHERE path @> 'root.a.b.c';
-- Obtener todos los descendientes (downline)
SELECT * FROM mlm.nodes WHERE path <@ 'root.a.b.c';
-- Obtener descendientes hasta N niveles
SELECT * FROM mlm.nodes
WHERE path <@ 'root.a.b.c'
AND nlevel(path) - nlevel('root.a.b.c') <= 3;
-- Obtener hermanos
SELECT * FROM mlm.nodes WHERE subpath(path, 0, -1) = 'root.a.b';
```
---
## 4. Arquitectura Backend
### 4.1 Estructura de Archivos
```
backend/src/modules/mlm/
├── mlm.module.ts
├── controllers/
│ ├── structures.controller.ts
│ ├── ranks.controller.ts
│ ├── nodes.controller.ts
│ ├── commissions.controller.ts
│ └── my-network.controller.ts
├── services/
│ ├── structures.service.ts
│ ├── ranks.service.ts
│ ├── nodes.service.ts
│ ├── commissions.service.ts
│ ├── calculation.service.ts
│ └── genealogy.service.ts
├── entities/
│ ├── structure.entity.ts
│ ├── rank.entity.ts
│ ├── node.entity.ts
│ ├── commission.entity.ts
│ ├── bonus.entity.ts
│ └── rank-history.entity.ts
└── dto/
```
### 4.2 Endpoints API
#### Structures
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /mlm/structures | Listar |
| GET | /mlm/structures/:id | Obtener |
| POST | /mlm/structures | Crear |
| PUT | /mlm/structures/:id | Actualizar |
| DELETE | /mlm/structures/:id | Eliminar |
#### Ranks
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /mlm/ranks | Listar |
| GET | /mlm/ranks/:id | Obtener |
| POST | /mlm/ranks | Crear |
| PUT | /mlm/ranks/:id | Actualizar |
| DELETE | /mlm/ranks/:id | Eliminar |
| POST | /mlm/ranks/evaluate/:structureId | Evaluar todos |
#### Nodes
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /mlm/nodes | Listar |
| GET | /mlm/nodes/:id | Obtener |
| POST | /mlm/nodes | Crear (registrar en red) |
| PUT | /mlm/nodes/:id | Actualizar |
| PATCH | /mlm/nodes/:id/status | Cambiar status |
| GET | /mlm/nodes/:id/downline | Linea descendente |
| GET | /mlm/nodes/:id/upline | Linea ascendente |
| GET | /mlm/nodes/:id/tree | Arbol visual |
#### My Network (Usuario autenticado)
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /mlm/my/dashboard | Mi dashboard |
| GET | /mlm/my/network | Mi red |
| GET | /mlm/my/earnings | Mis ganancias |
| GET | /mlm/my/rank | Mi rango actual |
| POST | /mlm/my/invite | Generar link de invitacion |
#### Commissions
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /mlm/commissions | Listar |
| GET | /mlm/commissions/:id | Obtener |
| POST | /mlm/commissions/calculate | Calcular |
| PATCH | /mlm/commissions/:id/status | Cambiar status |
| GET | /mlm/commissions/by-level | Por nivel |
---
## 5. Logica de Comisiones
### 5.1 Algoritmo de Calculo por Nivel
```typescript
async calculateLevelCommissions(sale: Sale): Promise<Commission[]> {
const commissions: Commission[] = [];
// Obtener nodo del vendedor
const sourceNode = await this.getNodeByUserId(sale.userId);
// Obtener estructura y tasas
const structure = await this.getStructure(sourceNode.structureId);
const levelRates = structure.levelRates;
// Recorrer upline
let currentNode = await this.getParentNode(sourceNode.id);
let level = 1;
while (currentNode && level <= levelRates.length) {
const rate = levelRates.find(r => r.level === level)?.rate || 0;
if (rate > 0 && currentNode.status === 'active') {
commissions.push({
nodeId: currentNode.id,
sourceNodeId: sourceNode.id,
type: 'level',
level,
sourceAmount: sale.amount,
rateApplied: rate,
commissionAmount: sale.amount * rate
});
}
currentNode = await this.getParentNode(currentNode.id);
level++;
}
return commissions;
}
```
### 5.2 Ejemplo
```
Estructura: 3 niveles (10%, 5%, 3%)
Venta: $1,000
Usuario D hace venta →
Nivel 1 (Usuario C): $1,000 × 10% = $100
Nivel 2 (Usuario B): $1,000 × 5% = $50
Nivel 3 (Usuario A): $1,000 × 3% = $30
```
---
## 6. Frontend (Pendiente)
### 6.1 Paginas Propuestas
| Ruta | Componente | Estado |
|------|------------|--------|
| /dashboard/mlm | MLMDashboard | Pendiente |
| /dashboard/mlm/network | NetworkPage | Pendiente |
| /dashboard/mlm/genealogy | GenealogyPage | Pendiente |
| /dashboard/mlm/ranks | RanksPage | Pendiente |
| /dashboard/mlm/commissions | MLMCommissionsPage | Pendiente |
| /dashboard/mlm/my-network | MyNetworkPage | Pendiente |
### 6.2 Hooks Existentes
```typescript
// frontend/src/hooks/useMlm.ts
useStructures, useStructure, useCreateStructure, useUpdateStructure
useRanks, useRank, useCreateRank, useEvaluateRanks
useNodes, useNode, useNodeDownline, useNodeUpline, useNodeTree
useMyDashboard, useMyNetwork, useMyEarnings, useMyRank, useGenerateInviteLink
useMLMCommissions, useCalculateCommissions, useCommissionsByLevel
```
---
## 7. Seguridad
### 7.1 RLS
```sql
CREATE POLICY nodes_tenant_isolation ON mlm.nodes
USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY commissions_tenant_isolation ON mlm.commissions
USING (tenant_id = current_setting('app.tenant_id')::uuid);
```
### 7.2 Permisos RBAC
| Permiso | Descripcion |
|---------|-------------|
| mlm:read | Ver red y comisiones |
| mlm:write | Gestionar nodos |
| mlm:admin | Administrar estructuras |
| mlm:calculate | Ejecutar calculos |
---
## 8. Integraciones
| Modulo | Integracion |
|--------|-------------|
| sales | Trigger en ventas para comisiones |
| commissions | Periodos compartidos |
| goals | Metas de volumen |
| notifications | Alertas de rango |
| audit | Log de cambios |
---
## 9. Referencias
- DDL: `database/ddl/schemas/mlm/`
- Backend: `backend/src/modules/mlm/`
- Frontend Services: `frontend/src/services/mlm/`
- Frontend Hooks: `frontend/src/hooks/useMlm.ts`

View File

@ -0,0 +1,399 @@
---
id: "ET-SAAS-022"
title: "Especificacion Tecnica Goals"
type: "TechnicalSpec"
status: "Implemented"
priority: "P1"
module: "goals"
version: "1.0.0"
created_date: "2026-02-03"
updated_date: "2026-02-03"
story_points: 8
---
# ET-SAAS-022: Especificacion Tecnica - Sistema de Metas (Goals)
## Metadata
- **Codigo:** ET-SAAS-022
- **Modulo:** Goals
- **Version:** 1.0.0
- **Estado:** Implementado (Backend)
- **Fecha:** 2026-02-03
- **Basado en:** SAAS-022
---
## 1. Resumen Ejecutivo
### 1.1 Estado Actual
Sistema de metas con backend implementado, UI pendiente.
| Capacidad | Estado | Notas |
|-----------|--------|-------|
| Definitions | SI | Definiciones de metas |
| Assignments | SI | Asignaciones usuario/team |
| Progress | SI | Tracking de progreso |
| Milestones | SI | Hitos con notificaciones |
| Auto-tracking | SI | Fuentes automaticas |
| RLS | SI | Row Level Security |
| UI | NO | Frontend pendiente |
### 1.2 Funcionalidades v1.0
Sistema completo con:
- **4 Entidades**: Definitions, Assignments, ProgressLog, MilestoneNotifications
- **3 Tipos de meta**: target, limit, maintain
- **5 Tipos de metrica**: number, currency, percentage, boolean, count
- **6 Periodos**: daily, weekly, monthly, quarterly, yearly, custom
- **Auto-tracking**: Integracion con sales, billing, commissions
---
## 2. Modelo de Datos
### 2.1 Schema: goals
#### Tabla: definitions
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| name | VARCHAR(200) | Nombre de la meta |
| description | TEXT | Descripcion |
| category | VARCHAR(100) | Categoria |
| type | ENUM | target, limit, maintain |
| metric | ENUM | number, currency, percentage, boolean, count |
| target_value | DECIMAL(15,2) | Valor objetivo |
| unit | VARCHAR(50) | USD, units, %, etc. |
| period | ENUM | daily, weekly, monthly, quarterly, yearly, custom |
| starts_at | DATE | Fecha inicio |
| ends_at | DATE | Fecha fin |
| source | ENUM | manual, sales, billing, commissions, custom |
| source_config | JSONB | Configuracion de fuente |
| milestones | JSONB | Hitos de progreso |
| status | ENUM | draft, active, paused, completed, cancelled |
| tags | JSONB | Array de tags |
**Source Config ejemplo:**
```json
{
"module": "sales",
"entity": "opportunities",
"filter": {"stage": "closed_won"},
"aggregation": "sum",
"field": "amount"
}
```
**Milestones ejemplo:**
```json
[
{"percentage": 25, "notify": true},
{"percentage": 50, "notify": true},
{"percentage": 75, "notify": true},
{"percentage": 100, "notify": true}
]
```
#### Tabla: assignments
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| definition_id | UUID | FK definitions |
| assignee_type | ENUM | user, team, tenant |
| user_id | UUID | FK users (si type=user) |
| team_id | UUID | Para futuro modulo de equipos |
| custom_target | DECIMAL(15,2) | Override del target |
| current_value | DECIMAL(15,2) | Valor actual |
| progress_percentage | DECIMAL(5,2) | 0-100% |
| last_updated_at | TIMESTAMPTZ | Ultima actualizacion |
| status | ENUM | active, achieved, failed, cancelled |
| achieved_at | TIMESTAMPTZ | Fecha de logro |
| notes | TEXT | Notas |
#### Tabla: progress_log
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| assignment_id | UUID | FK assignments |
| previous_value | DECIMAL(15,2) | Valor anterior |
| new_value | DECIMAL(15,2) | Nuevo valor |
| change_amount | DECIMAL(15,2) | Diferencia |
| source | ENUM | manual, automatic, import, api |
| source_reference | VARCHAR(200) | ID de transaccion origen |
| notes | TEXT | Notas |
| logged_at | TIMESTAMPTZ | Fecha del log |
| logged_by | UUID | FK users |
#### Tabla: milestone_notifications
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| assignment_id | UUID | FK assignments |
| milestone_percentage | INT | % del hito alcanzado |
| achieved_value | DECIMAL(15,2) | Valor al alcanzar |
| notified_at | TIMESTAMPTZ | Fecha de notificacion |
### 2.2 Enums
```sql
goals.goal_type: target, limit, maintain
goals.metric_type: number, currency, percentage, boolean, count
goals.period_type: daily, weekly, monthly, quarterly, yearly, custom
goals.data_source: manual, sales, billing, commissions, custom
goals.goal_status: draft, active, paused, completed, cancelled
goals.assignee_type: user, team, tenant
goals.assignment_status: active, achieved, failed, cancelled
goals.progress_source: manual, automatic, import, api
```
---
## 3. Tipos de Meta
### 3.1 Target (Alcanzar objetivo)
- **Descripcion**: Alcanzar un valor especifico
- **Ejemplo**: "Vender $50,000 este mes"
- **Logro**: current_value >= target_value
### 3.2 Limit (No exceder)
- **Descripcion**: No superar un limite
- **Ejemplo**: "Mantener gastos bajo $10,000"
- **Logro**: current_value <= target_value durante todo el periodo
### 3.3 Maintain (Mantener valor)
- **Descripcion**: Mantener un valor constante
- **Ejemplo**: "Mantener NPS >= 8.5"
- **Logro**: current_value dentro de rango durante todo el periodo
---
## 4. Arquitectura Backend
### 4.1 Estructura de Archivos
```
backend/src/modules/goals/
├── goals.module.ts
├── controllers/
│ ├── definitions.controller.ts
│ ├── assignments.controller.ts
│ ├── progress.controller.ts
│ └── dashboard.controller.ts
├── services/
│ ├── definitions.service.ts
│ ├── assignments.service.ts
│ ├── progress.service.ts
│ ├── tracking.service.ts
│ └── dashboard.service.ts
├── entities/
│ ├── definition.entity.ts
│ ├── assignment.entity.ts
│ ├── progress-log.entity.ts
│ └── milestone-notification.entity.ts
└── dto/
```
### 4.2 Endpoints API
#### Definitions
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /goals/definitions | Listar |
| GET | /goals/definitions/:id | Obtener |
| POST | /goals/definitions | Crear |
| PUT | /goals/definitions/:id | Actualizar |
| PATCH | /goals/definitions/:id/status | Cambiar status |
| DELETE | /goals/definitions/:id | Eliminar |
| POST | /goals/definitions/:id/duplicate | Duplicar |
#### Assignments
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /goals/assignments | Listar |
| GET | /goals/assignments/:id | Obtener |
| GET | /goals/assignments/user/:userId | Por usuario |
| GET | /goals/assignments/definition/:defId | Por definicion |
| POST | /goals/assignments | Crear |
| PUT | /goals/assignments/:id | Actualizar |
| DELETE | /goals/assignments/:id | Eliminar |
#### Progress
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /goals/progress/:assignmentId | Historial |
| POST | /goals/progress | Registrar progreso |
| POST | /goals/progress/bulk | Registrar multiples |
#### Dashboard
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /goals/dashboard | Resumen general |
| GET | /goals/dashboard/my | Mis metas |
| GET | /goals/dashboard/team/:teamId | Metas del equipo |
| GET | /goals/dashboard/user/:userId | Metas de usuario |
| GET | /goals/dashboard/achieved | Metas logradas |
| GET | /goals/dashboard/at-risk | Metas en riesgo |
---
## 5. Auto-Tracking
### 5.1 Configuracion de Fuentes
```typescript
interface SourceConfig {
module: 'sales' | 'billing' | 'commissions';
entity: string; // 'opportunities', 'invoices', etc.
filter?: Record<string, any>; // Filtros adicionales
aggregation: 'sum' | 'count' | 'avg' | 'min' | 'max';
field?: string; // Campo para sum/avg
}
```
### 5.2 Ejemplo: Meta de Ventas
```json
{
"name": "Ventas Q1 2026",
"type": "target",
"metric": "currency",
"target_value": 100000,
"unit": "USD",
"source": "sales",
"source_config": {
"module": "sales",
"entity": "opportunities",
"filter": {"stage": "closed_won"},
"aggregation": "sum",
"field": "amount"
}
}
```
### 5.3 Flujo de Actualizacion
```typescript
// Listener para eventos de ventas
@OnEvent('opportunity.won')
async handleOpportunityWon(event: OpportunityWonEvent) {
// 1. Buscar metas con source_config que matchee
const goals = await this.findMatchingGoals({
module: 'sales',
entity: 'opportunities',
userId: event.opportunity.assignedTo
});
// 2. Para cada meta, actualizar progreso
for (const assignment of goals) {
await this.updateProgress(assignment.id, {
changeAmount: event.opportunity.amount,
source: 'automatic',
sourceReference: event.opportunity.id
});
}
}
```
---
## 6. Frontend (Pendiente)
### 6.1 Paginas Propuestas
| Ruta | Componente | Estado |
|------|------------|--------|
| /dashboard/goals | GoalsDashboard | Pendiente |
| /dashboard/goals/my | MyGoalsPage | Pendiente |
| /dashboard/goals/definitions | DefinitionsPage | Pendiente |
| /dashboard/goals/new | GoalFormPage | Pendiente |
| /dashboard/goals/:id | GoalDetailPage | Pendiente |
### 6.2 Hooks Existentes
```typescript
// frontend/src/hooks/useGoals.ts
useDefinitions, useDefinition, useCreateDefinition, useUpdateDefinition
useAssignments, useMyAssignments, useUserAssignments
useAssignmentProgress, useUpdateProgress
useGoalsDashboard, useAchievedGoals, useAtRiskGoals
```
---
## 7. Seguridad
### 7.1 RLS
```sql
CREATE POLICY definitions_tenant_isolation ON goals.definitions
USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY assignments_tenant_isolation ON goals.assignments
USING (tenant_id = current_setting('app.tenant_id')::uuid);
```
### 7.2 Permisos RBAC
| Permiso | Descripcion |
|---------|-------------|
| goals:read | Ver metas |
| goals:write | Crear/editar metas |
| goals:assign | Asignar metas |
| goals:progress | Actualizar progreso |
| goals:manage | Administrar |
---
## 8. Notificaciones
### 8.1 Eventos de Notificacion
| Evento | Trigger | Destinatario |
|--------|---------|--------------|
| goal.milestone_reached | Alcanzar % | Usuario asignado |
| goal.achieved | 100% completado | Usuario + Manager |
| goal.at_risk | <50% y queda poco tiempo | Manager |
| goal.failed | Periodo terminado sin lograr | Manager |
### 8.2 Ejemplo de Notificacion
```typescript
interface MilestoneNotification {
type: 'goal.milestone_reached';
userId: string;
data: {
goalName: string;
milestone: 50; // percentage
currentValue: 25000;
targetValue: 50000;
remainingDays: 15;
};
}
```
---
## 9. Integraciones
| Modulo | Integracion |
|--------|-------------|
| sales | Tracking automatico |
| billing | Tracking de ingresos |
| commissions | Metas de comision |
| notifications | Alertas de hitos |
| audit | Log de cambios |
---
## 10. Referencias
- DDL: `database/ddl/schemas/goals/`
- Backend: `backend/src/modules/goals/`
- Frontend Services: `frontend/src/services/goals/`
- Frontend Hooks: `frontend/src/hooks/useGoals.ts`

View File

@ -4,9 +4,9 @@ title: "Mapa Especificaciones"
type: "Index"
status: "Published"
priority: "P2"
version: "1.0.0"
version: "2.0.0"
created_date: "2026-01-10"
updated_date: "2026-01-10"
updated_date: "2026-02-03"
---
# _MAP: Especificaciones Tecnicas
@ -14,8 +14,8 @@ updated_date: "2026-01-10"
**Carpeta:** docs/02-especificaciones/
**Proposito:** Especificaciones tecnicas detalladas
**Estado:** Actualizado
**Sistema:** SIMCO v3.7
**Ultima actualizacion:** 2026-01-10
**Sistema:** SIMCO v4.0
**Ultima actualizacion:** 2026-02-03
---
@ -23,27 +23,52 @@ updated_date: "2026-01-10"
| Metrica | Valor |
|---------|-------|
| Total especificaciones | 1 |
| Completadas | 1 |
| Total especificaciones | 9 |
| Implementadas | 9 |
---
## Contenido
| Archivo | Tipo | Estado | Descripcion |
|---------|------|--------|-------------|
| ET-001-file-storage.md | Especificacion Tecnica | Completado | Sistema de almacenamiento de archivos |
| Archivo | Modulo | Estado | Descripcion |
|---------|--------|--------|-------------|
| ET-SAAS-007-notifications-v2.md | notifications | Implementado | Sistema de notificaciones multi-canal |
| ET-SAAS-015-oauth.md | auth | Implementado | Autenticacion OAuth 2.0 |
| ET-SAAS-016-analytics.md | analytics | Implementado | Sistema de analiticas |
| ET-SAAS-017-reports.md | reports | Implementado | Generacion de reportes |
| ET-SAAS-018-sales.md | sales | Implementado | Pipeline de ventas CRM |
| ET-SAAS-019-portfolio.md | portfolio | Implementado | Catalogo de productos |
| ET-SAAS-020-commissions.md | commissions | Implementado | Sistema de comisiones |
| ET-SAAS-021-mlm.md | mlm | Implementado | Multi-Level Marketing |
| ET-SAAS-022-goals.md | goals | Implementado | Sistema de metas |
---
## Estructura de Especificaciones
Las especificaciones tecnicas siguen el formato ET-NNN y documentan:
- Requisitos tecnicos detallados
- Diagramas de arquitectura
- Flujos de datos
- Consideraciones de rendimiento
Las especificaciones tecnicas siguen el formato ET-SAAS-NNN y documentan:
1. **Resumen Ejecutivo** - Estado actual y propuesta
2. **Modelo de Datos** - Tablas, campos, enums
3. **Arquitectura Backend** - Modulos, endpoints, servicios
4. **Seguridad** - RLS, RBAC, permisos
5. **Frontend** - Paginas, hooks, componentes
6. **Integraciones** - Modulos relacionados
7. **Referencias** - Rutas a codigo fuente
---
**Mantenido por:** Orchestration Team
## Leyenda de Estado
| Estado | Descripcion |
|--------|-------------|
| Draft | En borrador |
| Proposed | Propuesto para revision |
| Approved | Aprobado, pendiente implementacion |
| Implemented | Implementado en codigo |
| Deprecated | Obsoleto |
---
**Mantenido por:** Claude Opus 4.5
**Ultima actualizacion:** 2026-02-03