# US-MGN-004-001-002: Jerarquía y Vista Árbol de Cuentas Contables

**RF Asociado:** [RF-MGN-004-001](../../02-modelado/requerimientos-funcionales/mgn-004/RF-MGN-004-001-gestión-de-plan-de-cuentas.md)
**Módulo:** MGN-004 - Financiero Básico
**Epic:** Plan de Cuentas
**Prioridad:** P0 (MVP)
**Story Points:** 3
**Sprint:** Sprint 7
**Estado:** Ready for Development
**Fecha:** 2025-11-24

---

## User Story

**Como** contador de la empresa,
**Quiero** organizar las cuentas contables en una estructura jerárquica (árbol),
**Para** agrupar las cuentas por categorías y subcategorías y visualizarlas de forma organizada.

---

## Descripción Detallada

Esta user story implementa la funcionalidad de jerarquía de cuentas contables mediante el uso del campo `parent_id`. Permite:
- Crear cuentas con cuentas padre (subcuentas)
- Visualizar el plan de cuentas como árbol jerárquico
- Calcular niveles de profundidad (nivel 0 = cuenta raíz, nivel 1 = hijos directos, etc.)
- Navegar por la jerarquía (expandir/colapsar nodos)

Ejemplo de jerarquía:
```
1 - Activos (parent_id: null)
  1.1 - Activos Corrientes (parent_id: 1)
    1.1.01 - Efectivo y Equivalentes (parent_id: 1.1)
      1.1.01.001 - Caja General (parent_id: 1.1.01)
      1.1.01.002 - Banco Santander (parent_id: 1.1.01)
```

---

## Criterios de Aceptación

### Escenario 1: Crear cuenta con cuenta padre
**Dado que** tengo una cuenta padre "1.1 Activos Corrientes" con id=10,
**Cuando** creo una cuenta "1.1.01 Efectivo" con parent_id=10,
**Entonces** el sistema crea la cuenta y establece la relación jerárquica correctamente.

### Escenario 2: Obtener árbol jerárquico de cuentas
**Dado que** tengo cuentas con jerarquía definida,
**Cuando** solicito GET /api/v1/financial/accounts/tree,
**Entonces** el sistema retorna un JSON con estructura de árbol incluyendo hijos (children array).

### Escenario 3: Validar que parent_id existe
**Dado que** intento crear una cuenta con parent_id=999 (no existe),
**Cuando** envío el request,
**Entonces** el sistema retorna error 400 "Cuenta padre no encontrada".

### Escenario 4: Prevenir ciclos en jerarquía
**Dado que** tengo cuenta A (id=1) con parent_id=null,
**Cuando** intento actualizar cuenta A con parent_id=1 (a sí misma),
**Entonces** el sistema retorna error 400 "Una cuenta no puede ser su propia cuenta padre".

### Escenario 5: Calcular nivel jerárquico
**Dado que** tengo una cuenta con 3 niveles de padres,
**Cuando** consulto el endpoint GET /api/v1/financial/accounts/:id?include=hierarchy_level,
**Entonces** el sistema retorna hierarchy_level=3.

---

## Reglas de Negocio

- **RN-1:** Una cuenta puede tener parent_id (opcional). Si parent_id=null, es cuenta raíz.
- **RN-2:** parent_id debe existir en la tabla accounts y pertenecer a la misma empresa.
- **RN-3:** Una cuenta no puede ser su propia cuenta padre (prevenir ciclos directos).
- **RN-4:** No se permiten ciclos indirectos (A → B → C → A). Validar recursivamente.
- **RN-5:** Nivel jerárquico se calcula recursivamente: nivel_padre + 1. Máximo 10 niveles.
- **RN-6:** Al eliminar (soft delete) una cuenta padre, las cuentas hijas NO se eliminan automáticamente.

---

## Tareas Técnicas (Checklist de Implementación)

### Backend
- [ ] Endpoint: `GET /api/v1/financial/accounts/tree` (retorna estructura jerárquica)
- [ ] Endpoint: `GET /api/v1/financial/accounts/:id/children` (hijos directos)
- [ ] Endpoint: `GET /api/v1/financial/accounts/:id/ancestors` (padres hasta la raíz)
- [ ] Service método: `AccountService.getTree()` (construye árbol con children)
- [ ] Service método: `AccountService.getChildren(parentId)`
- [ ] Service método: `AccountService.getAncestors(accountId)`
- [ ] Service método: `AccountService.validateParent(parentId)` (existe y no crea ciclos)
- [ ] Service método: `AccountService.calculateLevel(accountId)` (recursivo)
- [ ] Validación: Prevenir ciclos directos e indirectos
- [ ] Unit tests: Jerarquía (6 test cases)
- [ ] Integration tests: Tree endpoints (5 test cases)
- [ ] Swagger docs para endpoints de jerarquía

### Frontend
- [ ] Componente: `AccountTree.tsx` (vista árbol con expandir/colapsar)
- [ ] Componente: `AccountNode.tsx` (nodo individual del árbol)
- [ ] Componente: `AccountHierarchyBreadcrumb.tsx` (breadcrumb de jerarquía)
- [ ] Hook: `useAccountTree.ts` (manejo de estado del árbol)
- [ ] Función: `buildTree(flatAccounts)` (convierte array plano a árbol)
- [ ] Icono: Expandir/Colapsar nodos (chevron-right / chevron-down)
- [ ] Indentación visual por nivel (padding-left: nivel * 20px)
- [ ] Component tests: AccountTree.test.tsx (5 test cases)
- [ ] E2E test: "should expand and collapse account tree nodes"

### Database
- [ ] Validar foreign key: `accounts.parent_id → accounts.id`
- [ ] Índice: `idx_accounts_parent_id` (ya existe)
- [ ] Query recursivo: Common Table Expression (CTE) para calcular niveles
- [ ] Seed data: Plan de cuentas jerárquico de ejemplo (3 niveles)

---

## Mockups / Wireframes

**Vista Árbol de Plan de Cuentas:**
```
📂 1 - Activos                                [Editar] [+]
  📂 1.1 - Activos Corrientes                [Editar] [+]
    📂 1.1.01 - Efectivo y Equivalentes      [Editar] [+]
      📄 1.1.01.001 - Caja General           [Editar] [×]
      📄 1.1.01.002 - Banco Santander        [Editar] [×]
    📂 1.1.02 - Cuentas por Cobrar           [Editar] [+]
📂 2 - Pasivos                               [Editar] [+]
  📂 2.1 - Pasivos Corrientes                [Editar] [+]
```

**Interacciones:**
- Click en icono 📂 / 📄 : Expandir/colapsar nodos
- Click en [+]: Crear subcuenta
- Click en nombre: Ver detalle de cuenta
- Hover: Resaltar nodo completo

---

## Casos de Prueba (Test Scenarios)

### Pruebas Funcionales
1. **TC-001: Crear cuenta con parent_id válido**
   - Input: parent_id=10 (existe)
   - Expected: Status 201, cuenta creada con parent_id=10

2. **TC-002: Error por parent_id inexistente**
   - Input: parent_id=999
   - Expected: Status 400, error "Cuenta padre no encontrada"

3. **TC-003: Prevenir ciclo directo (A → A)**
   - Input: id=1, parent_id=1
   - Expected: Status 400, error "Cuenta no puede ser su propia padre"

4. **TC-004: Prevenir ciclo indirecto (A → B → A)**
   - Input: Cuenta B (parent_id=A) luego actualizar A (parent_id=B)
   - Expected: Status 400, error "Ciclo detectado en jerarquía"

5. **TC-005: Obtener árbol jerárquico**
   - Input: GET /accounts/tree
   - Expected: JSON con structure { id, code, name, children: [...] }

6. **TC-006: Calcular nivel jerárquico correcto**
   - Input: Cuenta con 3 niveles de padres
   - Expected: hierarchy_level=3

### Pruebas No Funcionales
1. **Performance:** GET /accounts/tree < 500ms (hasta 1000 cuentas)
2. **Usabilidad:** Árbol carga niveles lazy (cargar hijos al expandir)

---

## Dependencias

- **US bloqueantes:**
  - US-MGN-004-001-001 (CRUD de Cuentas) - Requerido para crear cuentas base
- **Módulos requeridos:** MGN-004

---

## Notas de Implementación

- Usar Common Table Expressions (CTE) recursivos para calcular niveles y ancestros:
```sql
WITH RECURSIVE account_hierarchy AS (
  SELECT id, parent_id, code, name, 0 as level
  FROM financial.accounts
  WHERE parent_id IS NULL
  UNION ALL
  SELECT a.id, a.parent_id, a.code, a.name, ah.level + 1
  FROM financial.accounts a
  JOIN account_hierarchy ah ON a.parent_id = ah.id
)
SELECT * FROM account_hierarchy ORDER BY code;
```
- Validación de ciclos: Función recursiva que recorre padres hasta root o detecta ciclo
- Frontend: Usar `react-arborist` o `react-complex-tree` para vista árbol avanzada
- Cache: Cachear árbol completo en Redis (TTL 10 minutos) para evitar recalcular

---

## Estimación Detallada

| Tarea | Estimación |
|-------|------------|
| Backend Development | 2 horas |
| Frontend Development (Tree Component) | 2 horas |
| Testing | 1.5 horas |
| Code Review | 0.5 hora |
| **TOTAL** | **6 horas** |

**Equivalente:** 3 Story Points

---

## Definition of Done (DoD)

- [ ] Código backend implementado (tree endpoints + validación ciclos)
- [ ] Código frontend implementado (AccountTree component)
- [ ] Unit tests escritos y pasando (cobertura > 80%)
- [ ] Integration tests pasando
- [ ] E2E test pasando (expand/collapse tree)
- [ ] Code review aprobado
- [ ] Documentación Swagger actualizada
- [ ] RLS aplicado
- [ ] Merge a develop
- [ ] QA manual completado
- [ ] PO aprobado

---

## Referencias

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