6.7 KiB
US-MGN-004-002-001: CRUD de Journals Contables
RF Asociado: RF-MGN-004-002 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
- TC-001: Crear journal type=sale exitosamente
- TC-002: Error por código duplicado
- TC-003: Listar journals con filtro type=bank
- TC-004: Actualizar nombre de journal
- TC-005: Error al eliminar journal con asientos
- TC-006: Error por type inválido
- TC-007: RLS filtra por empresa
No Funcionales
- Performance: Response time < 200ms
- 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