# 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
