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

986 lines
40 KiB
YAML

# TRACEABILITY-MGN-008.yaml
# Matriz de Trazabilidad - MGN-008: Contabilidad Analítica
# Fecha: 2025-11-24
# Versión: 1.0
module:
id: MGN-008
name: "Contabilidad Analítica"
description: "Sistema de cuentas analíticas para seguimiento de costos e ingresos por proyectos, departamentos y centros de costo"
priority: P0
story_points: 35
status: Diseñado
metadata:
total_rf: 5
total_et_backend: 5
total_et_frontend: 5
total_tables: 6
total_tests: 100
coverage: 100%
requirements:
- rf_id: RF-MGN-008-001
rf_title: "Gestión de Cuentas Analíticas"
rf_file: "requerimientos-funcionales/mgn-008/RF-MGN-008-001-gestión-de-cuentas-analíticas.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-008/ET-BACKEND-MGN-008-001-gestión-de-cuentas-analíticas.md"
endpoints:
- method: POST
path: /api/v1/analytics/accounts
description: "Crear nueva cuenta analítica"
- method: GET
path: /api/v1/analytics/accounts
description: "Listar todas las cuentas analíticas"
- method: GET
path: /api/v1/analytics/accounts/:id
description: "Obtener cuenta analítica por ID"
- method: PUT
path: /api/v1/analytics/accounts/:id
description: "Actualizar cuenta analítica"
- method: DELETE
path: /api/v1/analytics/accounts/:id
description: "Eliminar cuenta analítica (soft delete)"
services:
- name: "AnalyticAccountService"
file: "src/modules/analytics/services/analytic-account.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- validateBusinessRules
controllers:
- name: "AnalyticAccountController"
file: "src/modules/analytics/controllers/analytic-account.controller.ts"
dtos:
- name: "CreateAnalyticAccountDto"
file: "src/modules/analytics/dto/create-analytic-account.dto.ts"
- name: "UpdateAnalyticAccountDto"
file: "src/modules/analytics/dto/update-analytic-account.dto.ts"
- name: "AnalyticAccountResponseDto"
file: "src/modules/analytics/dto/analytic-account-response.dto.ts"
- name: "FilterAnalyticAccountDto"
file: "src/modules/analytics/dto/filter-analytic-account.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-008/ET-FRONTEND-MGN-008-001-gestión-de-cuentas-analíticas.md"
routes:
- path: "/analytics/accounts"
component: "AnalyticAccountsPage"
- path: "/analytics/accounts/create"
component: "CreateAnalyticAccountPage"
- path: "/analytics/accounts/:id/edit"
component: "EditAnalyticAccountPage"
- path: "/analytics/accounts/:id"
component: "ViewAnalyticAccountPage"
components:
- name: "AnalyticAccountsTable"
file: "src/widgets/analytic-accounts-table/ui/AnalyticAccountsTable.tsx"
type: widget
- name: "CreateAnalyticAccountForm"
file: "src/features/create-analytic-account/ui/CreateAnalyticAccountForm.tsx"
type: feature
- name: "AnalyticAccountCard"
file: "src/entities/analytic-account/ui/AnalyticAccountCard.tsx"
type: entity
- name: "AnalyticAccountPage"
file: "src/pages/analytics/AnalyticAccountPage.tsx"
type: page
api_client:
- name: "analyticAccountApi"
file: "src/entities/analytic-account/api/analytic-account.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useAnalyticAccountStore"
file: "src/entities/analytic-account/model/analytic-account.store.ts"
type: zustand
- name: "useAnalyticAccounts"
file: "src/entities/analytic-account/api/analytic-account.queries.ts"
type: react-query
database_tables:
- schema: analytics
table: analytic_accounts
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_analytic_accounts_tenant_id
- idx_analytic_accounts_code
- idx_analytic_accounts_plan_id
rls_policy: tenant_isolation_analytic_accounts
- schema: analytics
table: analytic_plans
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
indices:
- idx_analytic_plans_tenant_id
rls_policy: tenant_isolation_analytic_plans
tests:
backend:
unit_tests:
- file: "src/modules/analytics/services/analytic-account.service.spec.ts"
test_cases:
- "should create analytic account with valid data"
- "should throw error when code already exists"
- "should support hierarchical accounts"
- "should find all accounts for tenant"
- "should update account successfully"
integration_tests:
- file: "test/analytics/analytic-account.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/analytics/accounts should create account"
- "GET /api/v1/analytics/accounts should return all accounts"
- "GET /api/v1/analytics/accounts/:id should return account"
- "PUT /api/v1/analytics/accounts/:id should update account"
- "DELETE /api/v1/analytics/accounts/:id should soft delete account"
- "should enforce tenant isolation"
- "should require authentication"
- "should check permissions"
frontend:
component_tests:
- file: "src/widgets/analytic-accounts-table/ui/AnalyticAccountsTable.test.tsx"
test_cases:
- "should render table with accounts"
- "should handle pagination"
- "should call delete on button click"
- file: "src/features/create-analytic-account/ui/CreateAnalyticAccountForm.test.tsx"
test_cases:
- "should validate required fields"
- "should submit valid form"
- "should show error messages"
e2e_tests:
- file: "e2e/analytics/analytic-accounts.spec.ts"
test_cases:
- "should create analytic account successfully"
- "should edit analytic account successfully"
- "should delete analytic account with confirmation"
- "should enforce permissions"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear cuentas analíticas con código único"
status: Pending
test_reference: "test/analytics/analytic-account.controller.e2e-spec.ts:32"
- id: AC-002
description: "Cuentas analíticas soportan estructura jerárquica"
status: Pending
test_reference: "src/modules/analytics/services/analytic-account.service.spec.ts:65"
- id: AC-003
description: "Cuentas pueden asociarse a diferentes planes analíticos"
status: Pending
test_reference: "test/analytics/analytic-account.controller.e2e-spec.ts:98"
business_rules:
- id: RN-001
description: "Código de cuenta analítica debe ser único por tenant"
implementation: "database-design/schemas/analytics-schema-ddl.sql:CONSTRAINT uq_analytic_accounts_code_tenant"
test_reference: "src/modules/analytics/services/analytic-account.service.spec.ts:88"
- id: RN-002
description: "Cuenta analítica debe estar asociada a un plan analítico"
implementation: "src/modules/analytics/services/analytic-account.service.ts:validatePlan()"
test_reference: "src/modules/analytics/services/analytic-account.service.spec.ts:112"
- id: RN-003
description: "Cuenta con movimientos no puede ser eliminada"
implementation: "src/modules/analytics/services/analytic-account.service.ts:remove()"
test_reference: "src/modules/analytics/services/analytic-account.service.spec.ts:138"
dependencies:
rf_dependencies: []
module_dependencies:
- MGN-001
external_dependencies:
- name: "@nestjs/common"
version: "^10.0.0"
- name: "ant-design"
version: "^5.0.0"
- rf_id: RF-MGN-008-002
rf_title: "Registro de Líneas Analíticas"
rf_file: "requerimientos-funcionales/mgn-008/RF-MGN-008-002-registro-de-líneas-analíticas.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-008/ET-BACKEND-MGN-008-002-registro-de-líneas-analíticas.md"
endpoints:
- method: POST
path: /api/v1/analytics/lines
description: "Crear nueva línea analítica"
- method: GET
path: /api/v1/analytics/lines
description: "Listar todas las líneas analíticas"
- method: GET
path: /api/v1/analytics/lines/:id
description: "Obtener línea analítica por ID"
- method: PUT
path: /api/v1/analytics/lines/:id
description: "Actualizar línea analítica"
- method: DELETE
path: /api/v1/analytics/lines/:id
description: "Eliminar línea analítica (soft delete)"
services:
- name: "AnalyticLineService"
file: "src/modules/analytics/services/analytic-line.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- validateBusinessRules
controllers:
- name: "AnalyticLineController"
file: "src/modules/analytics/controllers/analytic-line.controller.ts"
dtos:
- name: "CreateAnalyticLineDto"
file: "src/modules/analytics/dto/create-analytic-line.dto.ts"
- name: "UpdateAnalyticLineDto"
file: "src/modules/analytics/dto/update-analytic-line.dto.ts"
- name: "AnalyticLineResponseDto"
file: "src/modules/analytics/dto/analytic-line-response.dto.ts"
- name: "FilterAnalyticLineDto"
file: "src/modules/analytics/dto/filter-analytic-line.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-008/ET-FRONTEND-MGN-008-002-registro-de-líneas-analíticas.md"
routes:
- path: "/analytics/lines"
component: "AnalyticLinesPage"
- path: "/analytics/lines/create"
component: "CreateAnalyticLinePage"
- path: "/analytics/lines/:id/edit"
component: "EditAnalyticLinePage"
- path: "/analytics/lines/:id"
component: "ViewAnalyticLinePage"
components:
- name: "AnalyticLinesTable"
file: "src/widgets/analytic-lines-table/ui/AnalyticLinesTable.tsx"
type: widget
- name: "CreateAnalyticLineForm"
file: "src/features/create-analytic-line/ui/CreateAnalyticLineForm.tsx"
type: feature
- name: "AnalyticLineCard"
file: "src/entities/analytic-line/ui/AnalyticLineCard.tsx"
type: entity
- name: "AnalyticLinePage"
file: "src/pages/analytics/AnalyticLinePage.tsx"
type: page
api_client:
- name: "analyticLineApi"
file: "src/entities/analytic-line/api/analytic-line.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useAnalyticLineStore"
file: "src/entities/analytic-line/model/analytic-line.store.ts"
type: zustand
- name: "useAnalyticLines"
file: "src/entities/analytic-line/api/analytic-line.queries.ts"
type: react-query
database_tables:
- schema: analytics
table: analytic_lines
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_analytic_lines_tenant_id
- idx_analytic_lines_account_id
- idx_analytic_lines_date
- idx_analytic_lines_journal_entry_id
rls_policy: tenant_isolation_analytic_lines
- schema: financial
table: journal_entries
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
indices:
- idx_journal_entries_tenant_id
rls_policy: tenant_isolation_journal_entries
tests:
backend:
unit_tests:
- file: "src/modules/analytics/services/analytic-line.service.spec.ts"
test_cases:
- "should create analytic line with valid data"
- "should link to journal entry automatically"
- "should validate account existence"
- "should find all lines for tenant"
- "should update line successfully"
integration_tests:
- file: "test/analytics/analytic-line.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/analytics/lines should create line"
- "GET /api/v1/analytics/lines should return all lines"
- "GET /api/v1/analytics/lines/:id should return line"
- "PUT /api/v1/analytics/lines/:id should update line"
- "DELETE /api/v1/analytics/lines/:id should soft delete line"
- "should enforce tenant isolation"
- "should require authentication"
- "should check permissions"
frontend:
component_tests:
- file: "src/widgets/analytic-lines-table/ui/AnalyticLinesTable.test.tsx"
test_cases:
- "should render table with lines"
- "should handle pagination"
- "should filter by account"
- file: "src/features/create-analytic-line/ui/CreateAnalyticLineForm.test.tsx"
test_cases:
- "should validate required fields"
- "should submit valid form"
- "should show error messages"
e2e_tests:
- file: "e2e/analytics/analytic-lines.spec.ts"
test_cases:
- "should create analytic line successfully"
- "should edit analytic line successfully"
- "should delete analytic line with confirmation"
- "should enforce permissions"
acceptance_criteria:
- id: AC-001
description: "Usuario puede registrar líneas analíticas manualmente"
status: Pending
test_reference: "test/analytics/analytic-line.controller.e2e-spec.ts:35"
- id: AC-002
description: "Líneas analíticas se crean automáticamente desde asientos contables"
status: Pending
test_reference: "src/modules/analytics/services/analytic-line.service.spec.ts:72"
- id: AC-003
description: "Líneas soportan montos positivos (ingresos) y negativos (costos)"
status: Pending
test_reference: "test/analytics/analytic-line.controller.e2e-spec.ts:108"
business_rules:
- id: RN-001
description: "Línea analítica debe tener cuenta analítica válida"
implementation: "src/modules/analytics/services/analytic-line.service.ts:validateAccount()"
test_reference: "src/modules/analytics/services/analytic-line.service.spec.ts:95"
- id: RN-002
description: "Monto puede ser positivo (ingreso) o negativo (costo)"
implementation: "src/modules/analytics/services/analytic-line.service.ts:create()"
test_reference: "src/modules/analytics/services/analytic-line.service.spec.ts:122"
- id: RN-003
description: "Líneas vinculadas a journal_entry no pueden ser editadas"
implementation: "src/modules/analytics/services/analytic-line.service.ts:update()"
test_reference: "src/modules/analytics/services/analytic-line.service.spec.ts:148"
dependencies:
rf_dependencies:
- RF-MGN-008-001
- RF-MGN-004-003
module_dependencies:
- MGN-001
- MGN-004
external_dependencies:
- name: "@nestjs/common"
version: "^10.0.0"
- rf_id: RF-MGN-008-003
rf_title: "Distribución Analítica Multi-Cuenta"
rf_file: "requerimientos-funcionales/mgn-008/RF-MGN-008-003-distribución-analítica-multi-cuenta.md"
priority: P1
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-008/ET-BACKEND-MGN-008-003-distribución-analítica-multi-cuenta.md"
endpoints:
- method: POST
path: /api/v1/analytics/distributions
description: "Crear nueva distribución analítica"
- method: GET
path: /api/v1/analytics/distributions
description: "Listar todas las distribuciones"
- method: GET
path: /api/v1/analytics/distributions/:id
description: "Obtener distribución por ID"
- method: PUT
path: /api/v1/analytics/distributions/:id
description: "Actualizar distribución"
- method: DELETE
path: /api/v1/analytics/distributions/:id
description: "Eliminar distribución (soft delete)"
services:
- name: "AnalyticDistributionService"
file: "src/modules/analytics/services/analytic-distribution.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- validateBusinessRules
controllers:
- name: "AnalyticDistributionController"
file: "src/modules/analytics/controllers/analytic-distribution.controller.ts"
dtos:
- name: "CreateAnalyticDistributionDto"
file: "src/modules/analytics/dto/create-analytic-distribution.dto.ts"
- name: "UpdateAnalyticDistributionDto"
file: "src/modules/analytics/dto/update-analytic-distribution.dto.ts"
- name: "AnalyticDistributionResponseDto"
file: "src/modules/analytics/dto/analytic-distribution-response.dto.ts"
- name: "FilterAnalyticDistributionDto"
file: "src/modules/analytics/dto/filter-analytic-distribution.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-008/ET-FRONTEND-MGN-008-003-distribución-analítica-multi-cuenta.md"
routes:
- path: "/analytics/distributions"
component: "AnalyticDistributionsPage"
- path: "/analytics/distributions/create"
component: "CreateAnalyticDistributionPage"
- path: "/analytics/distributions/:id/edit"
component: "EditAnalyticDistributionPage"
- path: "/analytics/distributions/:id"
component: "ViewAnalyticDistributionPage"
components:
- name: "AnalyticDistributionsTable"
file: "src/widgets/analytic-distributions-table/ui/AnalyticDistributionsTable.tsx"
type: widget
- name: "CreateAnalyticDistributionForm"
file: "src/features/create-analytic-distribution/ui/CreateAnalyticDistributionForm.tsx"
type: feature
- name: "AnalyticDistributionCard"
file: "src/entities/analytic-distribution/ui/AnalyticDistributionCard.tsx"
type: entity
- name: "AnalyticDistributionPage"
file: "src/pages/analytics/AnalyticDistributionPage.tsx"
type: page
api_client:
- name: "analyticDistributionApi"
file: "src/entities/analytic-distribution/api/analytic-distribution.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useAnalyticDistributionStore"
file: "src/entities/analytic-distribution/model/analytic-distribution.store.ts"
type: zustand
- name: "useAnalyticDistributions"
file: "src/entities/analytic-distribution/api/analytic-distribution.queries.ts"
type: react-query
database_tables:
- schema: analytics
table: analytic_distributions
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_analytic_distributions_tenant_id
- idx_analytic_distributions_name
rls_policy: tenant_isolation_analytic_distributions
- schema: analytics
table: distribution_lines
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE
indices:
- idx_distribution_lines_distribution_id
- idx_distribution_lines_account_id
rls_policy: tenant_isolation_distribution_lines
tests:
backend:
unit_tests:
- file: "src/modules/analytics/services/analytic-distribution.service.spec.ts"
test_cases:
- "should create distribution with multiple accounts"
- "should validate percentages sum to 100%"
- "should apply distribution to journal entry"
- "should find all distributions for tenant"
- "should update distribution successfully"
integration_tests:
- file: "test/analytics/analytic-distribution.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/analytics/distributions should create distribution"
- "GET /api/v1/analytics/distributions should return all distributions"
- "GET /api/v1/analytics/distributions/:id should return distribution"
- "PUT /api/v1/analytics/distributions/:id should update distribution"
- "DELETE /api/v1/analytics/distributions/:id should soft delete distribution"
- "should enforce tenant isolation"
- "should require authentication"
- "should check permissions"
frontend:
component_tests:
- file: "src/widgets/analytic-distributions-table/ui/AnalyticDistributionsTable.test.tsx"
test_cases:
- "should render table with distributions"
- "should handle pagination"
- "should call delete on button click"
- file: "src/features/create-analytic-distribution/ui/CreateAnalyticDistributionForm.test.tsx"
test_cases:
- "should validate percentages sum to 100%"
- "should submit valid form"
- "should show error messages"
e2e_tests:
- file: "e2e/analytics/analytic-distributions.spec.ts"
test_cases:
- "should create distribution successfully"
- "should edit distribution successfully"
- "should delete distribution with confirmation"
- "should enforce permissions"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear distribuciones con múltiples cuentas"
status: Pending
test_reference: "test/analytics/analytic-distribution.controller.e2e-spec.ts:38"
- id: AC-002
description: "Suma de porcentajes debe ser exactamente 100%"
status: Pending
test_reference: "src/modules/analytics/services/analytic-distribution.service.spec.ts:75"
- id: AC-003
description: "Distribuciones se aplican automáticamente a asientos contables"
status: Pending
test_reference: "test/analytics/analytic-distribution.controller.e2e-spec.ts:112"
business_rules:
- id: RN-001
description: "Suma de porcentajes de distribución debe ser 100%"
implementation: "src/modules/analytics/services/analytic-distribution.service.ts:validatePercentages()"
test_reference: "src/modules/analytics/services/analytic-distribution.service.spec.ts:98"
- id: RN-002
description: "Distribución debe tener al menos 2 cuentas analíticas"
implementation: "src/modules/analytics/services/analytic-distribution.service.ts:validateAccounts()"
test_reference: "src/modules/analytics/services/analytic-distribution.service.spec.ts:125"
- id: RN-003
description: "Al aplicar distribución, se crean múltiples líneas analíticas"
implementation: "src/modules/analytics/services/analytic-distribution.service.ts:apply()"
test_reference: "src/modules/analytics/services/analytic-distribution.service.spec.ts:152"
dependencies:
rf_dependencies:
- RF-MGN-008-001
- RF-MGN-008-002
module_dependencies:
- MGN-001
- MGN-004
external_dependencies:
- name: "@nestjs/common"
version: "^10.0.0"
- rf_id: RF-MGN-008-004
rf_title: "Tags Analíticos"
rf_file: "requerimientos-funcionales/mgn-008/RF-MGN-008-004-tags-analíticos.md"
priority: P1
story_points: 3
et_backend:
file: "especificaciones-tecnicas/backend/mgn-008/ET-BACKEND-MGN-008-004-tags-analíticos.md"
endpoints:
- method: POST
path: /api/v1/analytics/tags
description: "Crear nuevo tag analítico"
- method: GET
path: /api/v1/analytics/tags
description: "Listar todos los tags"
- method: GET
path: /api/v1/analytics/tags/:id
description: "Obtener tag por ID"
- method: PUT
path: /api/v1/analytics/tags/:id
description: "Actualizar tag"
- method: DELETE
path: /api/v1/analytics/tags/:id
description: "Eliminar tag (soft delete)"
services:
- name: "AnalyticTagService"
file: "src/modules/analytics/services/analytic-tag.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- validateBusinessRules
controllers:
- name: "AnalyticTagController"
file: "src/modules/analytics/controllers/analytic-tag.controller.ts"
dtos:
- name: "CreateAnalyticTagDto"
file: "src/modules/analytics/dto/create-analytic-tag.dto.ts"
- name: "UpdateAnalyticTagDto"
file: "src/modules/analytics/dto/update-analytic-tag.dto.ts"
- name: "AnalyticTagResponseDto"
file: "src/modules/analytics/dto/analytic-tag-response.dto.ts"
- name: "FilterAnalyticTagDto"
file: "src/modules/analytics/dto/filter-analytic-tag.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-008/ET-FRONTEND-MGN-008-004-tags-analíticos.md"
routes:
- path: "/analytics/tags"
component: "AnalyticTagsPage"
- path: "/analytics/tags/create"
component: "CreateAnalyticTagPage"
- path: "/analytics/tags/:id/edit"
component: "EditAnalyticTagPage"
- path: "/analytics/tags/:id"
component: "ViewAnalyticTagPage"
components:
- name: "AnalyticTagsTable"
file: "src/widgets/analytic-tags-table/ui/AnalyticTagsTable.tsx"
type: widget
- name: "CreateAnalyticTagForm"
file: "src/features/create-analytic-tag/ui/CreateAnalyticTagForm.tsx"
type: feature
- name: "AnalyticTagCard"
file: "src/entities/analytic-tag/ui/AnalyticTagCard.tsx"
type: entity
- name: "AnalyticTagPage"
file: "src/pages/analytics/AnalyticTagPage.tsx"
type: page
api_client:
- name: "analyticTagApi"
file: "src/entities/analytic-tag/api/analytic-tag.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useAnalyticTagStore"
file: "src/entities/analytic-tag/model/analytic-tag.store.ts"
type: zustand
- name: "useAnalyticTags"
file: "src/entities/analytic-tag/api/analytic-tag.queries.ts"
type: react-query
database_tables:
- schema: analytics
table: analytic_tags
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_analytic_tags_tenant_id
- idx_analytic_tags_name
rls_policy: tenant_isolation_analytic_tags
- schema: analytics
table: analytic_line_tags
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
- INSERT
- DELETE
indices:
- idx_analytic_line_tags_line_id
- idx_analytic_line_tags_tag_id
rls_policy: tenant_isolation_analytic_line_tags
tests:
backend:
unit_tests:
- file: "src/modules/analytics/services/analytic-tag.service.spec.ts"
test_cases:
- "should create analytic tag with valid data"
- "should assign tags to analytic lines"
- "should find all tags for tenant"
- "should update tag successfully"
- "should delete tag if no lines associated"
integration_tests:
- file: "test/analytics/analytic-tag.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/analytics/tags should create tag"
- "GET /api/v1/analytics/tags should return all tags"
- "GET /api/v1/analytics/tags/:id should return tag"
- "PUT /api/v1/analytics/tags/:id should update tag"
- "DELETE /api/v1/analytics/tags/:id should soft delete tag"
- "should enforce tenant isolation"
- "should require authentication"
- "should check permissions"
frontend:
component_tests:
- file: "src/widgets/analytic-tags-table/ui/AnalyticTagsTable.test.tsx"
test_cases:
- "should render table with tags"
- "should handle pagination"
- "should call delete on button click"
- file: "src/features/create-analytic-tag/ui/CreateAnalyticTagForm.test.tsx"
test_cases:
- "should validate required fields"
- "should submit valid form"
- "should show error messages"
e2e_tests:
- file: "e2e/analytics/analytic-tags.spec.ts"
test_cases:
- "should create analytic tag successfully"
- "should edit analytic tag successfully"
- "should delete analytic tag with confirmation"
- "should enforce permissions"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear tags para clasificación adicional"
status: Pending
test_reference: "test/analytics/analytic-tag.controller.e2e-spec.ts:32"
- id: AC-002
description: "Tags se asignan a líneas analíticas (relación many-to-many)"
status: Pending
test_reference: "src/modules/analytics/services/analytic-tag.service.spec.ts:68"
- id: AC-003
description: "Reportes pueden filtrarse por tags"
status: Pending
test_reference: "test/analytics/analytic-tag.controller.e2e-spec.ts:95"
business_rules:
- id: RN-001
description: "Nombre de tag debe ser único por tenant"
implementation: "database-design/schemas/analytics-schema-ddl.sql:CONSTRAINT uq_analytic_tags_name_tenant"
test_reference: "src/modules/analytics/services/analytic-tag.service.spec.ts:88"
- id: RN-002
description: "Una línea analítica puede tener múltiples tags"
implementation: "database-design/schemas/analytics-schema-ddl.sql:analytic_line_tags table"
test_reference: "src/modules/analytics/services/analytic-tag.service.spec.ts:112"
- id: RN-003
description: "Tag con líneas asociadas no puede ser eliminado permanentemente"
implementation: "src/modules/analytics/services/analytic-tag.service.ts:remove()"
test_reference: "src/modules/analytics/services/analytic-tag.service.spec.ts:138"
dependencies:
rf_dependencies:
- RF-MGN-008-002
module_dependencies:
- MGN-001
external_dependencies:
- name: "@nestjs/common"
version: "^10.0.0"
- rf_id: RF-MGN-008-005
rf_title: "Reportes Analíticos (P&L por Proyecto)"
rf_file: "requerimientos-funcionales/mgn-008/RF-MGN-008-005-reportes-analíticos-p&l-por-proyecto.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-008/ET-BACKEND-MGN-008-005-reportes-analíticos-p&l-por-proyecto.md"
endpoints:
- method: GET
path: /api/v1/analytics/reports/pl
description: "Obtener reporte P&L por cuenta analítica"
- method: GET
path: /api/v1/analytics/reports/balance
description: "Obtener balance analítico"
- method: GET
path: /api/v1/analytics/reports/summary
description: "Resumen analítico por período"
- method: GET
path: /api/v1/analytics/reports/comparison
description: "Comparación de cuentas analíticas"
- method: GET
path: /api/v1/analytics/reports/trends
description: "Tendencias analíticas"
services:
- name: "AnalyticReportService"
file: "src/modules/analytics/services/analytic-report.service.ts"
methods:
- getProfitAndLoss
- getBalance
- getSummary
- getComparison
- getTrends
controllers:
- name: "AnalyticReportController"
file: "src/modules/analytics/controllers/analytic-report.controller.ts"
dtos:
- name: "AnalyticReportFilterDto"
file: "src/modules/analytics/dto/analytic-report-filter.dto.ts"
- name: "AnalyticReportResponseDto"
file: "src/modules/analytics/dto/analytic-report-response.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-008/ET-FRONTEND-MGN-008-005-reportes-analíticos-p&l-por-proyecto.md"
routes:
- path: "/analytics/reports"
component: "AnalyticReportsPage"
- path: "/analytics/reports/pl"
component: "AnalyticPLPage"
- path: "/analytics/reports/balance"
component: "AnalyticBalancePage"
components:
- name: "AnalyticReportDashboard"
file: "src/widgets/analytic-report-dashboard/ui/AnalyticReportDashboard.tsx"
type: widget
- name: "AnalyticChart"
file: "src/features/analytic-chart/ui/AnalyticChart.tsx"
type: feature
- name: "AnalyticReportFilters"
file: "src/entities/analytic-report/ui/AnalyticReportFilters.tsx"
type: entity
- name: "AnalyticReportsPage"
file: "src/pages/analytics/AnalyticReportsPage.tsx"
type: page
api_client:
- name: "analyticReportApi"
file: "src/entities/analytic-report/api/analytic-report.api.ts"
methods:
- getPL
- getBalance
- getSummary
- getComparison
- getTrends
state_management:
- name: "useAnalyticReportStore"
file: "src/entities/analytic-report/model/analytic-report.store.ts"
type: zustand
- name: "useAnalyticReports"
file: "src/entities/analytic-report/api/analytic-report.queries.ts"
type: react-query
database_tables:
- schema: analytics
table: analytic_lines
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
indices:
- idx_analytic_lines_date
- idx_analytic_lines_account_id
rls_policy: tenant_isolation_analytic_lines
- schema: analytics
table: analytic_accounts
file: "database-design/schemas/analytics-schema-ddl.sql"
operations:
- SELECT
indices:
- idx_analytic_accounts_tenant_id
rls_policy: tenant_isolation_analytic_accounts
tests:
backend:
unit_tests:
- file: "src/modules/analytics/services/analytic-report.service.spec.ts"
test_cases:
- "should generate P&L report by account"
- "should calculate income, expenses, and profit"
- "should generate balance report"
- "should compare multiple accounts"
- "should calculate trends over time"
integration_tests:
- file: "test/analytics/analytic-report.controller.e2e-spec.ts"
test_cases:
- "GET /api/v1/analytics/reports/pl should return P&L report"
- "GET /api/v1/analytics/reports/balance should return balance"
- "GET /api/v1/analytics/reports/summary should return summary"
- "GET /api/v1/analytics/reports/comparison should compare accounts"
- "GET /api/v1/analytics/reports/trends should return trends"
- "should enforce tenant isolation"
- "should require authentication"
- "should check permissions"
frontend:
component_tests:
- file: "src/widgets/analytic-report-dashboard/ui/AnalyticReportDashboard.test.tsx"
test_cases:
- "should render dashboard with charts"
- "should apply filters"
- "should export report"
- file: "src/features/analytic-chart/ui/AnalyticChart.test.tsx"
test_cases:
- "should render chart with data"
- "should change chart type"
- "should handle empty data"
e2e_tests:
- file: "e2e/analytics/analytic-reports.spec.ts"
test_cases:
- "should display P&L report"
- "should filter by date range"
- "should export to PDF/Excel"
- "should enforce permissions"
acceptance_criteria:
- id: AC-001
description: "Usuario puede generar P&L por cuenta analítica"
status: Pending
test_reference: "test/analytics/analytic-report.controller.e2e-spec.ts:42"
- id: AC-002
description: "Reporte muestra ingresos, costos y margen neto"
status: Pending
test_reference: "src/modules/analytics/services/analytic-report.service.spec.ts:78"
- id: AC-003
description: "Reportes soportan filtros por fecha, tags y cuentas"
status: Pending
test_reference: "test/analytics/analytic-report.controller.e2e-spec.ts:115"
business_rules:
- id: RN-001
description: "P&L suma líneas positivas como ingresos, negativas como costos"
implementation: "src/modules/analytics/services/analytic-report.service.ts:calculatePL()"
test_reference: "src/modules/analytics/services/analytic-report.service.spec.ts:98"
- id: RN-002
description: "Margen = Ingresos - Costos, expresado también en porcentaje"
implementation: "src/modules/analytics/services/analytic-report.service.ts:calculateMargin()"
test_reference: "src/modules/analytics/services/analytic-report.service.spec.ts:125"
- id: RN-003
description: "Reportes solo incluyen líneas de cuentas activas"
implementation: "src/modules/analytics/services/analytic-report.service.ts:filterActiveAccounts()"
test_reference: "src/modules/analytics/services/analytic-report.service.spec.ts:152"
dependencies:
rf_dependencies:
- RF-MGN-008-001
- RF-MGN-008-002
module_dependencies:
- MGN-001
- MGN-012
external_dependencies:
- name: "chart.js"
version: "^4.0.0"
- name: "exceljs"
version: "^4.3.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: 25
total_components: 20
total_tables: 6
total_test_cases: 100
estimated_duration_sprints: 2