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

1461 lines
57 KiB
YAML

# TRACEABILITY-MGN-004.yaml
# Matriz de Trazabilidad - MGN-004: Financiero Básico
# Fecha: 2025-11-24
# Versión: 1.0
module:
id: MGN-004
name: "Financiero Básico"
description: "Plan de cuentas, journals, asientos contables, impuestos, facturas y pagos"
priority: P0
story_points: 81
status: Diseñado
metadata:
total_rf: 8
total_et_backend: 8
total_et_frontend: 8
total_tables: 12
total_tests: 160
coverage: 100%
requirements:
- rf_id: RF-MGN-004-001
rf_title: "Gestión de Plan de Cuentas"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-001-gestión-de-plan-de-cuentas.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-001-gestión-de-plan-de-cuentas.md"
endpoints:
- method: POST
path: /api/v1/financial/accounts
description: "Crear cuenta contable"
- method: GET
path: /api/v1/financial/accounts
description: "Listar cuentas contables"
- method: GET
path: /api/v1/financial/accounts/:id
description: "Obtener cuenta por ID"
- method: PUT
path: /api/v1/financial/accounts/:id
description: "Actualizar cuenta"
- method: DELETE
path: /api/v1/financial/accounts/:id
description: "Desactivar cuenta"
services:
- name: "AccountService"
file: "src/modules/financial/services/account.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
controllers:
- name: "AccountController"
file: "src/modules/financial/controllers/account.controller.ts"
dtos:
- name: "CreateAccountDto"
file: "src/modules/financial/dto/create-account.dto.ts"
- name: "UpdateAccountDto"
file: "src/modules/financial/dto/update-account.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-001-gestión-de-plan-de-cuentas.md"
routes:
- path: "/financial/accounts"
component: "AccountsPage"
- path: "/financial/accounts/create"
component: "CreateAccountPage"
- path: "/financial/accounts/:id/edit"
component: "EditAccountPage"
- path: "/financial/accounts/:id"
component: "ViewAccountPage"
components:
- name: "AccountsTable"
file: "src/widgets/accounts-table/ui/AccountsTable.tsx"
type: widget
- name: "CreateAccountForm"
file: "src/features/create-account/ui/CreateAccountForm.tsx"
type: feature
- name: "AccountCard"
file: "src/entities/account/ui/AccountCard.tsx"
type: entity
- name: "AccountTree"
file: "src/widgets/account-tree/ui/AccountTree.tsx"
type: widget
api_client:
- name: "accountApi"
file: "src/entities/account/api/account.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useAccountStore"
file: "src/entities/account/model/account.store.ts"
type: zustand
database_tables:
- schema: financial
table: accounts
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_accounts_company_id
- idx_accounts_code
- idx_accounts_parent_id
- idx_accounts_type
rls_policy: company_isolation_accounts
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/account.service.spec.ts"
test_cases:
- "should create account with valid data"
- "should create hierarchical accounts"
- "should validate account code uniqueness"
- "should throw error when parent not found"
- "should update account successfully"
- "should soft delete account"
integration_tests:
- file: "test/financial/account.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/financial/accounts should create account"
- "GET /api/v1/financial/accounts should return all accounts"
- "GET /api/v1/financial/accounts/:id should return account"
- "PUT /api/v1/financial/accounts/:id should update account"
- "DELETE /api/v1/financial/accounts/:id should soft delete account"
- "should enforce company isolation"
- "should require authentication"
- "should check accounting permissions"
frontend:
component_tests:
- file: "src/widgets/accounts-table/ui/AccountsTable.test.tsx"
test_cases:
- "should render table with accounts"
- "should handle pagination"
- "should filter by type"
- file: "src/features/create-account/ui/CreateAccountForm.test.tsx"
test_cases:
- "should validate required fields"
- "should validate account code format"
- "should submit valid form"
e2e_tests:
- file: "e2e/financial/accounts.spec.ts"
test_cases:
- "should create account successfully"
- "should create child account"
- "should edit account successfully"
- "should delete account with confirmation"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear plan de cuentas jerárquico"
status: Pending
test_reference: "test/financial/account.controller.e2e-spec.ts:28"
- id: AC-002
description: "Cuentas tienen tipos: asset, liability, equity, income, expense"
status: Pending
test_reference: "src/modules/financial/services/account.service.spec.ts:65"
- id: AC-003
description: "Código de cuenta es único por empresa"
status: Pending
test_reference: "test/financial/account.controller.e2e-spec.ts:95"
business_rules:
- id: RN-001
description: "Código de cuenta único por empresa"
implementation: "database-design/schemas/financial-schema-ddl.sql:CONSTRAINT uq_accounts_code_company"
test_reference: "src/modules/financial/services/account.service.spec.ts:48"
- id: RN-002
description: "Cuentas soportan jerarquía con parent_id"
implementation: "database-design/schemas/financial-schema-ddl.sql:accounts.parent_id"
test_reference: "src/modules/financial/services/account.service.spec.ts:78"
- id: RN-003
description: "No se puede eliminar cuenta con movimientos"
implementation: "src/modules/financial/services/account.service.ts:remove()"
test_reference: "src/modules/financial/services/account.service.spec.ts:108"
dependencies:
rf_dependencies:
- RF-MGN-002-001
module_dependencies:
- MGN-002
external_dependencies: []
- rf_id: RF-MGN-004-002
rf_title: "Gestión de Journals Contables"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-002-gestión-de-journals-contables.md"
priority: P0
story_points: 5
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-002-gestión-de-journals-contables.md"
endpoints:
- method: POST
path: /api/v1/financial/journals
description: "Crear journal"
- method: GET
path: /api/v1/financial/journals
description: "Listar journals"
- method: GET
path: /api/v1/financial/journals/:id
description: "Obtener journal por ID"
- method: PUT
path: /api/v1/financial/journals/:id
description: "Actualizar journal"
- method: DELETE
path: /api/v1/financial/journals/:id
description: "Desactivar journal"
services:
- name: "JournalService"
file: "src/modules/financial/services/journal.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
controllers:
- name: "JournalController"
file: "src/modules/financial/controllers/journal.controller.ts"
dtos:
- name: "CreateJournalDto"
file: "src/modules/financial/dto/create-journal.dto.ts"
- name: "UpdateJournalDto"
file: "src/modules/financial/dto/update-journal.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-002-gestión-de-journals-contables.md"
routes:
- path: "/financial/journals"
component: "JournalsPage"
- path: "/financial/journals/create"
component: "CreateJournalPage"
components:
- name: "JournalsTable"
file: "src/widgets/journals-table/ui/JournalsTable.tsx"
type: widget
- name: "CreateJournalForm"
file: "src/features/create-journal/ui/CreateJournalForm.tsx"
type: feature
- name: "JournalCard"
file: "src/entities/journal/ui/JournalCard.tsx"
type: entity
api_client:
- name: "journalApi"
file: "src/entities/journal/api/journal.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useJournalStore"
file: "src/entities/journal/model/journal.store.ts"
type: zustand
database_tables:
- schema: financial
table: journals
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_journals_company_id
- idx_journals_code
- idx_journals_type
rls_policy: company_isolation_journals
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/journal.service.spec.ts"
test_cases:
- "should create journal with valid data"
- "should validate journal type"
- "should throw error when code already exists"
- "should update journal successfully"
- "should soft delete journal"
integration_tests:
- file: "test/financial/journal.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/financial/journals should create journal"
- "GET /api/v1/financial/journals should return all journals"
- "GET /api/v1/financial/journals/:id should return journal"
- "PUT /api/v1/financial/journals/:id should update journal"
- "DELETE /api/v1/financial/journals/:id should soft delete journal"
- "should enforce company isolation"
- "should require authentication"
frontend:
component_tests:
- file: "src/widgets/journals-table/ui/JournalsTable.test.tsx"
test_cases:
- "should render table with journals"
- "should filter by type"
- file: "src/features/create-journal/ui/CreateJournalForm.test.tsx"
test_cases:
- "should validate required fields"
- "should submit valid form"
e2e_tests:
- file: "e2e/financial/journals.spec.ts"
test_cases:
- "should create journal successfully"
- "should edit journal successfully"
- "should delete journal with confirmation"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear journals por tipo (sale, purchase, bank, general)"
status: Pending
test_reference: "test/financial/journal.controller.e2e-spec.ts:28"
- id: AC-002
description: "Journal tiene código único por empresa"
status: Pending
test_reference: "src/modules/financial/services/journal.service.spec.ts:65"
- id: AC-003
description: "Asientos contables están vinculados a journals"
status: Pending
test_reference: "test/financial/journal.controller.e2e-spec.ts:95"
business_rules:
- id: RN-001
description: "Código de journal único por empresa"
implementation: "database-design/schemas/financial-schema-ddl.sql:CONSTRAINT uq_journals_code_company"
test_reference: "src/modules/financial/services/journal.service.spec.ts:48"
- id: RN-002
description: "Journals tienen tipos: sale, purchase, bank, cash, general"
implementation: "database-design/schemas/financial-schema-ddl.sql:journals.type enum"
test_reference: "src/modules/financial/services/journal.service.spec.ts:78"
- id: RN-003
description: "No se puede eliminar journal con asientos"
implementation: "src/modules/financial/services/journal.service.ts:remove()"
test_reference: "src/modules/financial/services/journal.service.spec.ts:95"
dependencies:
rf_dependencies:
- RF-MGN-002-001
- RF-MGN-004-001
module_dependencies:
- MGN-002
external_dependencies: []
- rf_id: RF-MGN-004-003
rf_title: "Registro de Asientos Contables"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-003-registro-de-asientos-contables.md"
priority: P0
story_points: 13
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-003-registro-de-asientos-contables.md"
endpoints:
- method: POST
path: /api/v1/financial/journal-entries
description: "Crear asiento contable"
- method: GET
path: /api/v1/financial/journal-entries
description: "Listar asientos"
- method: GET
path: /api/v1/financial/journal-entries/:id
description: "Obtener asiento por ID"
- method: PUT
path: /api/v1/financial/journal-entries/:id
description: "Actualizar asiento (draft)"
- method: POST
path: /api/v1/financial/journal-entries/:id/post
description: "Publicar asiento (draft → posted)"
- method: DELETE
path: /api/v1/financial/journal-entries/:id
description: "Eliminar asiento (draft)"
services:
- name: "JournalEntryService"
file: "src/modules/financial/services/journal-entry.service.ts"
methods:
- create
- findAll
- findOne
- update
- post
- remove
- validateBalance
controllers:
- name: "JournalEntryController"
file: "src/modules/financial/controllers/journal-entry.controller.ts"
dtos:
- name: "CreateJournalEntryDto"
file: "src/modules/financial/dto/create-journal-entry.dto.ts"
- name: "UpdateJournalEntryDto"
file: "src/modules/financial/dto/update-journal-entry.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-003-registro-de-asientos-contables.md"
routes:
- path: "/financial/journal-entries"
component: "JournalEntriesPage"
- path: "/financial/journal-entries/create"
component: "CreateJournalEntryPage"
- path: "/financial/journal-entries/:id/edit"
component: "EditJournalEntryPage"
- path: "/financial/journal-entries/:id"
component: "ViewJournalEntryPage"
components:
- name: "JournalEntriesTable"
file: "src/widgets/journal-entries-table/ui/JournalEntriesTable.tsx"
type: widget
- name: "CreateJournalEntryForm"
file: "src/features/create-journal-entry/ui/CreateJournalEntryForm.tsx"
type: feature
- name: "JournalEntryCard"
file: "src/entities/journal-entry/ui/JournalEntryCard.tsx"
type: entity
- name: "JournalEntryLineItems"
file: "src/widgets/journal-entry-lines/ui/JournalEntryLineItems.tsx"
type: widget
api_client:
- name: "journalEntryApi"
file: "src/entities/journal-entry/api/journal-entry.api.ts"
methods:
- getAll
- getById
- create
- update
- post
- delete
state_management:
- name: "useJournalEntryStore"
file: "src/entities/journal-entry/model/journal-entry.store.ts"
type: zustand
database_tables:
- schema: financial
table: journal_entries
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE
indices:
- idx_journal_entries_journal_id
- idx_journal_entries_company_id
- idx_journal_entries_date
- idx_journal_entries_state
rls_policy: company_isolation_journal_entries
- schema: financial
table: journal_entry_lines
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE
indices:
- idx_journal_entry_lines_entry_id
- idx_journal_entry_lines_account_id
- idx_journal_entry_lines_partner_id
rls_policy: company_isolation_journal_entry_lines
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/journal-entry.service.spec.ts"
test_cases:
- "should create journal entry with lines"
- "should validate debit = credit balance"
- "should throw error for unbalanced entry"
- "should post entry (draft → posted)"
- "should prevent editing posted entry"
- "should allow deleting draft entry"
- "should prevent deleting posted entry"
integration_tests:
- file: "test/financial/journal-entry.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/financial/journal-entries should create entry"
- "GET /api/v1/financial/journal-entries should return all entries"
- "GET /api/v1/financial/journal-entries/:id should return entry with lines"
- "PUT /api/v1/financial/journal-entries/:id should update draft entry"
- "POST /api/v1/financial/journal-entries/:id/post should post entry"
- "DELETE /api/v1/financial/journal-entries/:id should delete draft entry"
- "should enforce company isolation"
- "should require authentication"
- "should check accounting permissions"
frontend:
component_tests:
- file: "src/widgets/journal-entries-table/ui/JournalEntriesTable.test.tsx"
test_cases:
- "should render table with entries"
- "should filter by state"
- "should handle pagination"
- file: "src/features/create-journal-entry/ui/CreateJournalEntryForm.test.tsx"
test_cases:
- "should validate required fields"
- "should validate debit = credit"
- "should submit valid form"
e2e_tests:
- file: "e2e/financial/journal-entries.spec.ts"
test_cases:
- "should create journal entry successfully"
- "should post entry successfully"
- "should show error for unbalanced entry"
- "should prevent editing posted entry"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear asientos contables con múltiples líneas"
status: Pending
test_reference: "test/financial/journal-entry.controller.e2e-spec.ts:28"
- id: AC-002
description: "Sistema valida que suma de débitos = suma de créditos"
status: Pending
test_reference: "src/modules/financial/services/journal-entry.service.spec.ts:65"
- id: AC-003
description: "Asientos publicados no pueden modificarse"
status: Pending
test_reference: "test/financial/journal-entry.controller.e2e-spec.ts:105"
business_rules:
- id: RN-001
description: "Suma de débitos debe igualar suma de créditos"
implementation: "src/modules/financial/services/journal-entry.service.ts:validateBalance()"
test_reference: "src/modules/financial/services/journal-entry.service.spec.ts:48"
- id: RN-002
description: "Asientos tienen estados: draft, posted"
implementation: "database-design/schemas/financial-schema-ddl.sql:journal_entries.state"
test_reference: "src/modules/financial/services/journal-entry.service.spec.ts:78"
- id: RN-003
description: "Solo asientos draft pueden modificarse o eliminarse"
implementation: "src/modules/financial/services/journal-entry.service.ts:update()"
test_reference: "src/modules/financial/services/journal-entry.service.spec.ts:108"
dependencies:
rf_dependencies:
- RF-MGN-004-001
- RF-MGN-004-002
- RF-MGN-003-001
module_dependencies:
- MGN-003
external_dependencies: []
- rf_id: RF-MGN-004-004
rf_title: "Gestión de Impuestos"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-004-gestión-de-impuestos.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-004-gestión-de-impuestos.md"
endpoints:
- method: POST
path: /api/v1/financial/taxes
description: "Crear impuesto"
- method: GET
path: /api/v1/financial/taxes
description: "Listar impuestos"
- method: GET
path: /api/v1/financial/taxes/:id
description: "Obtener impuesto por ID"
- method: PUT
path: /api/v1/financial/taxes/:id
description: "Actualizar impuesto"
- method: DELETE
path: /api/v1/financial/taxes/:id
description: "Desactivar impuesto"
services:
- name: "TaxService"
file: "src/modules/financial/services/tax.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- calculateTax
controllers:
- name: "TaxController"
file: "src/modules/financial/controllers/tax.controller.ts"
dtos:
- name: "CreateTaxDto"
file: "src/modules/financial/dto/create-tax.dto.ts"
- name: "UpdateTaxDto"
file: "src/modules/financial/dto/update-tax.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-004-gestión-de-impuestos.md"
routes:
- path: "/financial/taxes"
component: "TaxesPage"
- path: "/financial/taxes/create"
component: "CreateTaxPage"
components:
- name: "TaxesTable"
file: "src/widgets/taxes-table/ui/TaxesTable.tsx"
type: widget
- name: "CreateTaxForm"
file: "src/features/create-tax/ui/CreateTaxForm.tsx"
type: feature
- name: "TaxCard"
file: "src/entities/tax/ui/TaxCard.tsx"
type: entity
api_client:
- name: "taxApi"
file: "src/entities/tax/api/tax.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useTaxStore"
file: "src/entities/tax/model/tax.store.ts"
type: zustand
database_tables:
- schema: financial
table: taxes
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_taxes_company_id
- idx_taxes_type
rls_policy: company_isolation_taxes
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/tax.service.spec.ts"
test_cases:
- "should create tax with valid data"
- "should calculate tax amount"
- "should handle percentage and fixed taxes"
- "should validate rate between 0-100"
- "should update tax successfully"
integration_tests:
- file: "test/financial/tax.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/financial/taxes should create tax"
- "GET /api/v1/financial/taxes should return all taxes"
- "GET /api/v1/financial/taxes/:id should return tax"
- "PUT /api/v1/financial/taxes/:id should update tax"
- "DELETE /api/v1/financial/taxes/:id should soft delete tax"
- "should enforce company isolation"
- "should require authentication"
frontend:
component_tests:
- file: "src/widgets/taxes-table/ui/TaxesTable.test.tsx"
test_cases:
- "should render table with taxes"
- "should filter by type"
- file: "src/features/create-tax/ui/CreateTaxForm.test.tsx"
test_cases:
- "should validate required fields"
- "should validate rate range"
- "should submit valid form"
e2e_tests:
- file: "e2e/financial/taxes.spec.ts"
test_cases:
- "should create tax successfully"
- "should edit tax successfully"
- "should delete tax with confirmation"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear impuestos con tipo (sale, purchase, both)"
status: Pending
test_reference: "test/financial/tax.controller.e2e-spec.ts:28"
- id: AC-002
description: "Sistema calcula impuestos automáticamente en facturas"
status: Pending
test_reference: "src/modules/financial/services/tax.service.spec.ts:65"
- id: AC-003
description: "Impuestos tienen cuentas contables asociadas"
status: Pending
test_reference: "test/financial/tax.controller.e2e-spec.ts:95"
business_rules:
- id: RN-001
description: "Impuestos tienen tipos: sale (ventas), purchase (compras), both"
implementation: "database-design/schemas/financial-schema-ddl.sql:taxes.type"
test_reference: "src/modules/financial/services/tax.service.spec.ts:48"
- id: RN-002
description: "Rate debe estar entre 0 y 100"
implementation: "src/modules/financial/dto/create-tax.dto.ts:@Min(0) @Max(100)"
test_reference: "src/modules/financial/services/tax.service.spec.ts:78"
- id: RN-003
description: "Impuesto debe tener cuenta contable asignada"
implementation: "database-design/schemas/financial-schema-ddl.sql:taxes.account_id"
test_reference: "src/modules/financial/services/tax.service.spec.ts:95"
dependencies:
rf_dependencies:
- RF-MGN-004-001
- RF-MGN-002-001
module_dependencies:
- MGN-002
external_dependencies: []
- rf_id: RF-MGN-004-005
rf_title: "Gestión de Facturas de Cliente"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-005-gestión-de-facturas-de-cliente.md"
priority: P0
story_points: 13
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-005-gestión-de-facturas-de-cliente.md"
endpoints:
- method: POST
path: /api/v1/financial/customer-invoices
description: "Crear factura de cliente"
- method: GET
path: /api/v1/financial/customer-invoices
description: "Listar facturas de cliente"
- method: GET
path: /api/v1/financial/customer-invoices/:id
description: "Obtener factura por ID"
- method: PUT
path: /api/v1/financial/customer-invoices/:id
description: "Actualizar factura (draft)"
- method: POST
path: /api/v1/financial/customer-invoices/:id/validate
description: "Validar factura (draft → open)"
- method: POST
path: /api/v1/financial/customer-invoices/:id/cancel
description: "Cancelar factura"
services:
- name: "CustomerInvoiceService"
file: "src/modules/financial/services/customer-invoice.service.ts"
methods:
- create
- findAll
- findOne
- update
- validate
- cancel
- generateJournalEntry
controllers:
- name: "CustomerInvoiceController"
file: "src/modules/financial/controllers/customer-invoice.controller.ts"
dtos:
- name: "CreateCustomerInvoiceDto"
file: "src/modules/financial/dto/create-customer-invoice.dto.ts"
- name: "UpdateCustomerInvoiceDto"
file: "src/modules/financial/dto/update-customer-invoice.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-005-gestión-de-facturas-de-cliente.md"
routes:
- path: "/financial/customer-invoices"
component: "CustomerInvoicesPage"
- path: "/financial/customer-invoices/create"
component: "CreateCustomerInvoicePage"
- path: "/financial/customer-invoices/:id/edit"
component: "EditCustomerInvoicePage"
- path: "/financial/customer-invoices/:id"
component: "ViewCustomerInvoicePage"
components:
- name: "CustomerInvoicesTable"
file: "src/widgets/customer-invoices-table/ui/CustomerInvoicesTable.tsx"
type: widget
- name: "CreateCustomerInvoiceForm"
file: "src/features/create-customer-invoice/ui/CreateCustomerInvoiceForm.tsx"
type: feature
- name: "CustomerInvoiceCard"
file: "src/entities/customer-invoice/ui/CustomerInvoiceCard.tsx"
type: entity
- name: "InvoiceLineItems"
file: "src/widgets/invoice-line-items/ui/InvoiceLineItems.tsx"
type: widget
api_client:
- name: "customerInvoiceApi"
file: "src/entities/customer-invoice/api/customer-invoice.api.ts"
methods:
- getAll
- getById
- create
- update
- validate
- cancel
state_management:
- name: "useCustomerInvoiceStore"
file: "src/entities/customer-invoice/model/customer-invoice.store.ts"
type: zustand
database_tables:
- schema: financial
table: invoices
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
indices:
- idx_invoices_company_id
- idx_invoices_partner_id
- idx_invoices_type
- idx_invoices_state
- idx_invoices_invoice_date
rls_policy: company_isolation_invoices
- schema: financial
table: invoice_lines
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE
indices:
- idx_invoice_lines_invoice_id
- idx_invoice_lines_product_id
rls_policy: company_isolation_invoice_lines
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/customer-invoice.service.spec.ts"
test_cases:
- "should create customer invoice with lines"
- "should calculate totals with taxes"
- "should validate invoice (draft → open)"
- "should generate journal entry on validation"
- "should cancel invoice"
- "should prevent modifying validated invoice"
integration_tests:
- file: "test/financial/customer-invoice.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/financial/customer-invoices should create invoice"
- "GET /api/v1/financial/customer-invoices should return all invoices"
- "GET /api/v1/financial/customer-invoices/:id should return invoice with lines"
- "PUT /api/v1/financial/customer-invoices/:id should update draft invoice"
- "POST /api/v1/financial/customer-invoices/:id/validate should validate invoice"
- "POST /api/v1/financial/customer-invoices/:id/cancel should cancel invoice"
- "should enforce company isolation"
- "should require authentication"
frontend:
component_tests:
- file: "src/widgets/customer-invoices-table/ui/CustomerInvoicesTable.test.tsx"
test_cases:
- "should render table with invoices"
- "should filter by state"
- "should handle pagination"
- file: "src/features/create-customer-invoice/ui/CreateCustomerInvoiceForm.test.tsx"
test_cases:
- "should validate required fields"
- "should calculate totals"
- "should submit valid form"
e2e_tests:
- file: "e2e/financial/customer-invoices.spec.ts"
test_cases:
- "should create customer invoice successfully"
- "should validate invoice successfully"
- "should cancel invoice with confirmation"
- "should prevent editing validated invoice"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear facturas de cliente con líneas y impuestos"
status: Pending
test_reference: "test/financial/customer-invoice.controller.e2e-spec.ts:28"
- id: AC-002
description: "Sistema genera asiento contable al validar factura"
status: Pending
test_reference: "src/modules/financial/services/customer-invoice.service.spec.ts:85"
- id: AC-003
description: "Facturas validadas no pueden modificarse"
status: Pending
test_reference: "test/financial/customer-invoice.controller.e2e-spec.ts:125"
business_rules:
- id: RN-001
description: "Facturas tienen estados: draft, open, paid, cancelled"
implementation: "database-design/schemas/financial-schema-ddl.sql:invoices.state"
test_reference: "src/modules/financial/services/customer-invoice.service.spec.ts:58"
- id: RN-002
description: "Al validar factura se genera asiento contable automático"
implementation: "src/modules/financial/services/customer-invoice.service.ts:generateJournalEntry()"
test_reference: "src/modules/financial/services/customer-invoice.service.spec.ts:92"
- id: RN-003
description: "Solo facturas draft pueden modificarse"
implementation: "src/modules/financial/services/customer-invoice.service.ts:update()"
test_reference: "src/modules/financial/services/customer-invoice.service.spec.ts:118"
dependencies:
rf_dependencies:
- RF-MGN-004-001
- RF-MGN-004-002
- RF-MGN-004-003
- RF-MGN-004-004
- RF-MGN-003-001
module_dependencies:
- MGN-003
external_dependencies: []
- rf_id: RF-MGN-004-006
rf_title: "Gestión de Facturas de Proveedor"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-006-gestión-de-facturas-de-proveedor.md"
priority: P0
story_points: 13
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-006-gestión-de-facturas-de-proveedor.md"
endpoints:
- method: POST
path: /api/v1/financial/vendor-invoices
description: "Crear factura de proveedor"
- method: GET
path: /api/v1/financial/vendor-invoices
description: "Listar facturas de proveedor"
- method: GET
path: /api/v1/financial/vendor-invoices/:id
description: "Obtener factura por ID"
- method: PUT
path: /api/v1/financial/vendor-invoices/:id
description: "Actualizar factura (draft)"
- method: POST
path: /api/v1/financial/vendor-invoices/:id/validate
description: "Validar factura (draft → open)"
- method: POST
path: /api/v1/financial/vendor-invoices/:id/cancel
description: "Cancelar factura"
services:
- name: "VendorInvoiceService"
file: "src/modules/financial/services/vendor-invoice.service.ts"
methods:
- create
- findAll
- findOne
- update
- validate
- cancel
- generateJournalEntry
controllers:
- name: "VendorInvoiceController"
file: "src/modules/financial/controllers/vendor-invoice.controller.ts"
dtos:
- name: "CreateVendorInvoiceDto"
file: "src/modules/financial/dto/create-vendor-invoice.dto.ts"
- name: "UpdateVendorInvoiceDto"
file: "src/modules/financial/dto/update-vendor-invoice.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-006-gestión-de-facturas-de-proveedor.md"
routes:
- path: "/financial/vendor-invoices"
component: "VendorInvoicesPage"
- path: "/financial/vendor-invoices/create"
component: "CreateVendorInvoicePage"
- path: "/financial/vendor-invoices/:id/edit"
component: "EditVendorInvoicePage"
- path: "/financial/vendor-invoices/:id"
component: "ViewVendorInvoicePage"
components:
- name: "VendorInvoicesTable"
file: "src/widgets/vendor-invoices-table/ui/VendorInvoicesTable.tsx"
type: widget
- name: "CreateVendorInvoiceForm"
file: "src/features/create-vendor-invoice/ui/CreateVendorInvoiceForm.tsx"
type: feature
- name: "VendorInvoiceCard"
file: "src/entities/vendor-invoice/ui/VendorInvoiceCard.tsx"
type: entity
- name: "InvoiceLineItems"
file: "src/widgets/invoice-line-items/ui/InvoiceLineItems.tsx"
type: widget
api_client:
- name: "vendorInvoiceApi"
file: "src/entities/vendor-invoice/api/vendor-invoice.api.ts"
methods:
- getAll
- getById
- create
- update
- validate
- cancel
state_management:
- name: "useVendorInvoiceStore"
file: "src/entities/vendor-invoice/model/vendor-invoice.store.ts"
type: zustand
database_tables:
- schema: financial
table: invoices
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
indices:
- idx_invoices_company_id
- idx_invoices_partner_id
- idx_invoices_type
- idx_invoices_state
rls_policy: company_isolation_invoices
- schema: financial
table: invoice_lines
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE
indices:
- idx_invoice_lines_invoice_id
- idx_invoice_lines_product_id
rls_policy: company_isolation_invoice_lines
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/vendor-invoice.service.spec.ts"
test_cases:
- "should create vendor invoice with lines"
- "should calculate totals with taxes"
- "should validate invoice (draft → open)"
- "should generate journal entry on validation"
- "should cancel invoice"
- "should prevent modifying validated invoice"
integration_tests:
- file: "test/financial/vendor-invoice.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/financial/vendor-invoices should create invoice"
- "GET /api/v1/financial/vendor-invoices should return all invoices"
- "GET /api/v1/financial/vendor-invoices/:id should return invoice with lines"
- "PUT /api/v1/financial/vendor-invoices/:id should update draft invoice"
- "POST /api/v1/financial/vendor-invoices/:id/validate should validate invoice"
- "POST /api/v1/financial/vendor-invoices/:id/cancel should cancel invoice"
- "should enforce company isolation"
- "should require authentication"
frontend:
component_tests:
- file: "src/widgets/vendor-invoices-table/ui/VendorInvoicesTable.test.tsx"
test_cases:
- "should render table with invoices"
- "should filter by state"
- "should handle pagination"
- file: "src/features/create-vendor-invoice/ui/CreateVendorInvoiceForm.test.tsx"
test_cases:
- "should validate required fields"
- "should calculate totals"
- "should submit valid form"
e2e_tests:
- file: "e2e/financial/vendor-invoices.spec.ts"
test_cases:
- "should create vendor invoice successfully"
- "should validate invoice successfully"
- "should cancel invoice with confirmation"
- "should prevent editing validated invoice"
acceptance_criteria:
- id: AC-001
description: "Usuario puede crear facturas de proveedor con líneas y impuestos"
status: Pending
test_reference: "test/financial/vendor-invoice.controller.e2e-spec.ts:28"
- id: AC-002
description: "Sistema genera asiento contable al validar factura"
status: Pending
test_reference: "src/modules/financial/services/vendor-invoice.service.spec.ts:85"
- id: AC-003
description: "Facturas validadas no pueden modificarse"
status: Pending
test_reference: "test/financial/vendor-invoice.controller.e2e-spec.ts:125"
business_rules:
- id: RN-001
description: "Facturas tienen estados: draft, open, paid, cancelled"
implementation: "database-design/schemas/financial-schema-ddl.sql:invoices.state"
test_reference: "src/modules/financial/services/vendor-invoice.service.spec.ts:58"
- id: RN-002
description: "Al validar factura se genera asiento contable automático"
implementation: "src/modules/financial/services/vendor-invoice.service.ts:generateJournalEntry()"
test_reference: "src/modules/financial/services/vendor-invoice.service.spec.ts:92"
- id: RN-003
description: "Solo facturas draft pueden modificarse"
implementation: "src/modules/financial/services/vendor-invoice.service.ts:update()"
test_reference: "src/modules/financial/services/vendor-invoice.service.spec.ts:118"
dependencies:
rf_dependencies:
- RF-MGN-004-001
- RF-MGN-004-002
- RF-MGN-004-003
- RF-MGN-004-004
- RF-MGN-003-001
module_dependencies:
- MGN-003
external_dependencies: []
- rf_id: RF-MGN-004-007
rf_title: "Gestión de Pagos y Conciliación"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-007-gestión-de-pagos-y-conciliación.md"
priority: P0
story_points: 13
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-007-gestión-de-pagos-y-conciliación.md"
endpoints:
- method: POST
path: /api/v1/financial/payments
description: "Registrar pago"
- method: GET
path: /api/v1/financial/payments
description: "Listar pagos"
- method: GET
path: /api/v1/financial/payments/:id
description: "Obtener pago por ID"
- method: POST
path: /api/v1/financial/payments/:id/reconcile
description: "Conciliar pago con factura(s)"
- method: POST
path: /api/v1/financial/payments/:id/cancel
description: "Cancelar pago"
services:
- name: "PaymentService"
file: "src/modules/financial/services/payment.service.ts"
methods:
- create
- findAll
- findOne
- reconcile
- cancel
- generateJournalEntry
controllers:
- name: "PaymentController"
file: "src/modules/financial/controllers/payment.controller.ts"
dtos:
- name: "CreatePaymentDto"
file: "src/modules/financial/dto/create-payment.dto.ts"
- name: "ReconcilePaymentDto"
file: "src/modules/financial/dto/reconcile-payment.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-007-gestión-de-pagos-y-conciliación.md"
routes:
- path: "/financial/payments"
component: "PaymentsPage"
- path: "/financial/payments/create"
component: "CreatePaymentPage"
- path: "/financial/payments/:id"
component: "ViewPaymentPage"
- path: "/financial/payments/:id/reconcile"
component: "ReconcilePaymentPage"
components:
- name: "PaymentsTable"
file: "src/widgets/payments-table/ui/PaymentsTable.tsx"
type: widget
- name: "CreatePaymentForm"
file: "src/features/create-payment/ui/CreatePaymentForm.tsx"
type: feature
- name: "PaymentCard"
file: "src/entities/payment/ui/PaymentCard.tsx"
type: entity
- name: "ReconcilePaymentForm"
file: "src/features/reconcile-payment/ui/ReconcilePaymentForm.tsx"
type: feature
api_client:
- name: "paymentApi"
file: "src/entities/payment/api/payment.api.ts"
methods:
- getAll
- getById
- create
- reconcile
- cancel
state_management:
- name: "usePaymentStore"
file: "src/entities/payment/model/payment.store.ts"
type: zustand
database_tables:
- schema: financial
table: payments
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
indices:
- idx_payments_company_id
- idx_payments_partner_id
- idx_payments_payment_date
- idx_payments_state
rls_policy: company_isolation_payments
- schema: financial
table: payment_invoice_reconciliations
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
- INSERT
- DELETE
indices:
- idx_reconciliations_payment_id
- idx_reconciliations_invoice_id
rls_policy: company_isolation_reconciliations
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/payment.service.spec.ts"
test_cases:
- "should create payment"
- "should reconcile payment with invoice"
- "should reconcile payment with multiple invoices"
- "should update invoice state to paid when fully reconciled"
- "should generate journal entry for payment"
- "should cancel payment"
integration_tests:
- file: "test/financial/payment.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/financial/payments should create payment"
- "GET /api/v1/financial/payments should return all payments"
- "GET /api/v1/financial/payments/:id should return payment"
- "POST /api/v1/financial/payments/:id/reconcile should reconcile payment"
- "POST /api/v1/financial/payments/:id/cancel should cancel payment"
- "should enforce company isolation"
- "should require authentication"
frontend:
component_tests:
- file: "src/widgets/payments-table/ui/PaymentsTable.test.tsx"
test_cases:
- "should render table with payments"
- "should filter by state"
- file: "src/features/create-payment/ui/CreatePaymentForm.test.tsx"
test_cases:
- "should validate required fields"
- "should submit valid form"
e2e_tests:
- file: "e2e/financial/payments.spec.ts"
test_cases:
- "should create payment successfully"
- "should reconcile payment with invoice"
- "should cancel payment with confirmation"
- "should show invoice as paid after full reconciliation"
acceptance_criteria:
- id: AC-001
description: "Usuario puede registrar pagos de clientes y proveedores"
status: Pending
test_reference: "test/financial/payment.controller.e2e-spec.ts:28"
- id: AC-002
description: "Usuario puede conciliar pagos con facturas"
status: Pending
test_reference: "test/financial/payment.controller.e2e-spec.ts:68"
- id: AC-003
description: "Factura cambia a estado paid cuando se concilia completamente"
status: Pending
test_reference: "src/modules/financial/services/payment.service.spec.ts:95"
business_rules:
- id: RN-001
description: "Pago puede conciliarse con una o múltiples facturas"
implementation: "database-design/schemas/financial-schema-ddl.sql:payment_invoice_reconciliations"
test_reference: "src/modules/financial/services/payment.service.spec.ts:58"
- id: RN-002
description: "Factura pasa a paid cuando monto conciliado = monto total"
implementation: "src/modules/financial/services/payment.service.ts:reconcile()"
test_reference: "src/modules/financial/services/payment.service.spec.ts:85"
- id: RN-003
description: "Al registrar pago se genera asiento contable"
implementation: "src/modules/financial/services/payment.service.ts:generateJournalEntry()"
test_reference: "src/modules/financial/services/payment.service.spec.ts:118"
dependencies:
rf_dependencies:
- RF-MGN-004-003
- RF-MGN-004-005
- RF-MGN-004-006
- RF-MGN-003-001
module_dependencies:
- MGN-003
external_dependencies: []
- rf_id: RF-MGN-004-008
rf_title: "Reportes Financieros (Balance y P&L)"
rf_file: "requerimientos-funcionales/mgn-004/RF-MGN-004-008-reportes-financieros-balance-y-p&l.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-008-reportes-financieros-balance-y-p&l.md"
endpoints:
- method: GET
path: /api/v1/financial/reports/balance-sheet
description: "Generar Balance General"
- method: GET
path: /api/v1/financial/reports/profit-loss
description: "Generar Estado de Resultados (P&L)"
- method: GET
path: /api/v1/financial/reports/trial-balance
description: "Generar Balanza de Comprobación"
- method: GET
path: /api/v1/financial/reports/general-ledger
description: "Generar Libro Mayor"
services:
- name: "FinancialReportService"
file: "src/modules/financial/services/financial-report.service.ts"
methods:
- generateBalanceSheet
- generateProfitLoss
- generateTrialBalance
- generateGeneralLedger
controllers:
- name: "FinancialReportController"
file: "src/modules/financial/controllers/financial-report.controller.ts"
dtos:
- name: "ReportPeriodDto"
file: "src/modules/financial/dto/report-period.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-008-reportes-financieros-balance-y-p&l.md"
routes:
- path: "/financial/reports/balance-sheet"
component: "BalanceSheetPage"
- path: "/financial/reports/profit-loss"
component: "ProfitLossPage"
- path: "/financial/reports/trial-balance"
component: "TrialBalancePage"
- path: "/financial/reports/general-ledger"
component: "GeneralLedgerPage"
components:
- name: "BalanceSheetReport"
file: "src/widgets/balance-sheet-report/ui/BalanceSheetReport.tsx"
type: widget
- name: "ProfitLossReport"
file: "src/widgets/profit-loss-report/ui/ProfitLossReport.tsx"
type: widget
- name: "ReportFilters"
file: "src/features/report-filters/ui/ReportFilters.tsx"
type: feature
api_client:
- name: "financialReportApi"
file: "src/entities/financial-report/api/financial-report.api.ts"
methods:
- getBalanceSheet
- getProfitLoss
- getTrialBalance
- getGeneralLedger
state_management:
- name: "useFinancialReportStore"
file: "src/entities/financial-report/model/financial-report.store.ts"
type: zustand
database_tables:
- schema: financial
table: journal_entry_lines
file: "database-design/schemas/financial-schema-ddl.sql"
operations:
- SELECT
indices:
- idx_journal_entry_lines_account_id
- idx_journal_entry_lines_date
rls_policy: company_isolation_journal_entry_lines
tests:
backend:
unit_tests:
- file: "src/modules/financial/services/financial-report.service.spec.ts"
test_cases:
- "should generate balance sheet"
- "should generate profit & loss"
- "should filter by date range"
- "should calculate balances correctly"
- "should handle hierarchical accounts"
integration_tests:
- file: "test/financial/financial-report.controller.e2e-spec.ts"
test_cases:
- "GET /api/v1/financial/reports/balance-sheet should return balance sheet"
- "GET /api/v1/financial/reports/profit-loss should return P&L"
- "GET /api/v1/financial/reports/trial-balance should return trial balance"
- "GET /api/v1/financial/reports/general-ledger should return general ledger"
- "should enforce company isolation"
- "should require authentication"
frontend:
component_tests:
- file: "src/widgets/balance-sheet-report/ui/BalanceSheetReport.test.tsx"
test_cases:
- "should render balance sheet"
- "should show assets and liabilities"
- file: "src/widgets/profit-loss-report/ui/ProfitLossReport.test.tsx"
test_cases:
- "should render P&L statement"
- "should show income and expenses"
e2e_tests:
- file: "e2e/financial/reports.spec.ts"
test_cases:
- "should generate balance sheet successfully"
- "should generate P&L successfully"
- "should filter by date range"
- "should export to PDF"
acceptance_criteria:
- id: AC-001
description: "Usuario puede generar Balance General por período"
status: Pending
test_reference: "test/financial/financial-report.controller.e2e-spec.ts:28"
- id: AC-002
description: "Usuario puede generar Estado de Resultados (P&L) por período"
status: Pending
test_reference: "test/financial/financial-report.controller.e2e-spec.ts:58"
- id: AC-003
description: "Reportes pueden exportarse a PDF y Excel"
status: Pending
test_reference: "e2e/financial/reports.spec.ts:85"
business_rules:
- id: RN-001
description: "Balance Sheet muestra Assets = Liabilities + Equity"
implementation: "src/modules/financial/services/financial-report.service.ts:generateBalanceSheet()"
test_reference: "src/modules/financial/services/financial-report.service.spec.ts:58"
- id: RN-002
description: "P&L calcula Net Income = Income - Expenses"
implementation: "src/modules/financial/services/financial-report.service.ts:generateProfitLoss()"
test_reference: "src/modules/financial/services/financial-report.service.spec.ts:85"
- id: RN-003
description: "Reportes filtran por rango de fechas (date_from, date_to)"
implementation: "src/modules/financial/services/financial-report.service.ts:filterByPeriod()"
test_reference: "src/modules/financial/services/financial-report.service.spec.ts:108"
dependencies:
rf_dependencies:
- RF-MGN-004-001
- RF-MGN-004-003
- RF-MGN-002-001
module_dependencies:
- MGN-002
external_dependencies:
- name: "pdfkit"
version: "^0.13.0"
- name: "xlsx"
version: "^0.18.5"
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: 40
total_components: 32
total_tables: 12
total_test_cases: 160
estimated_duration_sprints: 5