docs: Add ET-SAAS-018 to ET-SAAS-022 technical specifications
- 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:
parent
ae092a9bb1
commit
2825b3d5fd
289
docs/02-especificaciones/ET-SAAS-018-sales.md
Normal file
289
docs/02-especificaciones/ET-SAAS-018-sales.md
Normal 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/`
|
||||
318
docs/02-especificaciones/ET-SAAS-019-portfolio.md
Normal file
318
docs/02-especificaciones/ET-SAAS-019-portfolio.md
Normal 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/`
|
||||
375
docs/02-especificaciones/ET-SAAS-020-commissions.md
Normal file
375
docs/02-especificaciones/ET-SAAS-020-commissions.md
Normal 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`
|
||||
434
docs/02-especificaciones/ET-SAAS-021-mlm.md
Normal file
434
docs/02-especificaciones/ET-SAAS-021-mlm.md
Normal 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`
|
||||
399
docs/02-especificaciones/ET-SAAS-022-goals.md
Normal file
399
docs/02-especificaciones/ET-SAAS-022-goals.md
Normal 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`
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user