# TRACEABILITY-MGN-012.yaml # Matriz de Trazabilidad - MGN-012: Reportes y Analytics # Fecha: 2025-11-24 # Versión: 1.0 module: id: MGN-012 name: "Reportes y Analytics" description: "Sistema de dashboards configurables, query builder, reportes personalizados, exportación y visualizaciones" priority: P1 story_points: 39 status: Diseñado metadata: total_rf: 4 total_et_backend: 4 total_et_frontend: 4 total_tables: 5 total_tests: 80 coverage: 100% requirements: - rf_id: RF-MGN-012-001 rf_title: "Dashboards Configurables" rf_file: "requerimientos-funcionales/mgn-012/RF-MGN-012-001-dashboards-configurables.md" priority: P1 story_points: 13 et_backend: file: "especificaciones-tecnicas/backend/mgn-012/ET-BACKEND-MGN-012-001-dashboards-configurables.md" endpoints: - method: POST path: /api/v1/reports/dashboards description: "Crear dashboard" - method: GET path: /api/v1/reports/dashboards description: "Listar dashboards" - method: GET path: /api/v1/reports/dashboards/:id description: "Obtener dashboard por ID" - method: PUT path: /api/v1/reports/dashboards/:id description: "Actualizar dashboard" - method: DELETE path: /api/v1/reports/dashboards/:id description: "Eliminar dashboard" services: - name: "DashboardService" file: "src/modules/reports/services/dashboard.service.ts" methods: - create - findAll - findOne - update - remove - validateBusinessRules controllers: - name: "DashboardController" file: "src/modules/reports/controllers/dashboard.controller.ts" dtos: - name: "CreateDashboardDto" file: "src/modules/reports/dto/create-dashboard.dto.ts" - name: "UpdateDashboardDto" file: "src/modules/reports/dto/update-dashboard.dto.ts" - name: "DashboardResponseDto" file: "src/modules/reports/dto/dashboard-response.dto.ts" - name: "FilterDashboardDto" file: "src/modules/reports/dto/filter-dashboard.dto.ts" et_frontend: file: "especificaciones-tecnicas/frontend/mgn-012/ET-FRONTEND-MGN-012-001-dashboards-configurables.md" routes: - path: "/dashboards" component: "DashboardsPage" - path: "/dashboards/create" component: "CreateDashboardPage" - path: "/dashboards/:id" component: "ViewDashboardPage" - path: "/dashboards/:id/edit" component: "EditDashboardPage" components: - name: "DashboardGrid" file: "src/widgets/dashboard-grid/ui/DashboardGrid.tsx" type: widget - name: "WidgetBuilder" file: "src/features/widget-builder/ui/WidgetBuilder.tsx" type: feature - name: "DashboardCard" file: "src/entities/dashboard/ui/DashboardCard.tsx" type: entity - name: "DashboardPage" file: "src/pages/reports/DashboardPage.tsx" type: page api_client: - name: "dashboardApi" file: "src/entities/dashboard/api/dashboard.api.ts" methods: - getAll - getById - create - update - delete state_management: - name: "useDashboardStore" file: "src/entities/dashboard/model/dashboard.store.ts" type: zustand - name: "useDashboards" file: "src/entities/dashboard/api/dashboard.queries.ts" type: react-query database_tables: - schema: system table: dashboards file: "database-design/schemas/system-schema-ddl.sql" operations: - SELECT - INSERT - UPDATE - DELETE (soft) indices: - idx_dashboards_tenant_id - idx_dashboards_user_id rls_policy: tenant_isolation_dashboards - schema: system table: widgets file: "database-design/schemas/system-schema-ddl.sql" operations: - SELECT - INSERT - UPDATE - DELETE indices: - idx_widgets_dashboard_id rls_policy: tenant_isolation_widgets tests: backend: unit_tests: - file: "src/modules/reports/services/dashboard.service.spec.ts" test_cases: - "should create dashboard with widgets" - "should validate widget configuration" - "should clone dashboard" - "should find all dashboards for user" - "should update dashboard successfully" integration_tests: - file: "test/reports/dashboard.controller.e2e-spec.ts" test_cases: - "POST /api/v1/reports/dashboards should create dashboard" - "GET /api/v1/reports/dashboards should return dashboards" - "GET /api/v1/reports/dashboards/:id should return dashboard" - "PUT /api/v1/reports/dashboards/:id should update dashboard" - "DELETE /api/v1/reports/dashboards/:id should delete dashboard" - "should enforce tenant isolation" - "should require authentication" - "should check permissions" frontend: component_tests: - file: "src/widgets/dashboard-grid/ui/DashboardGrid.test.tsx" test_cases: - "should render dashboard grid" - "should drag and drop widgets" - "should resize widgets" - file: "src/features/widget-builder/ui/WidgetBuilder.test.tsx" test_cases: - "should create widget" - "should configure widget data source" - "should preview widget" e2e_tests: - file: "e2e/reports/dashboards.spec.ts" test_cases: - "should create dashboard successfully" - "should add widgets to dashboard" - "should rearrange widgets" - "should enforce permissions" acceptance_criteria: - id: AC-001 description: "Usuario puede crear dashboards personalizados" status: Pending test_reference: "test/reports/dashboard.controller.e2e-spec.ts:35" - id: AC-002 description: "Widgets se pueden arrastrar y redimensionar" status: Pending test_reference: "src/widgets/dashboard-grid/ui/DashboardGrid.test.tsx:72" - id: AC-003 description: "Dashboards soportan diferentes tipos de widgets (KPI, charts, tables)" status: Pending test_reference: "e2e/reports/dashboards.spec.ts:108" business_rules: - id: RN-001 description: "Dashboard puede ser privado o compartido" implementation: "database-design/schemas/system-schema-ddl.sql:dashboards.is_shared" test_reference: "src/modules/reports/services/dashboard.service.spec.ts:95" - id: RN-002 description: "Cada widget debe tener configuración válida de data source" implementation: "src/modules/reports/services/dashboard.service.ts:validateWidget()" test_reference: "src/modules/reports/services/dashboard.service.spec.ts:122" - id: RN-003 description: "Dashboard con widgets no puede ser eliminado (solo soft delete)" implementation: "src/modules/reports/services/dashboard.service.ts:remove()" test_reference: "src/modules/reports/services/dashboard.service.spec.ts:148" dependencies: rf_dependencies: [] module_dependencies: - MGN-001 external_dependencies: - name: "react-grid-layout" version: "^1.4.0" - name: "chart.js" version: "^4.0.0" - rf_id: RF-MGN-012-002 rf_title: "Query Builder y Reportes Personalizados" rf_file: "requerimientos-funcionales/mgn-012/RF-MGN-012-002-query-builder-y-reportes-personalizados.md" priority: P2 story_points: 13 et_backend: file: "especificaciones-tecnicas/backend/mgn-012/ET-BACKEND-MGN-012-002-query-builder-y-reportes-personalizados.md" endpoints: - method: POST path: /api/v1/reports/custom description: "Crear reporte personalizado" - method: GET path: /api/v1/reports/custom description: "Listar reportes personalizados" - method: GET path: /api/v1/reports/custom/:id description: "Obtener reporte por ID" - method: POST path: /api/v1/reports/custom/:id/execute description: "Ejecutar reporte" - method: DELETE path: /api/v1/reports/custom/:id description: "Eliminar reporte" services: - name: "CustomReportService" file: "src/modules/reports/services/custom-report.service.ts" methods: - create - findAll - findOne - execute - remove - validateBusinessRules controllers: - name: "CustomReportController" file: "src/modules/reports/controllers/custom-report.controller.ts" dtos: - name: "CreateCustomReportDto" file: "src/modules/reports/dto/create-custom-report.dto.ts" - name: "ExecuteReportDto" file: "src/modules/reports/dto/execute-report.dto.ts" - name: "CustomReportResponseDto" file: "src/modules/reports/dto/custom-report-response.dto.ts" - name: "ReportResultDto" file: "src/modules/reports/dto/report-result.dto.ts" et_frontend: file: "especificaciones-tecnicas/frontend/mgn-012/ET-FRONTEND-MGN-012-002-query-builder-y-reportes-personalizados.md" routes: - path: "/reports/custom" component: "CustomReportsPage" - path: "/reports/custom/create" component: "CreateCustomReportPage" - path: "/reports/custom/:id" component: "ViewCustomReportPage" components: - name: "QueryBuilder" file: "src/widgets/query-builder/ui/QueryBuilder.tsx" type: widget - name: "ReportDesigner" file: "src/features/report-designer/ui/ReportDesigner.tsx" type: feature - name: "ReportResults" file: "src/entities/report/ui/ReportResults.tsx" type: entity - name: "CustomReportPage" file: "src/pages/reports/CustomReportPage.tsx" type: page api_client: - name: "customReportApi" file: "src/entities/custom-report/api/custom-report.api.ts" methods: - getAll - getById - create - execute - delete state_management: - name: "useCustomReportStore" file: "src/entities/custom-report/model/custom-report.store.ts" type: zustand - name: "useCustomReports" file: "src/entities/custom-report/api/custom-report.queries.ts" type: react-query database_tables: - schema: system table: reports file: "database-design/schemas/system-schema-ddl.sql" operations: - SELECT - INSERT - UPDATE - DELETE (soft) indices: - idx_reports_tenant_id - idx_reports_user_id rls_policy: tenant_isolation_reports tests: backend: unit_tests: - file: "src/modules/reports/services/custom-report.service.spec.ts" test_cases: - "should create custom report" - "should validate SQL query" - "should execute report with parameters" - "should prevent SQL injection" - "should cache report results" integration_tests: - file: "test/reports/custom-report.controller.e2e-spec.ts" test_cases: - "POST /api/v1/reports/custom should create report" - "GET /api/v1/reports/custom should return reports" - "GET /api/v1/reports/custom/:id should return report" - "POST /api/v1/reports/custom/:id/execute should execute" - "DELETE /api/v1/reports/custom/:id should delete report" - "should enforce tenant isolation" - "should require authentication" - "should check permissions" frontend: component_tests: - file: "src/widgets/query-builder/ui/QueryBuilder.test.tsx" test_cases: - "should build query visually" - "should add filters" - "should select columns" - file: "src/features/report-designer/ui/ReportDesigner.test.tsx" test_cases: - "should design report layout" - "should preview report" - "should save report definition" e2e_tests: - file: "e2e/reports/custom-reports.spec.ts" test_cases: - "should create custom report" - "should execute report with parameters" - "should view results in table" - "should enforce permissions" acceptance_criteria: - id: AC-001 description: "Usuario puede crear reportes usando query builder visual" status: Pending test_reference: "test/reports/custom-report.controller.e2e-spec.ts:38" - id: AC-002 description: "Reportes soportan parámetros dinámicos" status: Pending test_reference: "src/modules/reports/services/custom-report.service.spec.ts:75" - id: AC-003 description: "Sistema valida queries y previene SQL injection" status: Pending test_reference: "e2e/reports/custom-reports.spec.ts:112" business_rules: - id: RN-001 description: "Queries deben validarse antes de ejecutar" implementation: "src/modules/reports/services/custom-report.service.ts:validateQuery()" test_reference: "src/modules/reports/services/custom-report.service.spec.ts:98" - id: RN-002 description: "Resultados se cachean por 5 minutos" implementation: "src/modules/reports/services/custom-report.service.ts:execute()" test_reference: "src/modules/reports/services/custom-report.service.spec.ts:125" - id: RN-003 description: "Queries solo pueden acceder a schemas permitidos" implementation: "src/modules/reports/services/custom-report.service.ts:validateAccess()" test_reference: "src/modules/reports/services/custom-report.service.spec.ts:152" dependencies: rf_dependencies: [] module_dependencies: - MGN-001 external_dependencies: - name: "sql-parser" version: "^3.0.0" - name: "redis" version: "^4.6.0" - rf_id: RF-MGN-012-003 rf_title: "Exportación de Datos (PDF, Excel, CSV)" rf_file: "requerimientos-funcionales/mgn-012/RF-MGN-012-003-exportación-de-datos-pdf,-excel,-csv.md" priority: P1 story_points: 5 et_backend: file: "especificaciones-tecnicas/backend/mgn-012/ET-BACKEND-MGN-012-003-exportación-de-datos-pdf,-excel,-csv.md" endpoints: - method: POST path: /api/v1/reports/export/pdf description: "Exportar a PDF" - method: POST path: /api/v1/reports/export/excel description: "Exportar a Excel" - method: POST path: /api/v1/reports/export/csv description: "Exportar a CSV" - method: GET path: /api/v1/reports/exports/:id description: "Descargar archivo exportado" - method: GET path: /api/v1/reports/exports description: "Listar exportaciones" services: - name: "ExportService" file: "src/modules/reports/services/export.service.ts" methods: - exportPdf - exportExcel - exportCsv - getExport - findAll - validateBusinessRules controllers: - name: "ExportController" file: "src/modules/reports/controllers/export.controller.ts" dtos: - name: "ExportPdfDto" file: "src/modules/reports/dto/export-pdf.dto.ts" - name: "ExportExcelDto" file: "src/modules/reports/dto/export-excel.dto.ts" - name: "ExportCsvDto" file: "src/modules/reports/dto/export-csv.dto.ts" - name: "ExportResponseDto" file: "src/modules/reports/dto/export-response.dto.ts" et_frontend: file: "especificaciones-tecnicas/frontend/mgn-012/ET-FRONTEND-MGN-012-003-exportación-de-datos-pdf,-excel,-csv.md" routes: - path: "/reports/exports" component: "ExportsPage" components: - name: "ExportButtons" file: "src/widgets/export-buttons/ui/ExportButtons.tsx" type: widget - name: "ExportDialog" file: "src/features/export-dialog/ui/ExportDialog.tsx" type: feature - name: "ExportHistory" file: "src/entities/export/ui/ExportHistory.tsx" type: entity - name: "ExportsPage" file: "src/pages/reports/ExportsPage.tsx" type: page api_client: - name: "exportApi" file: "src/entities/export/api/export.api.ts" methods: - exportPdf - exportExcel - exportCsv - getExport - getAll state_management: - name: "useExportStore" file: "src/entities/export/model/export.store.ts" type: zustand - name: "useExports" file: "src/entities/export/api/export.queries.ts" type: react-query database_tables: - schema: system table: exports file: "database-design/schemas/system-schema-ddl.sql" operations: - SELECT - INSERT - UPDATE indices: - idx_exports_tenant_id - idx_exports_user_id - idx_exports_created_at rls_policy: tenant_isolation_exports tests: backend: unit_tests: - file: "src/modules/reports/services/export.service.spec.ts" test_cases: - "should export data to PDF" - "should export data to Excel" - "should export data to CSV" - "should cleanup old exports" - "should validate file size limits" integration_tests: - file: "test/reports/export.controller.e2e-spec.ts" test_cases: - "POST /api/v1/reports/export/pdf should export PDF" - "POST /api/v1/reports/export/excel should export Excel" - "POST /api/v1/reports/export/csv should export CSV" - "GET /api/v1/reports/exports/:id should download file" - "GET /api/v1/reports/exports should return exports" - "should enforce tenant isolation" - "should require authentication" - "should check permissions" frontend: component_tests: - file: "src/widgets/export-buttons/ui/ExportButtons.test.tsx" test_cases: - "should show export options" - "should trigger export" - "should show progress" - file: "src/features/export-dialog/ui/ExportDialog.test.tsx" test_cases: - "should select format" - "should configure options" - "should start export" e2e_tests: - file: "e2e/reports/exports.spec.ts" test_cases: - "should export to PDF successfully" - "should export to Excel successfully" - "should download exported file" - "should enforce permissions" acceptance_criteria: - id: AC-001 description: "Usuario puede exportar reportes a PDF, Excel y CSV" status: Pending test_reference: "test/reports/export.controller.e2e-spec.ts:45" - id: AC-002 description: "Exportaciones se procesan en background" status: Pending test_reference: "src/modules/reports/services/export.service.spec.ts:82" - id: AC-003 description: "Archivos exportados se limpian después de 7 días" status: Pending test_reference: "e2e/reports/exports.spec.ts:118" business_rules: - id: RN-001 description: "Exportaciones grandes se procesan en background" implementation: "src/modules/reports/services/export.service.ts:export()" test_reference: "src/modules/reports/services/export.service.spec.ts:105" - id: RN-002 description: "Tamaño máximo de exportación: 10,000 registros" implementation: "src/modules/reports/services/export.service.ts:validateSize()" test_reference: "src/modules/reports/services/export.service.spec.ts:132" - id: RN-003 description: "Archivos se eliminan automáticamente después de 7 días" implementation: "src/modules/reports/services/export.service.ts:cleanupOldExports()" test_reference: "src/modules/reports/services/export.service.spec.ts:158" dependencies: rf_dependencies: [] module_dependencies: - MGN-001 external_dependencies: - name: "puppeteer" version: "^21.0.0" - name: "exceljs" version: "^4.3.0" - name: "csv-stringify" version: "^6.4.0" - rf_id: RF-MGN-012-004 rf_title: "Gráficos y Visualizaciones" rf_file: "requerimientos-funcionales/mgn-012/RF-MGN-012-004-gráficos-y-visualizaciones.md" priority: P1 story_points: 8 et_backend: file: "especificaciones-tecnicas/backend/mgn-012/ET-BACKEND-MGN-012-004-gráficos-y-visualizaciones.md" endpoints: - method: POST path: /api/v1/reports/charts description: "Crear configuración de gráfico" - method: GET path: /api/v1/reports/charts description: "Listar gráficos" - method: GET path: /api/v1/reports/charts/:id description: "Obtener gráfico por ID" - method: POST path: /api/v1/reports/charts/:id/data description: "Obtener datos del gráfico" - method: DELETE path: /api/v1/reports/charts/:id description: "Eliminar gráfico" services: - name: "ChartService" file: "src/modules/reports/services/chart.service.ts" methods: - create - findAll - findOne - getData - remove - validateBusinessRules controllers: - name: "ChartController" file: "src/modules/reports/controllers/chart.controller.ts" dtos: - name: "CreateChartDto" file: "src/modules/reports/dto/create-chart.dto.ts" - name: "ChartDataDto" file: "src/modules/reports/dto/chart-data.dto.ts" - name: "ChartResponseDto" file: "src/modules/reports/dto/chart-response.dto.ts" - name: "FilterChartDto" file: "src/modules/reports/dto/filter-chart.dto.ts" et_frontend: file: "especificaciones-tecnicas/frontend/mgn-012/ET-FRONTEND-MGN-012-004-gráficos-y-visualizaciones.md" routes: - path: "/reports/charts" component: "ChartsPage" - path: "/reports/charts/create" component: "CreateChartPage" - path: "/reports/charts/:id" component: "ViewChartPage" components: - name: "ChartWidget" file: "src/widgets/chart-widget/ui/ChartWidget.tsx" type: widget - name: "ChartBuilder" file: "src/features/chart-builder/ui/ChartBuilder.tsx" type: feature - name: "ChartCard" file: "src/entities/chart/ui/ChartCard.tsx" type: entity - name: "ChartPage" file: "src/pages/reports/ChartPage.tsx" type: page api_client: - name: "chartApi" file: "src/entities/chart/api/chart.api.ts" methods: - getAll - getById - create - getData - delete state_management: - name: "useChartStore" file: "src/entities/chart/model/chart.store.ts" type: zustand - name: "useCharts" file: "src/entities/chart/api/chart.queries.ts" type: react-query database_tables: - schema: system table: saved_filters file: "database-design/schemas/system-schema-ddl.sql" operations: - SELECT - INSERT - UPDATE - DELETE indices: - idx_saved_filters_tenant_id - idx_saved_filters_user_id rls_policy: tenant_isolation_saved_filters tests: backend: unit_tests: - file: "src/modules/reports/services/chart.service.spec.ts" test_cases: - "should create chart configuration" - "should fetch chart data" - "should aggregate data for charts" - "should support multiple chart types" - "should cache chart results" integration_tests: - file: "test/reports/chart.controller.e2e-spec.ts" test_cases: - "POST /api/v1/reports/charts should create chart" - "GET /api/v1/reports/charts should return charts" - "GET /api/v1/reports/charts/:id should return chart" - "POST /api/v1/reports/charts/:id/data should return data" - "DELETE /api/v1/reports/charts/:id should delete chart" - "should enforce tenant isolation" - "should require authentication" - "should check permissions" frontend: component_tests: - file: "src/widgets/chart-widget/ui/ChartWidget.test.tsx" test_cases: - "should render chart" - "should change chart type" - "should apply filters" - file: "src/features/chart-builder/ui/ChartBuilder.test.tsx" test_cases: - "should configure chart" - "should preview chart" - "should save chart configuration" e2e_tests: - file: "e2e/reports/charts.spec.ts" test_cases: - "should create chart successfully" - "should view chart with data" - "should change chart type" - "should enforce permissions" acceptance_criteria: - id: AC-001 description: "Usuario puede crear gráficos de múltiples tipos (bar, line, pie, etc)" status: Pending test_reference: "test/reports/chart.controller.e2e-spec.ts:48" - id: AC-002 description: "Gráficos soportan drill-down interactivo" status: Pending test_reference: "src/widgets/chart-widget/ui/ChartWidget.test.tsx:85" - id: AC-003 description: "Datos de gráficos se actualizan en tiempo real" status: Pending test_reference: "e2e/reports/charts.spec.ts:122" business_rules: - id: RN-001 description: "Gráficos soportan tipos: bar, line, pie, area, scatter" implementation: "src/modules/reports/services/chart.service.ts:getChartData()" test_reference: "src/modules/reports/services/chart.service.spec.ts:108" - id: RN-002 description: "Datos se agregan según dimensiones y medidas configuradas" implementation: "src/modules/reports/services/chart.service.ts:aggregateData()" test_reference: "src/modules/reports/services/chart.service.spec.ts:135" - id: RN-003 description: "Resultados se cachean por 2 minutos" implementation: "src/modules/reports/services/chart.service.ts:getData()" test_reference: "src/modules/reports/services/chart.service.spec.ts:162" dependencies: rf_dependencies: [] module_dependencies: - MGN-001 external_dependencies: - name: "chart.js" version: "^4.0.0" - name: "recharts" version: "^2.8.0" - name: "d3" version: "^7.8.0" coverage: rf_to_et_backend: 100% rf_to_et_frontend: 100% rf_to_database: 100% rf_to_tests: 100% backend_tests: 100% frontend_tests: 100% statistics: total_endpoints: 20 total_components: 16 total_tables: 5 total_test_cases: 80 estimated_duration_sprints: 2