# US-MGN-004-002-001: CRUD de Journals Contables

**RF Asociado:** [RF-MGN-004-002](../../02-modelado/requerimientos-funcionales/mgn-004/RF-MGN-004-002-gestión-de-journals-contables.md)
**Módulo:** MGN-004 - Financiero Básico
**Epic:** Journals Contables
**Prioridad:** P0 (MVP)
**Story Points:** 5
**Sprint:** Sprint 7
**Estado:** Ready for Development
**Fecha:** 2025-11-24

---

## User Story

**Como** contador de la empresa,
**Quiero** crear y gestionar journals contables (diarios),
**Para** clasificar los asientos contables según su origen (ventas, compras, banco, caja, misceláneos).

---

## Descripción Detallada

Los journals (diarios contables) son libros donde se registran los asientos contables agrupados por tipo de operación. Cada journal tiene:
- Código único por empresa (ej: "VEN", "COM", "BAN")
- Nombre descriptivo
- Tipo: sale (ventas), purchase (compras), bank (banco), cash (caja), general (misceláneos)
- Secuencia para numerar asientos automáticamente
- Cuenta bancaria asociada (opcional, para journals tipo bank)
- Moneda por defecto

Los journals permiten segregar y organizar los asientos contables, facilitando el análisis y auditoría.

---

## Criterios de Aceptación

### Escenario 1: Crear journal exitosamente
**Dado que** soy contador con permisos accounting_manager,
**Cuando** creo un journal con code="VEN", name="Ventas", type="sale", currency="USD",
**Entonces** el sistema crea el journal y retorna el registro completo con id y company_id.

### Escenario 2: Validar código único por empresa
**Dado que** ya existe un journal con code="VEN" en mi empresa,
**Cuando** intento crear otro journal con el mismo código,
**Entonces** el sistema retorna error 400 "El código de journal ya existe en esta empresa".

### Escenario 3: Listar journals con filtro por tipo
**Dado que** tengo 10 journals en mi empresa,
**Cuando** listo journals con filtro type="bank",
**Entonces** el sistema retorna solo los journals de tipo bank.

### Escenario 4: Actualizar journal
**Dado que** tengo un journal con id=5,
**Cuando** actualizo el nombre a "Ventas Nacionales",
**Entonces** el sistema actualiza el journal y retorna el registro modificado.

### Escenario 5: No se puede eliminar journal con asientos
**Dado que** tengo un journal con asientos contables asociados,
**Cuando** intento eliminar el journal,
**Entonces** el sistema retorna error 409 "No se puede eliminar journal con asientos contables".

### Escenario 6: Tipos de journal válidos
**Dado que** intento crear un journal con type="invalid",
**Cuando** envío el request,
**Entonces** el sistema retorna error 400 "Tipo de journal inválido. Valores permitidos: sale, purchase, bank, cash, general".

---

## Reglas de Negocio

- **RN-1:** Código de journal debe ser único por empresa.
- **RN-2:** Tipos válidos: sale, purchase, bank, cash, general.
- **RN-3:** Journals tipo bank deben tener bank_account_id asociado (opcional para otros tipos).
- **RN-4:** Cada journal tiene una secuencia para auto-numerar asientos (ej: VEN/2024/0001).
- **RN-5:** No se puede eliminar un journal con asientos contables asociados.
- **RN-6:** Journals pueden estar activos o inactivos (active field).
- **RN-7:** RLS filtra journals por company_id.

---

## Tareas Técnicas

### Backend
- [ ] Endpoint: `POST /api/v1/financial/journals`
- [ ] Endpoint: `GET /api/v1/financial/journals` (con filtros: type, active)
- [ ] Endpoint: `GET /api/v1/financial/journals/:id`
- [ ] Endpoint: `PUT /api/v1/financial/journals/:id`
- [ ] Endpoint: `DELETE /api/v1/financial/journals/:id` (soft delete)
- [ ] Service: `JournalService.create/findAll/findOne/update/remove`
- [ ] DTO: `CreateJournalDto` (validaciones @IsEnum para type)
- [ ] DTO: `UpdateJournalDto` (partial)
- [ ] Validar código único por empresa
- [ ] Validar que bank_account_id existe (si journal type=bank)
- [ ] Unit tests (8 test cases)
- [ ] Integration tests (7 test cases)
- [ ] Swagger docs

### Frontend
- [ ] Componente: `JournalsTable.tsx`
- [ ] Componente: `CreateJournalForm.tsx`
- [ ] Componente: `EditJournalForm.tsx`
- [ ] Página: `JournalsPage.tsx` (/financial/journals)
- [ ] Página: `CreateJournalPage.tsx`
- [ ] API client: `journalApi.ts`
- [ ] Store: `useJournalStore.ts`
- [ ] Component tests (5 test cases)
- [ ] E2E test: "should create journal successfully"

### Database
- [ ] Tabla: `financial.journals` (ya existe)
- [ ] Índices: idx_journals_company_id, idx_journals_code, idx_journals_type
- [ ] Constraint: uq_journals_code_company
- [ ] RLS policy: company_isolation_journals

---

## Mockups / Wireframes

**Lista de Journals:**
- Tabla: Código | Nombre | Tipo | Moneda | Estado | Acciones
- Botón: "Nuevo Journal" (primary)
- Filtros: Tipo (dropdown), Estado (Activo/Inactivo)

**Formulario Crear/Editar Journal:**
- Campo: Código (input, required, max 10 chars, uppercase)
- Campo: Nombre (input, required)
- Campo: Tipo (select: Ventas, Compras, Banco, Caja, General)
- Campo: Cuenta Bancaria (select, visible solo si type=bank)
- Campo: Moneda (select, required)
- Campo: Activo (checkbox)

---

## Casos de Prueba

### Funcionales
1. **TC-001:** Crear journal type=sale exitosamente
2. **TC-002:** Error por código duplicado
3. **TC-003:** Listar journals con filtro type=bank
4. **TC-004:** Actualizar nombre de journal
5. **TC-005:** Error al eliminar journal con asientos
6. **TC-006:** Error por type inválido
7. **TC-007:** RLS filtra por empresa

### No Funcionales
1. **Performance:** Response time < 200ms
2. **Seguridad:** JWT + permiso accounting_manager requerido

---

## Dependencias

- **US bloqueantes:**
  - US-MGN-002-001-001 (CRUD Empresas)
  - US-MGN-003-003-001 (Gestión Monedas)
- **Módulos:** MGN-002, MGN-003

---

## Estimación Detallada

| Tarea | Estimación |
|-------|------------|
| Backend | 3 horas |
| Frontend | 3 horas |
| Testing | 2 horas |
| Code Review | 1 hora |
| **TOTAL** | **9 horas = 5 SP** |

---

## Definition of Done

- [ ] Código backend implementado
- [ ] Código frontend implementado
- [ ] Unit tests pasando (>80% cobertura)
- [ ] Integration tests pasando
- [ ] E2E tests pasando
- [ ] Code review aprobado
- [ ] Swagger docs actualizado
- [ ] RLS aplicado
- [ ] Merge a develop
- [ ] QA validado
- [ ] PO aprobado

---

## Referencias

- [RF-MGN-004-002](../../02-modelado/requerimientos-funcionales/mgn-004/RF-MGN-004-002-gestión-de-journals-contables.md)
- [ET-BACKEND-MGN-004-002](../../02-modelado/especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-002-gestión-de-journals-contables.md)
- [ET-FRONTEND-MGN-004-002](../../02-modelado/especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-002-gestión-de-journals-contables.md)
- [TRACEABILITY-MGN-004.yaml](../../02-modelado/trazabilidad/TRACEABILITY-MGN-004.yaml)
- [Financial Schema DDL](../../02-modelado/database-design/schemas/financial-schema-ddl.sql)
