ET-HR-BACKEND - Especificacion Tecnica Backend HR
METADATOS
| Campo |
Valor |
| Modulo |
MGN-014 |
| Nombre |
Human Resources (HR) |
| Version |
1.0.0 |
| Fecha |
2026-01-10 |
| Ubicacion |
backend/src/modules/hr/ |
| Schema BD |
hr |
| Estado |
Implementado |
SERVICIOS
Resumen de Servicios (7)
| # |
Servicio |
Archivo |
Descripcion |
| 1 |
EmployeesService |
employees.service.ts |
Gestion de empleados |
| 2 |
DepartmentsService |
departments.service.ts |
Departamentos y puestos |
| 3 |
ContractsService |
contracts.service.ts |
Contratos laborales |
| 4 |
LeavesService |
leaves.service.ts |
Ausencias y vacaciones |
| 5 |
SkillsService |
skills.service.ts |
Competencias y habilidades |
| 6 |
ExpensesService |
expenses.service.ts |
Gastos de empleados |
| 7 |
PayslipsService |
payslips.service.ts |
Nominas y recibos |
1. EmployeesService
Archivo: employees.service.ts
Metodos
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: EmployeeFilters |
Promise<{ data: Employee[]; total: number }> |
Lista empleados con paginacion y filtros |
findById |
id: string, tenantId: string |
Promise<Employee> |
Obtiene empleado por ID |
create |
dto: CreateEmployeeDto, tenantId: string, userId: string |
Promise<Employee> |
Crea nuevo empleado |
update |
id: string, dto: UpdateEmployeeDto, tenantId: string, userId: string |
Promise<Employee> |
Actualiza empleado |
terminate |
id: string, terminationDate: string, tenantId: string, userId: string |
Promise<Employee> |
Da de baja empleado |
reactivate |
id: string, tenantId: string, userId: string |
Promise<Employee> |
Reactiva empleado |
delete |
id: string, tenantId: string |
Promise<void> |
Elimina empleado |
getSubordinates |
id: string, tenantId: string |
Promise<Employee[]> |
Obtiene subordinados |
Reglas de Negocio
- El
employee_number debe ser unico por tenant
- No se puede eliminar un empleado con contratos asociados
- No se puede eliminar un empleado que es manager de otros
- Al terminar un empleado, se terminan sus contratos activos
2. DepartmentsService
Archivo: departments.service.ts
Metodos - Departamentos
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: DepartmentFilters |
Promise<{ data: Department[]; total: number }> |
Lista departamentos |
findById |
id: string, tenantId: string |
Promise<Department> |
Obtiene departamento por ID |
create |
dto: CreateDepartmentDto, tenantId: string, userId: string |
Promise<Department> |
Crea departamento |
update |
id: string, dto: UpdateDepartmentDto, tenantId: string |
Promise<Department> |
Actualiza departamento |
delete |
id: string, tenantId: string |
Promise<void> |
Elimina departamento |
Metodos - Puestos de Trabajo
| Metodo |
Parametros |
Retorno |
Descripcion |
getJobPositions |
tenantId: string, includeInactive?: boolean |
Promise<JobPosition[]> |
Lista puestos de trabajo |
getJobPositionById |
id: string, tenantId: string |
Promise<JobPosition> |
Obtiene puesto por ID |
createJobPosition |
dto: CreateJobPositionDto, tenantId: string |
Promise<JobPosition> |
Crea puesto |
updateJobPosition |
id: string, dto: UpdateJobPositionDto, tenantId: string |
Promise<JobPosition> |
Actualiza puesto |
deleteJobPosition |
id: string, tenantId: string |
Promise<void> |
Elimina puesto |
Reglas de Negocio
- El nombre del departamento debe ser unico por empresa
- No se puede eliminar un departamento con empleados
- No se puede eliminar un departamento con subdepartamentos
- El nombre del puesto debe ser unico por tenant
3. ContractsService
Archivo: contracts.service.ts
Metodos
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: ContractFilters |
Promise<{ data: Contract[]; total: number }> |
Lista contratos |
findById |
id: string, tenantId: string |
Promise<Contract> |
Obtiene contrato por ID |
create |
dto: CreateContractDto, tenantId: string, userId: string |
Promise<Contract> |
Crea contrato |
update |
id: string, dto: UpdateContractDto, tenantId: string, userId: string |
Promise<Contract> |
Actualiza contrato |
activate |
id: string, tenantId: string, userId: string |
Promise<Contract> |
Activa contrato |
terminate |
id: string, terminationDate: string, tenantId: string, userId: string |
Promise<Contract> |
Termina contrato |
cancel |
id: string, tenantId: string, userId: string |
Promise<Contract> |
Cancela contrato |
delete |
id: string, tenantId: string |
Promise<void> |
Elimina contrato |
Flujo de Estados
draft -> active -> expired/terminated
draft -> cancelled
Reglas de Negocio
- Un empleado solo puede tener un contrato activo
- Solo se pueden editar contratos en estado
draft
- Solo se pueden eliminar contratos en
draft o cancelled
- Al activar, actualiza el departamento y puesto del empleado
4. LeavesService
Archivo: leaves.service.ts
Metodos - Tipos de Ausencia
| Metodo |
Parametros |
Retorno |
Descripcion |
getLeaveTypes |
tenantId: string, includeInactive?: boolean |
Promise<LeaveTypeConfig[]> |
Lista tipos de ausencia |
getLeaveTypeById |
id: string, tenantId: string |
Promise<LeaveTypeConfig> |
Obtiene tipo por ID |
createLeaveType |
dto: CreateLeaveTypeDto, tenantId: string |
Promise<LeaveTypeConfig> |
Crea tipo de ausencia |
updateLeaveType |
id: string, dto: UpdateLeaveTypeDto, tenantId: string |
Promise<LeaveTypeConfig> |
Actualiza tipo |
deleteLeaveType |
id: string, tenantId: string |
Promise<void> |
Elimina tipo |
Metodos - Ausencias
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: LeaveFilters |
Promise<{ data: Leave[]; total: number }> |
Lista ausencias |
findById |
id: string, tenantId: string |
Promise<Leave> |
Obtiene ausencia por ID |
create |
dto: CreateLeaveDto, tenantId: string, userId: string |
Promise<Leave> |
Crea ausencia |
update |
id: string, dto: UpdateLeaveDto, tenantId: string, userId: string |
Promise<Leave> |
Actualiza ausencia |
submit |
id: string, tenantId: string, userId: string |
Promise<Leave> |
Envia solicitud |
approve |
id: string, tenantId: string, userId: string |
Promise<Leave> |
Aprueba solicitud |
reject |
id: string, reason: string, tenantId: string, userId: string |
Promise<Leave> |
Rechaza solicitud |
cancel |
id: string, tenantId: string, userId: string |
Promise<Leave> |
Cancela solicitud |
delete |
id: string, tenantId: string |
Promise<void> |
Elimina ausencia |
Flujo de Estados
draft -> submitted -> approved
-> rejected
draft/submitted/approved -> cancelled
Reglas de Negocio
- Se calcula automaticamente el numero de dias
- No se permiten ausencias solapadas
- Se respeta el maximo de dias por tipo
- Al aprobar, se actualiza el estado del empleado si corresponde
5. SkillsService
Archivo: skills.service.ts
Metodos - Tipos de Habilidad
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllSkillTypes |
tenantId: string, filters: SkillTypeFilters |
Promise<{ data: SkillType[]; total: number; page: number; limit: number }> |
Lista tipos |
findSkillTypeById |
id: string, tenantId: string |
Promise<SkillType | null> |
Obtiene tipo por ID |
createSkillType |
tenantId: string, dto: CreateSkillTypeDto |
Promise<SkillType> |
Crea tipo |
updateSkillType |
id: string, tenantId: string, dto: UpdateSkillTypeDto |
Promise<SkillType | null> |
Actualiza tipo |
deleteSkillType |
id: string, tenantId: string |
Promise<boolean> |
Elimina tipo |
Metodos - Habilidades
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllSkills |
tenantId: string, filters: SkillFilters |
Promise<{ data: Skill[]; total: number; page: number; limit: number }> |
Lista habilidades |
findSkillById |
id: string, tenantId: string |
Promise<Skill | null> |
Obtiene habilidad por ID |
createSkill |
tenantId: string, dto: CreateSkillDto |
Promise<Skill> |
Crea habilidad |
updateSkill |
id: string, tenantId: string, dto: UpdateSkillDto |
Promise<Skill | null> |
Actualiza habilidad |
deleteSkill |
id: string, tenantId: string |
Promise<boolean> |
Elimina habilidad |
Metodos - Niveles de Habilidad
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllSkillLevels |
tenantId: string, filters: SkillLevelFilters |
Promise<{ data: SkillLevel[]; total: number; page: number; limit: number }> |
Lista niveles |
findSkillLevelById |
id: string, tenantId: string |
Promise<SkillLevel | null> |
Obtiene nivel por ID |
createSkillLevel |
tenantId: string, dto: CreateSkillLevelDto |
Promise<SkillLevel> |
Crea nivel |
updateSkillLevel |
id: string, tenantId: string, dto: UpdateSkillLevelDto |
Promise<SkillLevel | null> |
Actualiza nivel |
deleteSkillLevel |
id: string, tenantId: string |
Promise<boolean> |
Elimina nivel |
Metodos - Habilidades de Empleado
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllEmployeeSkills |
tenantId: string, filters: EmployeeSkillFilters |
Promise<{ data: EmployeeSkill[]; total: number; page: number; limit: number }> |
Lista habilidades de empleados |
findEmployeeSkillById |
id: string, tenantId: string |
Promise<EmployeeSkill | null> |
Obtiene por ID |
createEmployeeSkill |
tenantId: string, dto: CreateEmployeeSkillDto |
Promise<EmployeeSkill> |
Asigna habilidad |
updateEmployeeSkill |
id: string, tenantId: string, dto: UpdateEmployeeSkillDto |
Promise<EmployeeSkill | null> |
Actualiza asignacion |
deleteEmployeeSkill |
id: string, tenantId: string |
Promise<boolean> |
Elimina asignacion |
getSkillsByEmployee |
employeeId: string, tenantId: string |
Promise<EmployeeSkill[]> |
Obtiene habilidades de un empleado |
6. ExpensesService
Archivo: expenses.service.ts
Metodos - Hojas de Gastos
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllSheets |
tenantId: string, filters: ExpenseSheetFilters |
Promise<{ data: ExpenseSheet[]; total: number; page: number; limit: number }> |
Lista hojas |
findSheetById |
id: string, tenantId: string |
Promise<ExpenseSheet | null> |
Obtiene hoja por ID |
createSheet |
tenantId: string, dto: CreateExpenseSheetDto, userId?: string |
Promise<ExpenseSheet> |
Crea hoja |
updateSheet |
id: string, tenantId: string, dto: UpdateExpenseSheetDto |
Promise<ExpenseSheet | null> |
Actualiza hoja |
submitSheet |
id: string, tenantId: string |
Promise<ExpenseSheet | null> |
Envia hoja |
approveSheet |
id: string, tenantId: string, approvedBy: string |
Promise<ExpenseSheet | null> |
Aprueba hoja |
rejectSheet |
id: string, tenantId: string |
Promise<ExpenseSheet | null> |
Rechaza hoja |
deleteSheet |
id: string, tenantId: string |
Promise<boolean> |
Elimina hoja |
Metodos - Gastos
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllExpenses |
tenantId: string, filters: ExpenseFilters |
Promise<{ data: Expense[]; total: number; page: number; limit: number }> |
Lista gastos |
findExpenseById |
id: string, tenantId: string |
Promise<Expense | null> |
Obtiene gasto por ID |
createExpense |
tenantId: string, dto: CreateExpenseDto, userId?: string |
Promise<Expense> |
Crea gasto |
updateExpense |
id: string, tenantId: string, dto: UpdateExpenseDto |
Promise<Expense | null> |
Actualiza gasto |
deleteExpense |
id: string, tenantId: string |
Promise<boolean> |
Elimina gasto |
recalculateSheetTotals |
sheetId: string, tenantId: string |
Promise<void> |
Recalcula totales |
Flujo de Estados
draft -> submitted -> approved -> posted -> paid
-> rejected
Reglas de Negocio
- Solo se pueden modificar/eliminar gastos en
draft
total_amount se calcula como unit_amount * quantity
- Los totales de la hoja se recalculan automaticamente
7. PayslipsService
Archivo: payslips.service.ts
Metodos - Estructuras de Nomina
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllStructures |
tenantId: string, filters: PayslipStructureFilters |
Promise<{ data: PayslipStructure[]; total: number; page: number; limit: number }> |
Lista estructuras |
findStructureById |
id: string, tenantId: string |
Promise<PayslipStructure | null> |
Obtiene estructura por ID |
createStructure |
tenantId: string, dto: CreatePayslipStructureDto |
Promise<PayslipStructure> |
Crea estructura |
updateStructure |
id: string, tenantId: string, dto: UpdatePayslipStructureDto |
Promise<PayslipStructure | null> |
Actualiza estructura |
deleteStructure |
id: string, tenantId: string |
Promise<boolean> |
Elimina estructura |
Metodos - Nominas
| Metodo |
Parametros |
Retorno |
Descripcion |
findAllPayslips |
tenantId: string, filters: PayslipFilters |
Promise<{ data: Payslip[]; total: number; page: number; limit: number }> |
Lista nominas |
findPayslipById |
id: string, tenantId: string |
Promise<Payslip | null> |
Obtiene nomina por ID |
createPayslip |
tenantId: string, dto: CreatePayslipDto, userId?: string |
Promise<Payslip> |
Crea nomina |
updatePayslip |
id: string, tenantId: string, dto: UpdatePayslipDto |
Promise<Payslip | null> |
Actualiza nomina |
verifyPayslip |
id: string, tenantId: string |
Promise<Payslip | null> |
Verifica nomina |
confirmPayslip |
id: string, tenantId: string |
Promise<Payslip | null> |
Confirma nomina |
cancelPayslip |
id: string, tenantId: string |
Promise<Payslip | null> |
Cancela nomina |
deletePayslip |
id: string, tenantId: string |
Promise<boolean> |
Elimina nomina |
Metodos - Lineas de Nomina
| Metodo |
Parametros |
Retorno |
Descripcion |
getPayslipLines |
payslipId: string, tenantId: string |
Promise<PayslipLine[]> |
Obtiene lineas |
addPayslipLine |
payslipId: string, tenantId: string, dto: CreatePayslipLineDto |
Promise<PayslipLine | null> |
Agrega linea |
updatePayslipLine |
payslipId: string, lineId: string, tenantId: string, dto: UpdatePayslipLineDto |
Promise<PayslipLine | null> |
Actualiza linea |
removePayslipLine |
payslipId: string, lineId: string, tenantId: string |
Promise<boolean> |
Elimina linea |
Flujo de Estados
draft -> verify -> done
draft/verify -> cancel
Reglas de Negocio
- Solo se pueden modificar nominas en
draft
- Solo se pueden eliminar nominas en
draft o cancel
- Los totales se recalculan al modificar lineas
- El numero de nomina se genera al confirmar
ENTIDADES
Employee
interface Employee {
id: string;
tenant_id: string;
company_id: string;
company_name?: string;
employee_number: string;
first_name: string;
last_name: string;
middle_name?: string;
full_name?: string;
user_id?: string;
birth_date?: Date;
gender?: string;
marital_status?: string;
nationality?: string;
identification_id?: string;
identification_type?: string;
social_security_number?: string;
tax_id?: string;
email?: string;
work_email?: string;
phone?: string;
work_phone?: string;
mobile?: string;
emergency_contact?: string;
emergency_phone?: string;
street?: string;
city?: string;
state?: string;
zip?: string;
country?: string;
department_id?: string;
department_name?: string;
job_position_id?: string;
job_position_name?: string;
manager_id?: string;
manager_name?: string;
hire_date: Date;
termination_date?: Date;
status: EmployeeStatus;
bank_name?: string;
bank_account?: string;
bank_clabe?: string;
photo_url?: string;
notes?: string;
created_at: Date;
}
type EmployeeStatus = 'active' | 'inactive' | 'on_leave' | 'terminated';
Department
interface Department {
id: string;
tenant_id: string;
company_id: string;
company_name?: string;
name: string;
code?: string;
parent_id?: string;
parent_name?: string;
manager_id?: string;
manager_name?: string;
description?: string;
color?: string;
active: boolean;
employee_count?: number;
created_at: Date;
}
JobPosition
interface JobPosition {
id: string;
tenant_id: string;
name: string;
department_id?: string;
department_name?: string;
description?: string;
requirements?: string;
responsibilities?: string;
min_salary?: number;
max_salary?: number;
active: boolean;
employee_count?: number;
created_at: Date;
}
Contract
interface Contract {
id: string;
tenant_id: string;
company_id: string;
company_name?: string;
employee_id: string;
employee_name?: string;
employee_number?: string;
name: string;
reference?: string;
contract_type: ContractType;
status: ContractStatus;
job_position_id?: string;
job_position_name?: string;
department_id?: string;
department_name?: string;
date_start: Date;
date_end?: Date;
trial_date_end?: Date;
wage: number;
wage_type: string;
currency_id?: string;
currency_code?: string;
hours_per_week: number;
vacation_days: number;
christmas_bonus_days: number;
document_url?: string;
notes?: string;
created_at: Date;
}
type ContractStatus = 'draft' | 'active' | 'expired' | 'terminated' | 'cancelled';
type ContractType = 'permanent' | 'temporary' | 'contractor' | 'internship' | 'part_time';
Leave
interface Leave {
id: string;
tenant_id: string;
company_id: string;
company_name?: string;
employee_id: string;
employee_name?: string;
employee_number?: string;
leave_type_id: string;
leave_type_name?: string;
name?: string;
date_from: Date;
date_to: Date;
number_of_days: number;
status: LeaveStatus;
description?: string;
approved_by?: string;
approved_by_name?: string;
approved_at?: Date;
rejection_reason?: string;
created_at: Date;
}
type LeaveStatus = 'draft' | 'submitted' | 'approved' | 'rejected' | 'cancelled';
type LeaveType = 'vacation' | 'sick' | 'personal' | 'maternity' | 'paternity' | 'bereavement' | 'unpaid' | 'other';
LeaveTypeConfig
interface LeaveTypeConfig {
id: string;
tenant_id: string;
name: string;
code?: string;
leave_type: LeaveType;
requires_approval: boolean;
max_days?: number;
is_paid: boolean;
color?: string;
active: boolean;
created_at: Date;
}
Skill, SkillType, SkillLevel, EmployeeSkill
interface SkillType {
id: string;
tenant_id: string;
name: string;
skill_levels: string;
created_at: Date;
}
interface Skill {
id: string;
tenant_id: string;
skill_type_id: string;
skill_type_name?: string;
name: string;
created_at: Date;
}
interface SkillLevel {
id: string;
tenant_id: string;
skill_type_id: string;
skill_type_name?: string;
name: string;
level: number;
created_at: Date;
}
interface EmployeeSkill {
id: string;
employee_id: string;
employee_name?: string;
skill_id: string;
skill_name?: string;
skill_level_id?: string;
skill_level_name?: string;
skill_type_id?: string;
skill_type_name?: string;
created_at: Date;
}
ExpenseSheet, Expense
interface ExpenseSheet {
id: string;
tenant_id: string;
company_id: string;
employee_id: string;
employee_name?: string;
name: string;
state: ExpenseStatus;
total_amount: number;
untaxed_amount: number;
total_amount_taxes: number;
journal_id?: string;
account_move_id?: string;
user_id?: string;
user_name?: string;
approved_by?: string;
approved_by_name?: string;
approved_date?: Date;
accounting_date?: Date;
created_at: Date;
created_by?: string;
updated_at?: Date;
}
interface Expense {
id: string;
tenant_id: string;
company_id: string;
employee_id: string;
employee_name?: string;
name: string;
sheet_id?: string;
sheet_name?: string;
product_id?: string;
product_name?: string;
unit_amount: number;
quantity: number;
total_amount: number;
untaxed_amount?: number;
total_amount_taxes?: number;
currency_id?: string;
currency_code?: string;
tax_ids?: string[];
date: Date;
description?: string;
reference?: string;
analytic_account_id?: string;
analytic_account_name?: string;
state: ExpenseStatus;
payment_mode: string;
created_at: Date;
created_by?: string;
updated_at?: Date;
}
type ExpenseStatus = 'draft' | 'submitted' | 'approved' | 'posted' | 'paid' | 'rejected';
Payslip, PayslipStructure, PayslipLine
interface PayslipStructure {
id: string;
tenant_id: string;
name: string;
code?: string;
is_active: boolean;
note?: string;
created_at: Date;
}
interface Payslip {
id: string;
tenant_id: string;
company_id: string;
employee_id: string;
employee_name?: string;
employee_number?: string;
contract_id?: string;
contract_name?: string;
name: string;
number?: string;
state: PayslipStatus;
date_from: Date;
date_to: Date;
date?: Date;
structure_id?: string;
structure_name?: string;
basic_wage?: number;
gross_wage?: number;
net_wage?: number;
worked_days?: number;
worked_hours?: number;
journal_id?: string;
move_id?: string;
created_at: Date;
created_by?: string;
updated_at?: Date;
}
interface PayslipLine {
id: string;
payslip_id: string;
name: string;
code: string;
sequence: number;
category?: string;
quantity: number;
rate: number;
amount: number;
total: number;
appears_on_payslip: boolean;
created_at: Date;
}
type PayslipStatus = 'draft' | 'verify' | 'done' | 'cancel';
DTOs
Employees DTOs
interface CreateEmployeeDto {
company_id: string;
employee_number: string;
first_name: string;
last_name: string;
middle_name?: string;
user_id?: string;
birth_date?: string;
gender?: string;
marital_status?: string;
nationality?: string;
identification_id?: string;
identification_type?: string;
social_security_number?: string;
tax_id?: string;
email?: string;
work_email?: string;
phone?: string;
work_phone?: string;
mobile?: string;
emergency_contact?: string;
emergency_phone?: string;
street?: string;
city?: string;
state?: string;
zip?: string;
country?: string;
department_id?: string;
job_position_id?: string;
manager_id?: string;
hire_date: string;
bank_name?: string;
bank_account?: string;
bank_clabe?: string;
photo_url?: string;
notes?: string;
}
interface UpdateEmployeeDto {
first_name?: string;
last_name?: string;
middle_name?: string | null;
user_id?: string | null;
birth_date?: string | null;
gender?: string | null;
marital_status?: string | null;
nationality?: string | null;
identification_id?: string | null;
identification_type?: string | null;
social_security_number?: string | null;
tax_id?: string | null;
email?: string | null;
work_email?: string | null;
phone?: string | null;
work_phone?: string | null;
mobile?: string | null;
emergency_contact?: string | null;
emergency_phone?: string | null;
street?: string | null;
city?: string | null;
state?: string | null;
zip?: string | null;
country?: string | null;
department_id?: string | null;
job_position_id?: string | null;
manager_id?: string | null;
bank_name?: string | null;
bank_account?: string | null;
bank_clabe?: string | null;
photo_url?: string | null;
notes?: string | null;
}
interface EmployeeFilters {
company_id?: string;
department_id?: string;
status?: EmployeeStatus;
manager_id?: string;
search?: string;
page?: number;
limit?: number;
}
Departments DTOs
interface CreateDepartmentDto {
company_id: string;
name: string;
code?: string;
parent_id?: string;
manager_id?: string;
description?: string;
color?: string;
}
interface UpdateDepartmentDto {
name?: string;
code?: string | null;
parent_id?: string | null;
manager_id?: string | null;
description?: string | null;
color?: string | null;
active?: boolean;
}
interface DepartmentFilters {
company_id?: string;
active?: boolean;
search?: string;
page?: number;
limit?: number;
}
interface CreateJobPositionDto {
name: string;
department_id?: string;
description?: string;
requirements?: string;
responsibilities?: string;
min_salary?: number;
max_salary?: number;
}
interface UpdateJobPositionDto {
name?: string;
department_id?: string | null;
description?: string | null;
requirements?: string | null;
responsibilities?: string | null;
min_salary?: number | null;
max_salary?: number | null;
active?: boolean;
}
Contracts DTOs
interface CreateContractDto {
company_id: string;
employee_id: string;
name: string;
reference?: string;
contract_type: ContractType;
job_position_id?: string;
department_id?: string;
date_start: string;
date_end?: string;
trial_date_end?: string;
wage: number;
wage_type?: string;
currency_id?: string;
hours_per_week?: number;
vacation_days?: number;
christmas_bonus_days?: number;
document_url?: string;
notes?: string;
}
interface UpdateContractDto {
reference?: string | null;
job_position_id?: string | null;
department_id?: string | null;
date_end?: string | null;
trial_date_end?: string | null;
wage?: number;
wage_type?: string;
currency_id?: string | null;
hours_per_week?: number;
vacation_days?: number;
christmas_bonus_days?: number;
document_url?: string | null;
notes?: string | null;
}
interface ContractFilters {
company_id?: string;
employee_id?: string;
status?: ContractStatus;
contract_type?: ContractType;
search?: string;
page?: number;
limit?: number;
}
Leaves DTOs
interface CreateLeaveTypeDto {
name: string;
code?: string;
leave_type: LeaveType;
requires_approval?: boolean;
max_days?: number;
is_paid?: boolean;
color?: string;
}
interface UpdateLeaveTypeDto {
name?: string;
code?: string | null;
requires_approval?: boolean;
max_days?: number | null;
is_paid?: boolean;
color?: string | null;
active?: boolean;
}
interface CreateLeaveDto {
company_id: string;
employee_id: string;
leave_type_id: string;
name?: string;
date_from: string;
date_to: string;
description?: string;
}
interface UpdateLeaveDto {
leave_type_id?: string;
name?: string | null;
date_from?: string;
date_to?: string;
description?: string | null;
}
interface LeaveFilters {
company_id?: string;
employee_id?: string;
leave_type_id?: string;
status?: LeaveStatus;
date_from?: string;
date_to?: string;
search?: string;
page?: number;
limit?: number;
}
Skills DTOs
interface CreateSkillTypeDto {
name: string;
skill_levels?: string;
}
interface UpdateSkillTypeDto {
name?: string;
skill_levels?: string;
}
interface CreateSkillDto {
skill_type_id: string;
name: string;
}
interface UpdateSkillDto {
name?: string;
skill_type_id?: string;
}
interface CreateSkillLevelDto {
skill_type_id: string;
name: string;
level: number;
}
interface UpdateSkillLevelDto {
name?: string;
level?: number;
}
interface CreateEmployeeSkillDto {
employee_id: string;
skill_id: string;
skill_level_id?: string;
skill_type_id?: string;
}
interface UpdateEmployeeSkillDto {
skill_level_id?: string | null;
skill_type_id?: string | null;
}
Expenses DTOs
interface CreateExpenseSheetDto {
company_id: string;
employee_id: string;
name: string;
user_id?: string;
accounting_date?: string;
}
interface UpdateExpenseSheetDto {
name?: string;
user_id?: string | null;
accounting_date?: string | null;
}
interface CreateExpenseDto {
company_id: string;
employee_id: string;
name: string;
sheet_id?: string;
product_id?: string;
unit_amount: number;
quantity?: number;
currency_id?: string;
tax_ids?: string[];
date?: string;
description?: string;
reference?: string;
analytic_account_id?: string;
payment_mode?: string;
}
interface UpdateExpenseDto {
name?: string;
sheet_id?: string | null;
product_id?: string | null;
unit_amount?: number;
quantity?: number;
currency_id?: string | null;
tax_ids?: string[];
date?: string;
description?: string | null;
reference?: string | null;
analytic_account_id?: string | null;
payment_mode?: string;
}
interface ExpenseSheetFilters {
company_id?: string;
employee_id?: string;
state?: ExpenseStatus;
date_from?: string;
date_to?: string;
search?: string;
page?: number;
limit?: number;
}
interface ExpenseFilters {
company_id?: string;
employee_id?: string;
sheet_id?: string;
state?: ExpenseStatus;
date_from?: string;
date_to?: string;
search?: string;
page?: number;
limit?: number;
}
Payslips DTOs
interface CreatePayslipStructureDto {
name: string;
code?: string;
is_active?: boolean;
note?: string;
}
interface UpdatePayslipStructureDto {
name?: string;
code?: string | null;
is_active?: boolean;
note?: string | null;
}
interface CreatePayslipDto {
company_id: string;
employee_id: string;
contract_id?: string;
name: string;
date_from: string;
date_to: string;
date?: string;
structure_id?: string;
basic_wage?: number;
worked_days?: number;
worked_hours?: number;
}
interface UpdatePayslipDto {
name?: string;
date?: string | null;
structure_id?: string | null;
basic_wage?: number;
gross_wage?: number;
net_wage?: number;
worked_days?: number;
worked_hours?: number;
}
interface CreatePayslipLineDto {
name: string;
code: string;
sequence?: number;
category?: string;
quantity?: number;
rate?: number;
amount: number;
appears_on_payslip?: boolean;
}
interface UpdatePayslipLineDto {
name?: string;
code?: string;
sequence?: number;
category?: string;
quantity?: number;
rate?: number;
amount?: number;
appears_on_payslip?: boolean;
}
interface PayslipStructureFilters {
is_active?: boolean;
search?: string;
page?: number;
limit?: number;
}
interface PayslipFilters {
company_id?: string;
employee_id?: string;
contract_id?: string;
structure_id?: string;
state?: PayslipStatus;
date_from?: string;
date_to?: string;
search?: string;
page?: number;
limit?: number;
}
ENDPOINTS
Employees
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/employees |
Listar empleados |
| GET |
/api/hr/employees/:id |
Obtener empleado |
| POST |
/api/hr/employees |
Crear empleado |
| PUT |
/api/hr/employees/:id |
Actualizar empleado |
| DELETE |
/api/hr/employees/:id |
Eliminar empleado |
| POST |
/api/hr/employees/:id/terminate |
Dar de baja |
| POST |
/api/hr/employees/:id/reactivate |
Reactivar |
| GET |
/api/hr/employees/:id/subordinates |
Obtener subordinados |
Departments
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/departments |
Listar departamentos |
| GET |
/api/hr/departments/:id |
Obtener departamento |
| POST |
/api/hr/departments |
Crear departamento |
| PUT |
/api/hr/departments/:id |
Actualizar departamento |
| DELETE |
/api/hr/departments/:id |
Eliminar departamento |
Job Positions
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/job-positions |
Listar puestos |
| GET |
/api/hr/job-positions/:id |
Obtener puesto |
| POST |
/api/hr/job-positions |
Crear puesto |
| PUT |
/api/hr/job-positions/:id |
Actualizar puesto |
| DELETE |
/api/hr/job-positions/:id |
Eliminar puesto |
Contracts
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/contracts |
Listar contratos |
| GET |
/api/hr/contracts/:id |
Obtener contrato |
| POST |
/api/hr/contracts |
Crear contrato |
| PUT |
/api/hr/contracts/:id |
Actualizar contrato |
| DELETE |
/api/hr/contracts/:id |
Eliminar contrato |
| POST |
/api/hr/contracts/:id/activate |
Activar contrato |
| POST |
/api/hr/contracts/:id/terminate |
Terminar contrato |
| POST |
/api/hr/contracts/:id/cancel |
Cancelar contrato |
Leaves
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/leave-types |
Listar tipos de ausencia |
| GET |
/api/hr/leave-types/:id |
Obtener tipo |
| POST |
/api/hr/leave-types |
Crear tipo |
| PUT |
/api/hr/leave-types/:id |
Actualizar tipo |
| DELETE |
/api/hr/leave-types/:id |
Eliminar tipo |
| GET |
/api/hr/leaves |
Listar ausencias |
| GET |
/api/hr/leaves/:id |
Obtener ausencia |
| POST |
/api/hr/leaves |
Crear ausencia |
| PUT |
/api/hr/leaves/:id |
Actualizar ausencia |
| DELETE |
/api/hr/leaves/:id |
Eliminar ausencia |
| POST |
/api/hr/leaves/:id/submit |
Enviar solicitud |
| POST |
/api/hr/leaves/:id/approve |
Aprobar solicitud |
| POST |
/api/hr/leaves/:id/reject |
Rechazar solicitud |
| POST |
/api/hr/leaves/:id/cancel |
Cancelar solicitud |
Skills
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/skill-types |
Listar tipos de habilidad |
| GET |
/api/hr/skill-types/:id |
Obtener tipo |
| POST |
/api/hr/skill-types |
Crear tipo |
| PUT |
/api/hr/skill-types/:id |
Actualizar tipo |
| DELETE |
/api/hr/skill-types/:id |
Eliminar tipo |
| GET |
/api/hr/skills |
Listar habilidades |
| GET |
/api/hr/skills/:id |
Obtener habilidad |
| POST |
/api/hr/skills |
Crear habilidad |
| PUT |
/api/hr/skills/:id |
Actualizar habilidad |
| DELETE |
/api/hr/skills/:id |
Eliminar habilidad |
| GET |
/api/hr/skill-levels |
Listar niveles |
| GET |
/api/hr/skill-levels/:id |
Obtener nivel |
| POST |
/api/hr/skill-levels |
Crear nivel |
| PUT |
/api/hr/skill-levels/:id |
Actualizar nivel |
| DELETE |
/api/hr/skill-levels/:id |
Eliminar nivel |
| GET |
/api/hr/employee-skills |
Listar habilidades de empleados |
| GET |
/api/hr/employee-skills/:id |
Obtener asignacion |
| POST |
/api/hr/employee-skills |
Asignar habilidad |
| PUT |
/api/hr/employee-skills/:id |
Actualizar asignacion |
| DELETE |
/api/hr/employee-skills/:id |
Eliminar asignacion |
| GET |
/api/hr/employees/:id/skills |
Habilidades de empleado |
Expenses
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/expense-sheets |
Listar hojas de gastos |
| GET |
/api/hr/expense-sheets/:id |
Obtener hoja |
| POST |
/api/hr/expense-sheets |
Crear hoja |
| PUT |
/api/hr/expense-sheets/:id |
Actualizar hoja |
| DELETE |
/api/hr/expense-sheets/:id |
Eliminar hoja |
| POST |
/api/hr/expense-sheets/:id/submit |
Enviar hoja |
| POST |
/api/hr/expense-sheets/:id/approve |
Aprobar hoja |
| POST |
/api/hr/expense-sheets/:id/reject |
Rechazar hoja |
| GET |
/api/hr/expenses |
Listar gastos |
| GET |
/api/hr/expenses/:id |
Obtener gasto |
| POST |
/api/hr/expenses |
Crear gasto |
| PUT |
/api/hr/expenses/:id |
Actualizar gasto |
| DELETE |
/api/hr/expenses/:id |
Eliminar gasto |
Payslips
| Metodo |
Ruta |
Descripcion |
| GET |
/api/hr/payslip-structures |
Listar estructuras |
| GET |
/api/hr/payslip-structures/:id |
Obtener estructura |
| POST |
/api/hr/payslip-structures |
Crear estructura |
| PUT |
/api/hr/payslip-structures/:id |
Actualizar estructura |
| DELETE |
/api/hr/payslip-structures/:id |
Eliminar estructura |
| GET |
/api/hr/payslips |
Listar nominas |
| GET |
/api/hr/payslips/:id |
Obtener nomina |
| POST |
/api/hr/payslips |
Crear nomina |
| PUT |
/api/hr/payslips/:id |
Actualizar nomina |
| DELETE |
/api/hr/payslips/:id |
Eliminar nomina |
| POST |
/api/hr/payslips/:id/verify |
Verificar nomina |
| POST |
/api/hr/payslips/:id/confirm |
Confirmar nomina |
| POST |
/api/hr/payslips/:id/cancel |
Cancelar nomina |
| GET |
/api/hr/payslips/:id/lines |
Obtener lineas |
| POST |
/api/hr/payslips/:id/lines |
Agregar linea |
| PUT |
/api/hr/payslips/:id/lines/:lineId |
Actualizar linea |
| DELETE |
/api/hr/payslips/:id/lines/:lineId |
Eliminar linea |
TESTS
Ubicacion de Tests
backend/src/modules/hr/__tests__/
employees.test.ts
departments.test.ts
contracts.test.ts
leaves.test.ts
skills.test.ts
expenses.test.ts
payslips.test.ts
Casos de Prueba Requeridos
EmployeesService
DepartmentsService
ContractsService
LeavesService
SkillsService
ExpensesService
PayslipsService
DEPENDENCIAS
Internas
| Modulo |
Descripcion |
auth |
Empresas y usuarios |
core |
Monedas |
inventory |
Productos (para gastos) |
analytics |
Cuentas analiticas |
Tablas Referenciadas
auth.companies - Empresa del empleado/contrato
auth.users - Usuario asociado al empleado
core.currencies - Moneda del contrato/gasto
inventory.products - Producto del gasto
analytics.analytic_accounts - Cuenta analitica
Externas
{
"pg": "Base de datos PostgreSQL"
}
ERRORES COMUNES
| Codigo |
Mensaje |
Causa |
NOT_FOUND |
Empleado no encontrado |
ID invalido o no pertenece al tenant |
CONFLICT |
Ya existe un empleado con ese numero |
employee_number duplicado |
CONFLICT |
No se puede eliminar un empleado con contratos |
Tiene contratos asociados |
CONFLICT |
No se puede eliminar un empleado que es manager |
Es manager de otros empleados |
VALIDATION |
El empleado ya tiene un contrato activo |
Intento de crear segundo contrato activo |
VALIDATION |
Solo se pueden editar contratos en estado borrador |
Contrato no esta en draft |
VALIDATION |
Ya existe una solicitud de ausencia para estas fechas |
Ausencias solapadas |
VALIDATION |
Este tipo de ausencia tiene un maximo de X dias |
Excede dias permitidos |
VALIDATION |
Solo se pueden modificar gastos en estado borrador |
Gasto no esta en draft |
VALIDATION |
Solo se pueden modificar nominas en estado borrador |
Nomina no esta en draft |
CHANGELOG
| Version |
Fecha |
Cambios |
| 1.0.0 |
2026-01-10 |
Especificacion inicial con 7 servicios |