# 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)