766 lines
28 KiB
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
|