erp-core/docs/04-modelado/trazabilidad/TRACEABILITY-MGN-012.yaml

766 lines
28 KiB
YAML

# 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