# TRACEABILITY.yml - MAI-003: Presupuestos y Control de Costos # Matriz completa de trazabilidad: Requerimientos → Especificaciones → Historias → Implementación epic_code: MAI-003 epic_name: Presupuestos y Control de Costos phase: 2 phase_name: Core Business budget_mxn: 35000 story_points: 46 status: planned sprint: 7-10 period: "Semanas 13-20" reused_from_gamilit: 0% # ============================================================================ # METADATA # ============================================================================ metadata: modulo: MAI-003 nombre: Presupuestos y Control de Costos version: 1.0.0 fecha: 2025-12-06 descripcion: Sistema integral de presupuestos de construcción en tres niveles (obra, etapa, prototipo), catálogo de conceptos con precios unitarios, control de costos reales y análisis de rentabilidad objetivo_negocio: Incrementar margen de utilidad +2 puntos mediante control preciso de costos, reducción 80% en tiempo de elaboración de presupuestos, y detección temprana de desviaciones impacto_esperado: - Eficiencia en elaboración de presupuestos (2h vs 10h) - Precisión en estimación de costos (<3% desviación vs real) - Control en tiempo real de costos - Mejora en rentabilidad por proyecto # ============================================================================ # DOCUMENTACIÓN # ============================================================================ documentation: requirements: - id: RF-COST-001 file: requerimientos/RF-COST-001-catalogo-conceptos-precios.md title: Catálogo de Conceptos y Precios Unitarios status: planned reused_from: null adaptations: - "Sistema nuevo específico para construcción" - "4 tipos de conceptos: material, mano de obra, maquinaria, compuesto" - "Catálogo jerárquico por división CMIC (16 capítulos)" - "Análisis de precios unitarios (APU) detallado" - "Versionado y historial de precios" - "Regionalización de precios por plaza" - id: RF-COST-002 file: requerimientos/RF-COST-002-presupuestos-maestros.md title: Presupuestos Maestros (Obra, Etapa, Prototipo) status: planned reused_from: null adaptations: - "3 niveles jerárquicos de presupuestos" - "Generadores automáticos de volumetrías" - "Versionado completo (baseline, ajustes, cambios)" - "Integración con catálogo de conceptos" - "Análisis de rentabilidad integrado" - id: RF-COST-003 file: requerimientos/RF-COST-003-control-costos-reales.md title: Control de Costos Reales y Desviaciones status: planned reused_from: null adaptations: - "Registro automático desde compras, nómina, subcontratos" - "Dashboard con curva S" - "Cálculo de desviaciones (precio, cantidad, mixta)" - "Proyecciones EAC (3 métodos)" - "Alertas automáticas configurables" - id: RF-COST-004 file: requerimientos/RF-COST-004-analisis-rentabilidad.md title: Análisis de Rentabilidad y Márgenes status: planned reused_from: null adaptations: - "Análisis financiero por proyecto y prototipo" - "Punto de equilibrio y margen de seguridad" - "Simulador de escenarios" - "Matriz de sensibilidad (precio vs costo)" - "ROI y TIR proyectados" specifications: - id: ET-COST-001 file: especificaciones/ET-COST-001-implementacion-catalogo-conceptos.md rf: RF-COST-001 title: Implementación del Catálogo de Conceptos status: planned reused_from: null adaptations: - "Schema budgets en PostgreSQL" - "Búsqueda full-text con índices GIN" - "Triggers para historial automático de precios" - "Cálculo automático de PU compuestos" - id: ET-COST-002 file: especificaciones/ET-COST-002-implementacion-presupuestos.md rf: RF-COST-002 title: Implementación de Presupuestos status: planned reused_from: null adaptations: - "Estructura jerárquica de partidas (3 niveles)" - "Wizard de creación desde prototipos" - "Triggers para cálculo automático de totales" - "Versionado con comparación" - id: ET-COST-003 file: especificaciones/ET-COST-003-implementacion-control-costos.md rf: RF-COST-003 title: Implementación de Control de Costos status: planned reused_from: null adaptations: - "Integración con módulos de Compras/Nómina/Subcontratos" - "Recálculo automático de desviaciones" - "Proyección EAC con múltiples métodos" - "Cron job diario para actualización (6:00 AM)" - id: ET-COST-004 file: especificaciones/ET-COST-004-implementacion-analisis-rentabilidad.md rf: RF-COST-004 title: Implementación de Análisis de Rentabilidad status: planned reused_from: null adaptations: - "Cálculo automático de indicadores financieros" - "Simulador interactivo de escenarios" - "Matriz de sensibilidad con visualización" - "Comparación de prototipos" user_stories: - id: US-COST-001 file: historias-usuario/US-COST-001-catalogo-conceptos.md title: Catálogo de Conceptos y Búsqueda rf: [RF-COST-001] et: [ET-COST-001] story_points: 5 status: planned sprint: 7 reused_from: null adaptations: ["Nuevo desarrollo completo"] - id: US-COST-002 file: historias-usuario/US-COST-002-precios-compuestos.md title: Precios Unitarios Compuestos rf: [RF-COST-001] et: [ET-COST-001] story_points: 5 status: planned sprint: 7 reused_from: null adaptations: ["Cálculo automático de APU"] - id: US-COST-003 file: historias-usuario/US-COST-003-actualizacion-precios.md title: Actualización Masiva de Precios rf: [RF-COST-001] et: [ET-COST-001] story_points: 3 status: planned sprint: 7 reused_from: null adaptations: ["Actualización con preview y confirmación"] - id: US-COST-004 file: historias-usuario/US-COST-004-presupuesto-obra.md title: Presupuesto de Obra Completo rf: [RF-COST-002] et: [ET-COST-002] story_points: 8 status: planned sprint: 8 reused_from: null adaptations: ["Wizard multi-paso con validaciones"] - id: US-COST-005 file: historias-usuario/US-COST-005-presupuesto-prototipo.md title: Presupuesto de Prototipo con Generadores rf: [RF-COST-002] et: [ET-COST-002] story_points: 5 status: planned sprint: 8 reused_from: null adaptations: ["Generadores automáticos de volumetrías"] - id: US-COST-006 file: historias-usuario/US-COST-006-dashboard-control-costos.md title: Dashboard de Control de Costos Reales rf: [RF-COST-003] et: [ET-COST-003] story_points: 5 status: planned sprint: 9 reused_from: null adaptations: ["Dashboard con curva S y KPIs"] - id: US-COST-007 file: historias-usuario/US-COST-007-analisis-desviaciones.md title: Análisis de Desviaciones y Plan de Acción rf: [RF-COST-003] et: [ET-COST-003] story_points: 5 status: planned sprint: 9 reused_from: null adaptations: ["Análisis de causa raíz con alertas"] - id: US-COST-008 file: historias-usuario/US-COST-008-analisis-rentabilidad.md title: Análisis de Rentabilidad y Simulaciones rf: [RF-COST-004] et: [ET-COST-004] story_points: 5 status: planned sprint: 10 reused_from: null adaptations: ["Simulador interactivo con matriz de sensibilidad"] # ============================================================================ # IMPLEMENTACIÓN - BASE DE DATOS # ============================================================================ implementation: database: schemas: - name: budgets path: apps/database/ddl/schemas/budgets/ description: Schema para presupuestos, catálogo de conceptos y control de costos reused_from_gamilit: false note: "Schema completamente nuevo para módulo de construcción" enums: - name: concept_type schema: budgets file: apps/database/ddl/schemas/budgets/00-prerequisites.sql lines: "10-14" values: [material, labor, equipment, composite] rf: RF-COST-001 reused_from: null note: "4 tipos de conceptos de obra" - name: budget_type schema: budgets file: apps/database/ddl/schemas/budgets/00-prerequisites.sql lines: "16-20" values: [project, stage, prototype] rf: RF-COST-002 reused_from: null note: "3 niveles de presupuestos" - name: budget_status schema: budgets file: apps/database/ddl/schemas/budgets/00-prerequisites.sql lines: "22-26" values: [draft, active, approved, closed] rf: RF-COST-002 reused_from: null - name: version_type schema: budgets file: apps/database/ddl/schemas/budgets/00-prerequisites.sql lines: "28-32" values: [baseline, price_adjustment, scope_change, additional_volume] rf: RF-COST-002 reused_from: null tables: - name: concept_catalog schema: budgets file: apps/database/ddl/schemas/budgets/tables/01-concept_catalog.sql lines: 150 description: Catálogo maestro de conceptos de obra con precios unitarios rf: RF-COST-001 reused_from_gamilit: false note: "Tabla central del módulo de presupuestos" columns: - id (UUID, PK) - constructora_id (UUID, FK) - code (VARCHAR(20), UNIQUE per constructora) - name (VARCHAR(255)) - description (TEXT) - concept_type (ENUM) - category (VARCHAR(100)) # División CMIC - subcategory (VARCHAR(100)) # Grupo CMIC - unit (VARCHAR(20)) # m³, m², kg, pza, jornal - base_price (DECIMAL(12,2)) - includes_vat (BOOLEAN) - currency (VARCHAR(3)) - waste_factor (DECIMAL(5,3)) - components (JSONB) # Para conceptos compuestos - labor_crew (JSONB) # Cuadrilla tipo - indirect_percentage (DECIMAL(5,2)) - financing_percentage (DECIMAL(5,2)) - profit_percentage (DECIMAL(5,2)) - additional_charges (DECIMAL(5,2)) - direct_cost (DECIMAL(12,2)) - unit_price (DECIMAL(12,2)) - unit_price_with_vat (DECIMAL(12,2)) - region_id (UUID, FK) - preferred_supplier_id (UUID, FK) - technical_specs (TEXT) - performance (VARCHAR(255)) - version (INTEGER) - status (VARCHAR(20)) - created_by (UUID) - created_at (TIMESTAMP) - updated_at (TIMESTAMP) - name: concept_price_history schema: budgets file: apps/database/ddl/schemas/budgets/tables/02-concept_price_history.sql lines: 60 description: Historial de cambios de precios de conceptos rf: RF-COST-001 reused_from_gamilit: false columns: - id (UUID, PK) - concept_id (UUID, FK) - price (DECIMAL(12,2)) - valid_from (DATE) - valid_until (DATE) - variation_percentage (DECIMAL(6,2)) - reason (VARCHAR(255)) - created_by (UUID) - created_at (TIMESTAMP) - name: regions schema: budgets file: apps/database/ddl/schemas/budgets/tables/03-regions.sql lines: 40 description: Catálogo de regiones para precios regionalizados rf: RF-COST-001 reused_from_gamilit: false columns: - id (UUID, PK) - constructora_id (UUID, FK) - code (VARCHAR(10)) - name (VARCHAR(100)) - description (TEXT) - is_active (BOOLEAN) - created_at (TIMESTAMP) - name: budgets schema: budgets file: apps/database/ddl/schemas/budgets/tables/04-budgets.sql lines: 180 description: Presupuestos maestros (obra, etapa, prototipo) rf: RF-COST-002 reused_from_gamilit: false columns: - id (UUID, PK) - constructora_id (UUID, FK) - project_id (UUID, FK nullable) - stage_id (UUID, FK nullable) - prototype_id (UUID, FK nullable) - code (VARCHAR(20), UNIQUE) - name (VARCHAR(255)) - budget_type (ENUM) - version (INTEGER) - is_baseline (BOOLEAN) - status (ENUM) - housing_units_count (INTEGER) - total_built_area (DECIMAL(12,2)) - total_land_area (DECIMAL(12,2)) - direct_cost (DECIMAL(15,2)) - indirect_percentage (DECIMAL(5,2)) - indirect_amount (DECIMAL(15,2)) - financing_percentage (DECIMAL(5,2)) - financing_amount (DECIMAL(15,2)) - profit_percentage (DECIMAL(5,2)) - profit_amount (DECIMAL(15,2)) - additional_charges (DECIMAL(15,2)) - total_cost (DECIMAL(15,2)) - sale_price (DECIMAL(15,2)) - gross_margin (DECIMAL(15,2)) - margin_percentage (DECIMAL(5,2)) - roi (DECIMAL(5,2)) - cost_per_sqm (DECIMAL(10,2)) - cost_per_unit (DECIMAL(12,2)) - approved_by (UUID) - approved_at (TIMESTAMP) - created_by (UUID) - created_at (TIMESTAMP) - updated_at (TIMESTAMP) - name: budget_items schema: budgets file: apps/database/ddl/schemas/budgets/tables/05-budget_items.sql lines: 120 description: Partidas jerárquicas del presupuesto (3 niveles) rf: RF-COST-002 reused_from_gamilit: false columns: - id (UUID, PK) - budget_id (UUID, FK) - parent_item_id (UUID, FK nullable) - level (INTEGER) # 1=División, 2=Grupo, 3=Concepto - sort_order (INTEGER) - concept_id (UUID, FK nullable) - code (VARCHAR(20)) - name (VARCHAR(255)) - unit (VARCHAR(20)) - quantity (DECIMAL(12,4)) - unit_price (DECIMAL(12,2)) - amount (DECIMAL(15,2)) - has_generator (BOOLEAN) - generator_formula (TEXT) - generator_inputs (JSONB) - notes (TEXT) - created_at (TIMESTAMP) - updated_at (TIMESTAMP) - name: budget_versions schema: budgets file: apps/database/ddl/schemas/budgets/tables/06-budget_versions.sql lines: 70 description: Historial de versiones de presupuestos rf: RF-COST-002 reused_from_gamilit: false columns: - id (UUID, PK) - budget_id (UUID, FK) - version (INTEGER) - version_type (ENUM) - previous_version_id (UUID, FK nullable) - total_cost (DECIMAL(15,2)) - variation_amount (DECIMAL(15,2)) - variation_percentage (DECIMAL(6,2)) - reason (TEXT) - approved_by (UUID) - created_at (TIMESTAMP) - name: actual_costs schema: budgets file: apps/database/ddl/schemas/budgets/tables/07-actual_costs.sql lines: 100 description: Registro de costos reales de construcción rf: RF-COST-003 reused_from_gamilit: false columns: - id (UUID, PK) - constructora_id (UUID, FK) - project_id (UUID, FK) - stage_id (UUID, FK nullable) - budget_item_id (UUID, FK) - source_type (ENUM) # purchase, payroll, subcontract, equipment, other - source_id (UUID) - source_document_number (VARCHAR(50)) - amount (DECIMAL(15,2)) - currency (VARCHAR(3)) - includes_vat (BOOLEAN) - transaction_date (DATE) - accounting_period (VARCHAR(7)) # 2025-11 - cost_type (ENUM) # material, labor, equipment, subcontract, indirect - notes (TEXT) - created_by (UUID) - created_at (TIMESTAMP) - name: cost_variances schema: budgets file: apps/database/ddl/schemas/budgets/tables/08-cost_variances.sql lines: 90 description: Análisis de desviaciones presupuesto vs real rf: RF-COST-003 reused_from_gamilit: false columns: - id (UUID, PK) - project_id (UUID, FK) - budget_item_id (UUID, FK) - analysis_date (DATE) - budgeted_amount (DECIMAL(15,2)) - actual_amount (DECIMAL(15,2)) - variance (DECIMAL(15,2)) - variance_percentage (DECIMAL(6,2)) - price_variance (DECIMAL(15,2)) - quantity_variance (DECIMAL(15,2)) - mixed_variance (DECIMAL(15,2)) - status (ENUM) # within_tolerance, warning, critical - root_cause (TEXT) - action_plan (TEXT) - responsible_user_id (UUID) - created_at (TIMESTAMP) - name: cost_projections schema: budgets file: apps/database/ddl/schemas/budgets/tables/09-cost_projections.sql lines: 80 description: Proyecciones de costo final (EAC) rf: RF-COST-003 reused_from_gamilit: false columns: - id (UUID, PK) - project_id (UUID, FK) - projection_date (DATE) - physical_progress (DECIMAL(5,2)) - budgeted_total_cost (DECIMAL(15,2)) - actual_cost_to_date (DECIMAL(15,2)) - linear_projection (DECIMAL(15,2)) - cpi_based_projection (DECIMAL(15,2)) - weighted_projection (DECIMAL(15,2)) - recommended_eac (DECIMAL(15,2)) - cpi (DECIMAL(5,3)) # Cost Performance Index - spi (DECIMAL(5,3)) # Schedule Performance Index - created_at (TIMESTAMP) - name: profitability_analysis schema: budgets file: apps/database/ddl/schemas/budgets/tables/10-profitability_analysis.sql lines: 110 description: Análisis de rentabilidad por proyecto rf: RF-COST-004 reused_from_gamilit: false columns: - id (UUID, PK) - constructora_id (UUID, FK) - project_id (UUID, FK) - analysis_date (DATE) - analysis_type (ENUM) # actual, projected, scenario - total_revenue (DECIMAL(15,2)) - average_sale_price (DECIMAL(12,2)) - units_to_sell (INTEGER) - construction_cost (DECIMAL(15,2)) - land_cost (DECIMAL(15,2)) - marketing_cost (DECIMAL(15,2)) - administrative_cost (DECIMAL(15,2)) - financial_cost (DECIMAL(15,2)) - total_costs (DECIMAL(15,2)) - gross_profit (DECIMAL(15,2)) - gross_margin (DECIMAL(6,2)) - net_profit (DECIMAL(15,2)) - net_margin (DECIMAL(6,2)) - roi (DECIMAL(6,2)) - irr (DECIMAL(6,2)) - payback_months (INTEGER) - break_even_units (INTEGER) - fixed_costs (DECIMAL(15,2)) - variable_cost_per_unit (DECIMAL(12,2)) - contribution_margin (DECIMAL(12,2)) - created_by (UUID) - created_at (TIMESTAMP) - name: prototype_profitability schema: budgets file: apps/database/ddl/schemas/budgets/tables/11-prototype_profitability.sql lines: 70 description: Rentabilidad comparativa por prototipo rf: RF-COST-004 reused_from_gamilit: false columns: - id (UUID, PK) - project_id (UUID, FK) - prototype_id (UUID, FK) - units_planned (INTEGER) - units_sold (INTEGER) - units_delivered (INTEGER) - sale_price (DECIMAL(12,2)) - construction_cost (DECIMAL(12,2)) - land_cost_allocated (DECIMAL(12,2)) - indirect_costs (DECIMAL(12,2)) - unit_profit (DECIMAL(12,2)) - unit_margin (DECIMAL(6,2)) - total_profit (DECIMAL(15,2)) - average_construction_days (INTEGER) - sales_conversion_rate (DECIMAL(5,2)) - updated_at (TIMESTAMP) functions: - name: calculate_composite_price schema: budgets file: apps/database/ddl/schemas/budgets/functions/calculate_composite_price.sql lines: "10-80" description: Calcula precio unitario de concepto compuesto (APU) rf: RF-COST-001 reused_from_gamilit: false note: "Suma materiales + MO + maquinaria + factores" - name: calculate_variances schema: budgets file: apps/database/ddl/schemas/budgets/functions/calculate_variances.sql lines: "10-100" description: Genera análisis de desviaciones por partida rf: RF-COST-003 reused_from_gamilit: false note: "Descompone en precio, cantidad y mixta" - name: calculate_eac schema: budgets file: apps/database/ddl/schemas/budgets/functions/calculate_eac.sql lines: "10-70" description: Proyección de costo final (3 métodos) rf: RF-COST-003 reused_from_gamilit: false note: "Lineal, CPI-based, ponderado" - name: calculate_profitability schema: budgets file: apps/database/ddl/schemas/budgets/functions/calculate_profitability.sql lines: "10-90" description: Análisis de rentabilidad del proyecto rf: RF-COST-004 reused_from_gamilit: false note: "Margen, ROI, TIR, punto de equilibrio" triggers: - table: budgets.concept_catalog trigger: trigger_concept_updated_at description: Actualiza timestamp al modificar concepto rf: RF-COST-001 reused_from_gamilit: false sql: | CREATE TRIGGER trigger_concept_updated_at BEFORE UPDATE ON budgets.concept_catalog FOR EACH ROW EXECUTE FUNCTION budgets.update_concept_timestamp(); - table: budgets.concept_catalog trigger: trigger_create_price_history description: Crea registro en historial al cambiar precio rf: RF-COST-001 reused_from_gamilit: false sql: | CREATE TRIGGER trigger_create_price_history AFTER UPDATE ON budgets.concept_catalog FOR EACH ROW WHEN (NEW.base_price IS DISTINCT FROM OLD.base_price) EXECUTE FUNCTION budgets.create_price_history(); - table: budgets.budget_items trigger: trigger_budget_items_calculate description: Recalcula totales del presupuesto al modificar partidas rf: RF-COST-002 reused_from_gamilit: false sql: | CREATE TRIGGER trigger_budget_items_calculate AFTER INSERT OR UPDATE OR DELETE ON budgets.budget_items FOR EACH ROW EXECUTE FUNCTION budgets.calculate_budget_totals(); - table: budgets.actual_costs trigger: trigger_actual_costs_update_variance description: Actualiza desviaciones al registrar costo real rf: RF-COST-003 reused_from_gamilit: false sql: | CREATE TRIGGER trigger_actual_costs_update_variance AFTER INSERT ON budgets.actual_costs FOR EACH ROW EXECUTE FUNCTION budgets.update_cost_variance(); rls_policies: - table: budgets.concept_catalog policy: concept_catalog_select_own description: Usuarios solo ven conceptos de su constructora rf: RF-COST-001 reused_from_gamilit: false sql: | CREATE POLICY "concept_catalog_select_own" ON budgets.concept_catalog FOR SELECT TO authenticated USING ( constructora_id = get_current_constructora_id() ); - table: budgets.budgets policy: budgets_select_own description: Usuarios solo ven presupuestos de su constructora rf: RF-COST-002 reused_from_gamilit: false sql: | CREATE POLICY "budgets_select_own" ON budgets.budgets FOR SELECT TO authenticated USING ( constructora_id = get_current_constructora_id() ); - table: budgets.actual_costs policy: actual_costs_select_own description: Usuarios solo ven costos de su constructora rf: RF-COST-003 reused_from_gamilit: false sql: | CREATE POLICY "actual_costs_select_own" ON budgets.actual_costs FOR SELECT TO authenticated USING ( constructora_id = get_current_constructora_id() ); # ============================================================================ # IMPLEMENTACIÓN - BACKEND # ============================================================================ backend: modules: - name: budgets path: apps/backend/src/modules/budgets/ description: Módulo completo de presupuestos, catálogo y control de costos rf: [RF-COST-001, RF-COST-002, RF-COST-003, RF-COST-004] reused_from_gamilit: false adaptations: - "Módulo nuevo completo para construcción" - "4 servicios principales (Catalog, Budget, CostControl, Profitability)" services: - name: ConceptCatalogService path: apps/backend/src/modules/budgets/concept-catalog.service.ts description: Lógica de gestión del catálogo de conceptos rf: [RF-COST-001] reused_from_gamilit: false methods: - create(dto) - findAll(filters) - findOne(id) - update(id, dto) - delete(id) - calculateCompositePrice(conceptId) - massUpdatePrices(categoryId, adjustmentPercentage) - exportToExcel() - importFromExcel(file) - name: BudgetService path: apps/backend/src/modules/budgets/budget.service.ts description: Lógica de elaboración y gestión de presupuestos rf: [RF-COST-002] reused_from_gamilit: false methods: - createBudget(dto) - generateFromPrototype(prototypeId) - addBudgetItem(budgetId, itemDto) - calculateTotals(budgetId) - createVersion(budgetId, versionType, reason) - compareVersions(budgetId, v1, v2) - approveBudget(budgetId) - exportToPdf(budgetId) - name: CostControlService path: apps/backend/src/modules/budgets/cost-control.service.ts description: Lógica de control de costos reales y desviaciones rf: [RF-COST-003] reused_from_gamilit: false methods: - registerActualCost(dto) - calculateVariances(projectId) - projectEAC(projectId, method) - getCostDashboard(projectId) - generateAlerts(projectId) - getCurveS(projectId) - createActionPlan(varianceId, actionPlan) - name: ProfitabilityService path: apps/backend/src/modules/budgets/profitability.service.ts description: Lógica de análisis de rentabilidad y simulaciones rf: [RF-COST-004] reused_from_gamilit: false methods: - analyzeProjectProfitability(projectId) - analyzePrototypeProfitability(prototypeId) - calculateBreakEven(projectId) - simulateScenarios(projectId, scenarios) - sensitivityMatrix(projectId, priceRange, costRange) - compareProjects(projectIds) - calculateROI(projectId) controllers: - name: ConceptCatalogController path: apps/backend/src/modules/budgets/concept-catalog.controller.ts description: Endpoints del catálogo de conceptos rf: RF-COST-001 reused_from_gamilit: false endpoints: - "POST /api/v1/budgets/concepts" - "GET /api/v1/budgets/concepts" - "GET /api/v1/budgets/concepts/:id" - "PATCH /api/v1/budgets/concepts/:id" - "DELETE /api/v1/budgets/concepts/:id" - "POST /api/v1/budgets/concepts/:id/calculate-price" - "POST /api/v1/budgets/concepts/mass-update" - "GET /api/v1/budgets/concepts/:id/price-history" - "POST /api/v1/budgets/concepts/import" - name: BudgetController path: apps/backend/src/modules/budgets/budget.controller.ts description: Endpoints de presupuestos rf: RF-COST-002 reused_from_gamilit: false endpoints: - "POST /api/v1/budgets" - "GET /api/v1/budgets" - "GET /api/v1/budgets/:id" - "PATCH /api/v1/budgets/:id" - "DELETE /api/v1/budgets/:id" - "POST /api/v1/budgets/:id/items" - "POST /api/v1/budgets/:id/versions" - "GET /api/v1/budgets/:id/versions" - "GET /api/v1/budgets/:id/compare/:v1/:v2" - "POST /api/v1/budgets/:id/approve" - "GET /api/v1/budgets/:id/export/pdf" - "POST /api/v1/budgets/generate-from-prototype/:prototypeId" - name: CostControlController path: apps/backend/src/modules/budgets/cost-control.controller.ts description: Endpoints de control de costos rf: RF-COST-003 reused_from_gamilit: false endpoints: - "POST /api/v1/budgets/actual-costs" - "GET /api/v1/budgets/projects/:projectId/cost-control" - "GET /api/v1/budgets/projects/:projectId/variances" - "GET /api/v1/budgets/projects/:projectId/eac" - "GET /api/v1/budgets/projects/:projectId/curve-s" - "GET /api/v1/budgets/projects/:projectId/alerts" - "POST /api/v1/budgets/variances/:varianceId/action-plan" - "GET /api/v1/budgets/projects/:projectId/cost-breakdown" - name: ProfitabilityController path: apps/backend/src/modules/budgets/profitability.controller.ts description: Endpoints de análisis de rentabilidad rf: RF-COST-004 reused_from_gamilit: false endpoints: - "GET /api/v1/budgets/projects/:projectId/profitability" - "GET /api/v1/budgets/prototypes/:prototypeId/profitability" - "GET /api/v1/budgets/projects/:projectId/break-even" - "POST /api/v1/budgets/projects/:projectId/simulate" - "GET /api/v1/budgets/projects/:projectId/sensitivity" - "POST /api/v1/budgets/portfolio/compare" cron_jobs: - name: DailyCostAnalysisTask path: apps/backend/src/modules/budgets/tasks/daily-cost-analysis.task.ts schedule: "0 6 * * *" # Diario a las 6:00 AM description: Análisis diario de costos y generación de alertas rf: RF-COST-003 reused_from_gamilit: false enums: - name: ConceptType path: apps/backend/src/modules/budgets/enums/concept-type.enum.ts description: Enum TypeScript de tipos de conceptos rf: RF-COST-001 reused_from: null values: - MATERIAL = 'material' - LABOR = 'labor' - EQUIPMENT = 'equipment' - COMPOSITE = 'composite' - name: BudgetType path: apps/backend/src/modules/budgets/enums/budget-type.enum.ts description: Enum TypeScript de tipos de presupuestos rf: RF-COST-002 reused_from: null values: - PROJECT = 'project' - STAGE = 'stage' - PROTOTYPE = 'prototype' # ============================================================================ # IMPLEMENTACIÓN - FRONTEND # ============================================================================ frontend: features: - name: budgets path: apps/frontend/src/features/budgets/ description: Feature completo de presupuestos y control de costos rf: [RF-COST-001, RF-COST-002, RF-COST-003, RF-COST-004] reused_from_gamilit: false adaptations: ["Feature nuevo completo para construcción"] pages: - name: ConceptCatalogPage path: apps/frontend/src/features/budgets/pages/ConceptCatalogPage.tsx route: /concept-catalog description: Página principal del catálogo de conceptos rf: RF-COST-001 reused_from_gamilit: false - name: BudgetDetailPage path: apps/frontend/src/features/budgets/pages/BudgetDetailPage.tsx route: /budgets/:id description: Detalle y edición de presupuesto rf: RF-COST-002 reused_from_gamilit: false - name: CostControlDashboardPage path: apps/frontend/src/features/budgets/pages/CostControlDashboardPage.tsx route: /projects/:projectId/cost-control description: Dashboard de control de costos rf: RF-COST-003 reused_from_gamilit: false - name: ProfitabilityAnalysisPage path: apps/frontend/src/features/budgets/pages/ProfitabilityAnalysisPage.tsx route: /projects/:projectId/profitability description: Análisis de rentabilidad y simulaciones rf: RF-COST-004 reused_from_gamilit: false components: - name: ConceptCatalogList path: apps/frontend/src/features/budgets/components/ConceptCatalogList.tsx description: Lista de conceptos con búsqueda y filtros rf: RF-COST-001 reused_from_gamilit: false note: "Incluye búsqueda full-text, filtros por tipo/categoría" - name: CreateConceptModal path: apps/frontend/src/features/budgets/components/CreateConceptModal.tsx description: Modal para crear concepto compuesto con APU rf: RF-COST-001 reused_from_gamilit: false note: "Formulario multi-sección: materiales, MO, maquinaria, factores" - name: BudgetItemsTree path: apps/frontend/src/features/budgets/components/BudgetItemsTree.tsx description: Árbol jerárquico de partidas presupuestales rf: RF-COST-002 reused_from_gamilit: false note: "3 niveles: División, Grupo, Concepto" - name: BudgetWizard path: apps/frontend/src/features/budgets/components/BudgetWizard.tsx description: Wizard multi-paso para crear presupuesto rf: RF-COST-002 reused_from_gamilit: false note: "Pasos: Tipo, Alcance, Conceptos, Factores, Resumen" - name: CurveSChart path: apps/frontend/src/features/budgets/components/CurveSChart.tsx description: Gráfica de curva S (Presupuestado vs Real vs Proyectado) rf: RF-COST-003 reused_from_gamilit: false note: "Chart.js con 3 líneas de tendencia" - name: VarianceAnalysisTable path: apps/frontend/src/features/budgets/components/VarianceAnalysisTable.tsx description: Tabla de análisis de desviaciones por partida rf: RF-COST-003 reused_from_gamilit: false note: "Descompone en precio, cantidad, mixta" - name: ProfitabilityDashboard path: apps/frontend/src/features/budgets/components/ProfitabilityDashboard.tsx description: Dashboard ejecutivo de rentabilidad rf: RF-COST-004 reused_from_gamilit: false note: "KPIs: Margen, ROI, TIR, Punto de equilibrio" - name: ScenarioSimulator path: apps/frontend/src/features/budgets/components/ScenarioSimulator.tsx description: Simulador interactivo de escenarios rf: RF-COST-004 reused_from_gamilit: false note: "Sliders para precio/costo/volumen, cálculo en vivo" - name: SensitivityMatrix path: apps/frontend/src/features/budgets/components/SensitivityMatrix.tsx description: Matriz de sensibilidad (precio vs costo) rf: RF-COST-004 reused_from_gamilit: false note: "Heat map con colores según margen" stores: - name: useConceptCatalogStore path: apps/frontend/src/stores/budgets/conceptCatalogStore.ts description: Store de catálogo de conceptos (Zustand) rf: RF-COST-001 reused_from_gamilit: false state: - concepts (array) - filters (object) - selectedConcept (object) - isLoading (boolean) - name: useBudgetStore path: apps/frontend/src/stores/budgets/budgetStore.ts description: Store de presupuestos (Zustand) rf: RF-COST-002 reused_from_gamilit: false state: - budgets (array) - currentBudget (object) - budgetItems (array) - versions (array) - isLoading (boolean) - name: useCostControlStore path: apps/frontend/src/stores/budgets/costControlStore.ts description: Store de control de costos (Zustand) rf: RF-COST-003 reused_from_gamilit: false state: - actualCosts (array) - variances (array) - projections (object) - alerts (array) - curveSData (object) - name: useProfitabilityStore path: apps/frontend/src/stores/budgets/profitabilityStore.ts description: Store de análisis de rentabilidad (Zustand) rf: RF-COST-004 reused_from_gamilit: false state: - profitabilityAnalysis (object) - scenarios (array) - sensitivityMatrix (array) - comparativeData (array) # ============================================================================ # TESTING # ============================================================================ testing: unit_tests: - module: ConceptCatalogService file: apps/backend/src/modules/budgets/concept-catalog.service.spec.ts coverage_target: 85% reused_from_gamilit: false key_tests: - "create concept simple (material)" - "create concept composite (APU calculation)" - "mass update prices by category" - "calculate composite price with components" - module: BudgetService file: apps/backend/src/modules/budgets/budget.service.spec.ts coverage_target: 85% reused_from_gamilit: false key_tests: - "create budget from prototype" - "calculate totals trigger" - "create version (baseline, adjustment)" - "compare versions" - module: CostControlService file: apps/backend/src/modules/budgets/cost-control.service.spec.ts coverage_target: 85% reused_from_gamilit: false key_tests: - "register actual cost from purchase" - "calculate variances (price, quantity, mixed)" - "project EAC (3 methods)" - "generate alerts on threshold" - module: ProfitabilityService file: apps/backend/src/modules/budgets/profitability.service.spec.ts coverage_target: 85% reused_from_gamilit: false key_tests: - "calculate project profitability" - "break-even calculation" - "ROI and TIR calculation" - "scenario simulation" integration_tests: - name: Budget Creation Flow file: apps/backend/test/integration/budget-creation.spec.ts scenarios: - Crear concepto compuesto - Generar presupuesto desde prototipo - Agregar partidas al presupuesto - Calcular totales automáticamente - Aprobar presupuesto reused_from_gamilit: false - name: Cost Control Integration file: apps/backend/test/integration/cost-control.spec.ts scenarios: - Registrar costo desde orden de compra - Actualizar desviaciones automáticamente - Generar alerta si desviación >5% - Crear plan de acción reused_from_gamilit: false e2e_tests: - name: Budget E2E file: apps/frontend/test/e2e/budgets.e2e.spec.ts scenarios: - Usuario crea concepto compuesto - Usuario genera presupuesto de prototipo - Usuario compara versiones de presupuesto - Usuario exporta presupuesto a PDF reused_from_gamilit: false - name: Cost Control E2E file: apps/frontend/test/e2e/cost-control.e2e.spec.ts scenarios: - Usuario ve dashboard de control de costos - Usuario investiga desviación crítica - Usuario crea plan de acción - Usuario simula escenarios de rentabilidad reused_from_gamilit: false # ============================================================================ # MÉTRICAS # ============================================================================ metrics: story_points: planned: 46 completed: 0 by_sprint: sprint_7: 13 # US-COST-001, 002, 003 sprint_8: 13 # US-COST-004, 005 sprint_9: 10 # US-COST-006, 007 sprint_10: 10 # US-COST-008 variance: 0% budget: planned: 35000 actual: 0 variance: 0% reuse_from_gamilit: infrastructure: 0% database: 0% backend: 0% frontend: 0% overall: 0% note: "Módulo completamente nuevo, sin reutilización de GAMILIT" performance_targets: concept_search: "<200ms" composite_price_calculation: "<100ms" budget_generation_100_items: "<2s" mass_price_update_500_concepts: "<5s" dashboard_load: "<1.5s" curve_s_rendering: "<800ms" quality_targets: test_coverage: ">85%" budget_accuracy: "<3% deviation vs real" eac_projection_accuracy: "<2% error" alert_response_time: "<24h" # ============================================================================ # ROADMAP # ============================================================================ roadmap: sprint_7: weeks: "13-14" goal: "Catálogo de Conceptos y Precios Unitarios" story_points: 13 tasks: - Implementar schema budgets en DB - Crear tablas concept_catalog, price_history, regions - Desarrollar ConceptCatalogService (CRUD + cálculos) - Implementar búsqueda full-text - Desarrollar CreateConceptModal (frontend) - Implementar actualización masiva de precios - Tests unitarios del catálogo deliverables: - US-COST-001: Catálogo de Conceptos - US-COST-002: Precios Compuestos - US-COST-003: Actualización Masiva sprint_8: weeks: "15-16" goal: "Presupuestos Maestros (3 niveles)" story_points: 13 tasks: - Crear tablas budgets, budget_items, budget_versions - Desarrollar BudgetService con generadores - Implementar triggers de cálculo automático - Desarrollar BudgetWizard (frontend) - Implementar árbol jerárquico de partidas - Sistema de versionado - Tests de integración de presupuestos deliverables: - US-COST-004: Presupuesto de Obra - US-COST-005: Presupuesto de Prototipo sprint_9: weeks: "17-18" goal: "Control de Costos Reales" story_points: 10 tasks: - Crear tablas actual_costs, cost_variances, cost_projections - Desarrollar CostControlService - Implementar integración con Compras/Nómina/Subcontratos - Desarrollar CurveSChart (frontend) - Implementar análisis de desviaciones - Sistema de alertas automáticas - Cron job de análisis diario deliverables: - US-COST-006: Dashboard de Control - US-COST-007: Análisis de Desviaciones sprint_10: weeks: "19-20" goal: "Análisis de Rentabilidad" story_points: 10 tasks: - Crear tablas profitability_analysis, prototype_profitability - Desarrollar ProfitabilityService - Implementar cálculos ROI, TIR, punto de equilibrio - Desarrollar ScenarioSimulator (frontend) - Implementar matriz de sensibilidad - Comparación de proyectos - Tests E2E completos del módulo deliverables: - US-COST-008: Análisis de Rentabilidad # ============================================================================ # DEPENDENCIAS # ============================================================================ dependencies: modules_required: - id: MAI-001 name: Fundamentos reason: "Sistema de autenticación, roles, multi-tenancy" critical: true - id: MAI-002 name: Proyectos y Obras reason: "Estructura de proyectos, etapas, prototipos para presupuestos" critical: true modules_that_depend_on_this: - id: MAI-004 name: Compras e Inventarios reason: "Consume presupuesto para planificar compras, alimenta costos reales" impact: high - id: MAI-005 name: Control de Obra reason: "Consume presupuesto como baseline, registra avances" impact: high - id: MAI-007 name: Recursos Humanos reason: "Consume presupuesto de MO, alimenta costos de nómina" impact: medium - id: MAI-009 name: Reportes y Analytics reason: "Consume datos de costos y rentabilidad para reportes" impact: medium external_integrations: - name: OPUS type: import/export description: "Importar/exportar catálogo de conceptos" priority: medium - name: Neodata type: import/export description: "Importar/exportar presupuestos" priority: medium - name: Excel/CSV type: import/export description: "Importar catálogo masivo, exportar reportes" priority: high # ============================================================================ # COBERTURA # ============================================================================ cobertura: rf_total: 4 rf_implementados: 0 rf_en_progreso: 0 rf_pendientes: 4 et_total: 4 et_implementados: 0 us_total: 8 us_implementados: 0 tablas_total: 11 tablas_implementadas: 0 endpoints_total: 35 endpoints_implementados: 0 componentes_ui_total: 10 componentes_ui_implementados: 0 # ============================================================================ # NOTAS # ============================================================================ notes: - "Módulo completamente nuevo sin reutilización de GAMILIT" - "Core crítico del negocio: impacta directamente en rentabilidad" - "Integración estrecha con MAI-002 (Proyectos) y MAI-004 (Compras)" - "Performance crítica: catálogo puede crecer a 10,000+ conceptos" - "Indices full-text y paginación necesarios desde Sprint 7" - "Dashboard en tiempo real requiere optimización de queries" - "Triggers de cálculo automático deben ser eficientes" - "Curva S y gráficas requieren Chart.js en frontend" - "Simulador de escenarios debe ser interactivo (cálculos en vivo)" - "Plan de 4 sprints (8 semanas) es ajustado pero alcanzable" - "Priorizar funcionalidad core sobre features avanzadas si hay retrasos" - "Tests de performance necesarios en Sprint 7 (búsqueda) y Sprint 9 (dashboard)"