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