# 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)
