erp-core/docs/05-user-stories/mgn-004/US-MGN-004-005-002-validar-factura-cliente.md

5.2 KiB

US-MGN-004-005-002: Validar Factura de Cliente y Generar Asiento

RF Asociado: RF-MGN-004-005 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