# 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