# US-MGN-004-005-002: Validar Factura de Cliente y Generar Asiento **RF Asociado:** [RF-MGN-004-005](../../02-modelado/requerimientos-funcionales/mgn-004/RF-MGN-004-005-gestión-de-facturas-de-cliente.md) **Módulo:** MGN-004 - Financiero Básico **Epic:** Facturas de Cliente **Prioridad:** P0 (MVP) **Story Points:** 5 **Sprint:** Sprint 10 **Estado:** Ready for Development **Fecha:** 2025-11-24 --- ## User Story **Como** usuario de ventas o contador, **Quiero** validar facturas de cliente draft para contabilizarlas, **Para** que generen asiento contable automático y queden confirmadas. --- ## Descripción Detallada Al validar una factura draft → open: - Estado cambia de 'draft' a 'open' - Se genera asiento contable automático (journal entry) - Factura queda inmutable (no se puede editar) - Se actualiza due_date según payment_term - Se registra validated_date y validated_by El asiento contable generado tiene: - Débito: Cuentas por Cobrar (partner.receivable_account) por total - Crédito: Cuentas de Ingresos (products.income_account) por subtotal de cada línea - Crédito: Cuentas de Impuestos (tax.collected_account) por impuestos --- ## Criterios de Aceptación ### Escenario 1: Validar factura draft exitosamente **Dado que** tengo factura draft con id=10, totales correctos, **Cuando** POST /customer-invoices/10/validate, **Entonces** state='open', asiento contable creado y posteado, due_date calculado. ### Escenario 2: Generar asiento contable correcto **Dado que** factura tiene subtotal=1000, IVA 21%=210, total=1210, **Cuando** valido factura, **Entonces** asiento contable: - Débito: Cuentas por Cobrar 1210 - Crédito: Ingresos 1000 - Crédito: IVA por Pagar 210 ### Escenario 3: No se puede validar factura ya open **Dado que** factura tiene state='open', **Cuando** intento validarla nuevamente, **Entonces** error 409 "Factura ya está validada". ### Escenario 4: Calcular due_date según payment_term **Dado que** invoice_date="2024-01-15", payment_term="30 días", **Cuando** valido factura, **Entonces** due_date="2024-02-14". ### Escenario 5: Factura open no se puede editar **Dado que** factura tiene state='open', **Cuando** intento actualizar líneas, **Entonces** error 400 "Facturas validadas no pueden editarse". --- ## Reglas de Negocio - **RN-1:** Solo facturas draft pueden validarse. - **RN-2:** Asiento contable se genera automáticamente. - **RN-3:** Asiento se postea automáticamente (state='posted'). - **RN-4:** Facturas open son inmutables. - **RN-5:** due_date = invoice_date + payment_term.days. - **RN-6:** Cuentas contables vienen de partner y products. - **RN-7:** Se registra validated_date y validated_by. --- ## Tareas Técnicas ### Backend - [ ] POST /api/v1/financial/customer-invoices/:id/validate - [ ] Service: CustomerInvoiceService.validate(id, userId) - [ ] Service: CustomerInvoiceService.generateJournalEntry(invoice) - [ ] Validar state='draft' - [ ] Generar asiento contable (débitos y créditos) - [ ] Postear asiento automáticamente - [ ] Actualizar state='open', validated_date, validated_by - [ ] Calcular due_date según payment_term - [ ] Unit tests (10 test cases) - [ ] Integration tests (8 test cases) ### Frontend - [ ] Botón "Validar" (visible solo si draft) - [ ] Modal: ConfirmValidateInvoiceModal.tsx - [ ] Badge estado: Draft vs Open vs Paid - [ ] Deshabilitar edición si open - [ ] Link: "Ver Asiento Contable" - [ ] API client: customerInvoiceApi.validate(id) - [ ] E2E test: "should validate invoice and generate entry" ### Database - [ ] Campo: invoices.state (draft, open, paid, cancelled) - [ ] Campo: invoices.journal_entry_id (FK a journal_entries) - [ ] Campo: invoices.validated_date, validated_by - [ ] Campo: invoices.due_date (calculated) --- ## Mockups / Wireframes **Botón Validar (Factura Draft):** ``` [Ver PDF] [Editar] [Validar Factura] ``` **Modal Confirmación:** ``` ⚠️ ¿Validar factura INV/2024/0001? Esto generará asiento contable y la factura quedará confirmada (no se podrá editar). [Cancelar] [Sí, Validar] ``` **Badge Estado Open:** ``` Factura INV/2024/0001 [Confirmada ✓] Validada: 2024-01-15 10:30 (Juan Pérez) Vencimiento: 2024-02-14 [Ver Asiento Contable →] ``` --- ## Casos de Prueba 1. **TC-001:** Validar draft exitosamente 2. **TC-002:** Generar asiento con débitos/créditos correctos 3. **TC-003:** Error por factura ya open 4. **TC-004:** Calcular due_date correctamente 5. **TC-005:** Factura open no editable 6. **TC-006:** Asiento se postea automáticamente 7. **TC-007:** Vincular invoice.journal_entry_id --- ## Dependencias - **US bloqueantes:** - US-MGN-004-005-001 (Crear Factura Cliente) - US-MGN-004-003-001 (Crear Asiento) - US-MGN-004-003-002 (Postear Asiento) --- ## Estimación: 9 horas = 5 SP --- ## Definition of Done - [ ] Código implementado - [ ] Asiento contable se genera correctamente - [ ] Asiento se postea automáticamente - [ ] Due_date calculado - [ ] Factura open inmutable - [ ] Tests pasando (>80%) - [ ] Code review aprobado - [ ] Merge a develop --- ## Referencias - [RF-MGN-004-005](../../02-modelado/requerimientos-funcionales/mgn-004/RF-MGN-004-005-gestión-de-facturas-de-cliente.md) - [TRACEABILITY-MGN-004.yaml](../../02-modelado/trazabilidad/TRACEABILITY-MGN-004.yaml)