# RF-MGN-002-004: Jerarquías de Empresas (Holdings)

**Módulo:** MGN-002 - Empresas y Organizaciones
**Prioridad:** P1 (Post-MVP)
**Story Points:** 5
**Estado:** Definido
**Fecha:** 2025-11-23

## Descripción

El sistema debe permitir crear jerarquías de empresas (holdings) donde una empresa puede ser padre de otras. Facilita gestión de grupos empresariales y visualización de organigramas.

## Actores

- **Actor Principal:** Administrador de Sistema
- **Actores Secundarios:** Gerente de Grupo (consulta jerarquía)

## Precondiciones

1. Empresas deben estar creadas (RF-MGN-002-001)
2. Usuario debe tener permisos de administración

## Flujo Principal

1. Administrador accede a Gestión de Empresas
2. Administrador crea/edita empresa
3. Administrador selecciona parent_id (empresa padre)
4. Sistema valida que no haya ciclos en jerarquía (A → B → A)
5. Sistema actualiza core.companies.parent_id
6. Sistema calcula nivel jerárquico (parent_path)
7. Jerarquía queda establecida
8. Usuario puede visualizar organigrama de empresas

## Flujos Alternativos

### FA-1: Visualización de Organigrama
1. Usuario accede a módulo de Empresas
2. Usuario selecciona vista "Organigrama"
3. Sistema carga jerarquía de empresas
4. Sistema muestra árbol visual (D3.js o similar)
5. Usuario puede expandir/colapsar nodos
6. Usuario puede hacer clic en empresa para ver detalle

### FA-2: Ciclo Detectado
1. Administrador intenta asignar parent_id que crea ciclo
2. Sistema detecta ciclo: Holding A → Empresa B → Holding A
3. Sistema retorna error 400: "No se permiten ciclos en jerarquías"

### FA-3: Empresas Huérfanas (Sin Padre)
1. Sistema permite empresas sin parent_id (raíz de jerarquía)
2. Empresas huérfanas son holdings independientes

### FA-4: Cambio de Padre
1. Administrador cambia parent_id de empresa
2. Sistema recalcula parent_path de empresa y descendientes
3. Jerarquía se actualiza automáticamente

## Reglas de Negocio

- **RN-1:** Empresa puede tener un solo parent_id (padre)
- **RN-2:** Empresa puede tener múltiples hijos
- **RN-3:** No se permiten ciclos en jerarquías (validación estricta)
- **RN-4:** Empresas sin parent_id son raíz de jerarquía
- **RN-5:** parent_path almacena ruta completa (ej: "1/5/12" = niveles)
- **RN-6:** Profundidad máxima recomendada: 5 niveles

## Criterios de Aceptación

- [ ] Administrador puede asignar parent_id a empresas
- [ ] Sistema valida que no haya ciclos en jerarquías
- [ ] Sistema calcula parent_path automáticamente
- [ ] Usuario puede visualizar organigrama de empresas
- [ ] Organigrama muestra jerarquía completa con niveles
- [ ] Cambio de padre recalcula rutas automáticamente
- [ ] Empresas huérfanas (sin padre) son permitidas

## Entidades Involucradas

- **Principales:**
  - core.companies (parent_id, parent_path, level)
- **Relacionadas:**
  - Ninguna (funcionalidad interna de empresas)

## Referencias

- [ALCANCE-POR-MODULO.md - MGN-002](../../01-definicion-modulos/ALCANCE-POR-MODULO.md#mgn-002-empresas-y-organizaciones)
- [Core Schema DDL](../database-design/schemas/core-schema-ddl.sql)
- [Gap Analysis MGN-002](../../01-definicion-modulos/gaps/GAP-ANALYSIS-MGN-002.md)

## Notas Técnicas

- **parent_path:** Materialized path pattern (ej: "1/5/12/34")
- **Validación Ciclos:**
  ```sql
  WITH RECURSIVE hierarchy AS (
    SELECT id, parent_id, ARRAY[id] AS path
    FROM core.companies
    WHERE id = NEW.id
    UNION ALL
    SELECT c.id, c.parent_id, h.path || c.id
    FROM core.companies c
    JOIN hierarchy h ON c.id = h.parent_id
    WHERE NOT (c.id = ANY(h.path)) -- Detectar ciclo
  )
  SELECT * FROM hierarchy;
  ```
- **Visualización:** D3.js tree layout o React Flow
- **Backend:** NestJS CompaniesService.validateHierarchy()
- **Performance:** Índice en parent_id y parent_path

## Dependencias

- **RF Dependientes:** RF-MGN-002-001 (Gestión de Empresas)
- **Bloqueante para:** Ninguno (funcionalidad opcional)
