--- id: "SAAS-020" title: "Commissions" type: "Module" status: "Completed" priority: "P2" module: "commissions" version: "1.0.0" created_date: "2026-01-24" updated_date: "2026-01-24" completed_date: "2026-01-24" estimated_sp: 13 --- # SAAS-020: Commissions ## Metadata - **Codigo:** SAAS-020 - **Modulo:** Commissions - **Prioridad:** P2 - **Estado:** Completado - **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. [x] Esquemas porcentaje, fijo y escalonado 2. [x] Asignacion esquema-vendedor funcional 3. [x] Calculo automatico de comisiones 4. [x] Gestion de periodos de pago 5. [x] Dashboard de earnings 6. [x] Reportes por vendedor y periodo 7. [ ] Tests unitarios (>70% coverage) - Pendiente ## Estimacion | Componente | SP | |------------|-----| | DDL + Entities | 2 | | Backend Services | 4 | | Controllers + DTOs | 2 | | Frontend Pages | 3 | | Frontend Components | 2 | | Tests | 1 | | **Total** | **13** | ## Implementacion ### Backend (NestJS) - **Entities:** CommissionScheme, CommissionAssignment, CommissionEntry, CommissionPeriod - **Services:** SchemesService, AssignmentsService, EntriesService, PeriodsService, CommissionsDashboardService - **Controllers:** SchemesController, AssignmentsController, EntriesController, PeriodsController, DashboardController - **DTOs:** Create/Update DTOs para cada entidad (scheme.dto, assignment.dto, entry.dto, period.dto, dashboard.dto) - **Tests:** Pendiente - 0 tests unitarios actualmente ### Frontend (React) - **Pages:** /commissions, /commissions/schemes, /commissions/entries, /commissions/periods, /commissions/my-earnings - **Components:** CommissionsDashboard, SchemesList, SchemeForm, TiersEditor, EntriesList, PeriodManager, EarningsCard, CommissionCalculator - **Hooks:** useSchemes, useAssignments, useEntries, usePeriods, useMyEarnings, useCommissionsDashboard (+22 hooks adicionales) - **Services:** schemes.api, assignments.api, entries.api, periods.api, dashboard.api ### Database (PostgreSQL) - **Schema:** commissions - **Tables:** schemes, assignments, entries, periods - **Enums:** scheme_type, applies_to, entry_status, period_status - **RLS:** Tenant isolation policies aplicadas a todas las tablas --- **Ultima actualizacion:** 2026-01-24 **Implementado por:** Claude Opus 4.5