Plataforma técnica · Orchestrator
Cargo Service
Remuneraciones Cargos Catalogo
CargoService administra el catálogo de cargos del tenant. Es deliberadamente delgado: las decisiones contables (banda salarial, jerarquía, cuenta de gasto asociada) se materializan al asociar el cargo al contrato, no acá. Este service sólo mantiene el catálogo coherente.
El cargo aporta tres controles al ciclo de remuneraciones: clasificación funcional para reportería, banda salarial referencial para detectar desviaciones, y nivel jerárquico para flujos de aprobación.
Ubicación
Section titled “Ubicación”Directoryorchestrator/src/domain/cargos/
- CargoService.ts
- CargoRepository.ts
Tabla: remuneraciones.cargos.
API pública
Section titled “API pública”| Método | Firma | Resultado |
|---|---|---|
findAll | (ctx) => Promise<Cargo[]> | Catálogo ordenado por nivel_jerarquico, nombre. Cap a 500 filas. |
findById | (ctx, id) => Promise<Cargo | null> | Cargo completo o null. |
create | (ctx, data: Cargo) => Promise<ServiceResult<string>> | Inserta y devuelve el id generado. |
update | (ctx, id, data: Partial<Cargo>) => Promise<ServiceResult<number>> | Filas afectadas; lanza Error("Cargo no encontrado") si 0. |
delete | (ctx, id) => Promise<ServiceResult<number>> | Filas borradas; lanza Error("Cargo no encontrado") si 0. |
interface Cargo { id?: string; codigo: string; // único, normalizado uppercase + trim nombre: string; // trim descripcion?: string; nivel_jerarquico?: number; // default 1 salario_minimo?: number; // default 0 salario_maximo?: number; // default 0 requiere_titulo_profesional?: boolean; // default false requiere_experiencia_anos?: number; // default 0 activo?: boolean; // default true}Validaciones y normalización
Section titled “Validaciones y normalización”| Campo | Regla |
|---|---|
codigo, nombre | Obligatorios. validateRequired los exige. |
codigo | Se transforma a data.codigo.toUpperCase().trim() antes de persistir → garantiza unicidad case-insensitive. |
nombre | Se transforma a data.nombre.trim(). |
| Defaults | El repository completa nivel_jerarquico=1, salario_minimo=0, salario_maximo=0, requiere_titulo_profesional=false, requiere_experiencia_anos=0, activo=true cuando vienen null/undefined. |
Update parcial
Section titled “Update parcial”El repository filtra el payload antes de armar el UPDATE:
const dataToUpdate = Object.fromEntries( Object.entries(data).filter(([key, value]) => key !== "id" && key !== "created_by" && key !== "created_at" && key !== "updated_by" && key !== "updated_at" && value !== undefined && value !== null ));Si después del filtrado no quedan campos, ejecuta sólo SET updated_by = $2, updated_at = NOW() — útil para “tocar” el cargo y refrescar trazabilidad.
Errores
Section titled “Errores”| Origen | Mensaje | Cuándo |
|---|---|---|
| Validación previa | "<Campo> es requerido" (de validateRequired) | Crear sin codigo o sin nombre. |
| Service | "Cargo no encontrado" | update o delete con id que no afecta filas. |
| Base de datos | unique_violation (23505) | codigo duplicado tras normalización. |
| Base de datos | foreign_key_violation (23503) | delete con contratos vigentes que referencian el cargo. |
Flujo de escritura
Section titled “Flujo de escritura”-
Endpoint llama a
CargoService.create(ctx, data). -
validateRequiredconfirmacodigoynombre. -
Service normaliza:
codigo.toUpperCase().trim()ynombre.trim(). -
CargoRepository.create(pool, normalized, userId)inserta conbuildInsertyRETURNING id. -
Devuelve
ServiceResult<string>con elidrecién creado.
Consumidores
Section titled “Consumidores”| Service / Vista | Cómo consume |
|---|---|
ContractService | cargo_id opcional en el contrato; valida que exista al persistir. |
v_empleados_activos | Join contra cargos para exponer cargo_nombre y nivel_jerarquico al frontend. |
PayrollService | No consume cargo directamente; lo recibe vía contrato cuando arma contexto. |