erp-core/docs/04-modelado/domain-models/hr-domain.md

11 KiB

MODELO DE DOMINIO: RRHH

Módulos: MGN-010 (RRHH Básico) Fecha: 2025-11-24 Referencia Odoo: hr, hr_attendance, hr_holidays Referencia Gamilit: hr_management schema


Diagrama de Entidades (Texto UML)

[Employee]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - company_id: UUID (FK)
  - user_id: UUID (FK)
  - partner_id: UUID (FK)
  - full_name: String
  - employee_number: String
  - job_id: UUID (FK)
  - department_id: UUID (FK)
  - manager_id: UUID (FK self)
  - work_email: String
  - work_phone: String
  - hire_date: Date
  - status: ENUM (active, inactive)

  1 <----> * [Contract]
  1 <----> * [Attendance]
  1 <----> * [Leave]
  1 <----> * [Timesheet]

[Department]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - company_id: UUID (FK)
  - name: String
  - parent_id: UUID (FK self)
  - manager_id: UUID (FK employee)

  1 <----> * [Employee]

[Job]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - company_id: UUID (FK)
  - name: String
  - description: Text
  - department_id: UUID (FK)

  1 <----> * [Employee]

[Contract]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - employee_id: UUID (FK)
  - name: String
  - contract_type: ENUM (permanent, temporary, contractor)
  - job_id: UUID (FK)
  - wage: Decimal
  - date_start: Date
  - date_end: Date
  - status: ENUM (draft, running, expired, cancelled)

[Attendance]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - employee_id: UUID (FK)
  - check_in: Timestamp
  - check_out: Timestamp
  - worked_hours: Decimal

[LeaveType]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - company_id: UUID (FK)
  - name: String
  - code: String
  - allocation_type: ENUM (fixed, accrual, unlimited)
  - requires_approval: Boolean

  1 <----> * [LeaveAllocation]
  1 <----> * [Leave]

[LeaveAllocation]
  - id: UUID (PK)
  - employee_id: UUID (FK)
  - leave_type_id: UUID (FK)
  - days_allocated: Decimal
  - date_from: Date
  - date_to: Date

[Leave]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - employee_id: UUID (FK)
  - leave_type_id: UUID (FK)
  - date_from: Date
  - date_to: Date
  - days_requested: Decimal
  - status: ENUM (draft, pending_approval, approved, refused, cancelled)
  - approver_id: UUID (FK user)

[Timesheet]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - employee_id: UUID (FK)
  - date: Date
  - hours: Decimal
  - analytic_account_id: UUID (FK)
  - task_id: UUID (FK)
  - description: String
  - status: ENUM (draft, approved)

Entidades Principales

1. Employee (Empleado)

Descripción: Empleado de la empresa.

Atributos:

  • id: UUID
  • user_id: Usuario asociado (opcional)
  • partner_id: Partner asociado
  • full_name: Nombre completo
  • employee_number: Número de empleado
  • job_id: Puesto
  • department_id: Departamento
  • manager_id: Jefe directo
  • work_email: Email laboral
  • work_phone: Teléfono laboral
  • hire_date: Fecha de ingreso
  • status: active, inactive

Relaciones:

  • 1 Employee → 1 User (opcional)
  • 1 Employee → 1 Partner
  • N Employees → 1 Department
  • N Employees → 1 Job
  • N Employees → 1 Manager (self-reference)

Patrón Odoo: hr.employee Nota: Un empleado puede o no tener user_id (acceso al sistema)

2. Department (Departamento)

Descripción: Departamento organizacional.

Atributos:

  • id: UUID
  • name: Nombre
  • parent_id: Departamento padre (jerarquía)
  • manager_id: Jefe de departamento

Relaciones:

  • 1 Department → N Employees
  • 1 Department → N Subdepartments

Patrón Odoo: hr.department Jerarquía típica:

  • Dirección General
    • Administración
      • Finanzas
      • RRHH
    • Operaciones
      • Producción
      • Logística

3. Job (Puesto)

Descripción: Puesto de trabajo.

Atributos:

  • id: UUID
  • name: Nombre (ej: "Gerente de Ventas")
  • description: Descripción del puesto
  • department_id: Departamento

Relaciones:

  • N Jobs → 1 Department
  • 1 Job → N Employees

Patrón Odoo: hr.job

4. Contract (Contrato Laboral)

Descripción: Contrato de trabajo del empleado.

Atributos:

  • id: UUID
  • employee_id: Empleado
  • name: Nombre del contrato
  • contract_type: permanent, temporary, contractor
  • job_id: Puesto contratado
  • wage: Salario
  • date_start: Fecha de inicio
  • date_end: Fecha de fin (opcional)
  • status: draft, running, expired, cancelled

Relaciones:

  • N Contracts → 1 Employee
  • N Contracts → 1 Job

Patrón Odoo: hr.contract Estados:

  • draft: Borrador
  • running: Activo (date_start <= HOY <= date_end)
  • expired: Expirado (date_end < HOY)
  • cancelled: Cancelado

5. Attendance (Asistencia)

Descripción: Registro de entrada/salida de empleado.

Atributos:

  • id: UUID
  • employee_id: Empleado
  • check_in: Hora de entrada
  • check_out: Hora de salida
  • worked_hours: Horas trabajadas (calculado)

Relaciones:

  • N Attendances → 1 Employee

Patrón Odoo: hr.attendance Cálculo: worked_hours = check_out - check_in (en horas)

6. LeaveType (Tipo de Ausencia)

Descripción: Tipo de ausencia/permiso.

Atributos:

  • id: UUID
  • name: Nombre (ej: "Vacaciones", "Incapacidad")
  • code: Código
  • allocation_type: fixed, accrual, unlimited
  • requires_approval: Requiere aprobación

Relaciones:

  • 1 LeaveType → N Leaves
  • 1 LeaveType → N LeaveAllocations

Patrón Odoo: hr.leave.type Tipos comunes:

  • Vacaciones (fixed: X días al año)
  • Incapacidad (unlimited)
  • Permiso sin goce (requires_approval)
  • Permiso con goce (requires_approval)

7. LeaveAllocation (Asignación de Ausencias)

Descripción: Días de ausencia asignados a empleado.

Atributos:

  • id: UUID
  • employee_id: Empleado
  • leave_type_id: Tipo de ausencia
  • days_allocated: Días asignados
  • date_from: Fecha inicio de vigencia
  • date_to: Fecha fin de vigencia

Relaciones:

  • N LeaveAllocations → 1 Employee
  • N LeaveAllocations → 1 LeaveType

Patrón Odoo: hr.leave.allocation Ejemplo: 15 días de vacaciones por año

8. Leave (Ausencia/Permiso)

Descripción: Solicitud de ausencia de empleado.

Atributos:

  • id: UUID
  • employee_id: Empleado
  • leave_type_id: Tipo de ausencia
  • date_from: Fecha inicio
  • date_to: Fecha fin
  • days_requested: Días solicitados
  • status: draft, pending_approval, approved, refused, cancelled
  • approver_id: Usuario que aprobó

Relaciones:

  • N Leaves → 1 Employee
  • N Leaves → 1 LeaveType

Patrón Odoo: hr.leave Flujo:

  1. Empleado crea solicitud (draft)
  2. Empleado envía a aprobación (pending_approval)
  3. Manager aprueba/rechaza (approved/refused)

9. Timesheet (Hoja de Horas)

Descripción: Registro de horas trabajadas por proyecto/tarea.

Atributos:

  • id: UUID
  • employee_id: Empleado
  • date: Fecha
  • hours: Horas trabajadas
  • analytic_account_id: Cuenta analítica (proyecto)
  • task_id: Tarea (opcional)
  • description: Descripción
  • status: draft, approved

Relaciones:

  • N Timesheets → 1 Employee
  • N Timesheets → 1 AnalyticAccount (MGN-008)
  • N Timesheets → 1 Task (MGN-011)

Patrón Odoo: account.analytic.line (tipo=timesheet) Integración: Genera líneas analíticas en MGN-008

Reglas de Negocio

RN-HR-001: Un Empleado = Un Partner

  • Todo empleado tiene partner_id (is_employee=true)
  • Partner tiene datos personales: dirección, contactos, etc.

RN-HR-002: Contrato Activo

  • Empleado puede tener múltiples contratos
  • Solo un contrato puede estar 'running' simultáneamente
  • Contrato 'running' si date_start <= HOY <= date_end

RN-HR-003: Check-in/Check-out

  • Check-out no puede ser anterior a check-in
  • Un empleado no puede tener check-in sin check-out pendiente
  • worked_hours calculado automáticamente

RN-HR-004: Saldo de Vacaciones

  • Saldo = LeaveAllocation.days_allocated - SUM(Leave.days_requested WHERE approved)
  • No permitir Leave si saldo insuficiente (excepto tipos unlimited)

RN-HR-005: Aprobación de Ausencias

  • Manager puede aprobar ausencias de su equipo
  • RRHH puede aprobar todas las ausencias
  • Empleado no puede aprobar sus propias ausencias

RN-HR-006: Timesheet y Analítica

  • Timesheet genera línea analítica en MGN-008
  • Tipo de línea: 'expense' (costo de mano de obra)
  • Monto = hours * employee hourly rate

RN-HR-007: Organigrama

  • Estructura jerárquica: Employee.manager_id
  • Visualización en árbol
  • Manager puede ver timesheets/ausencias de su equipo

Casos de Uso Principales

  1. UC-HR-001: RRHH crea empleado
  2. UC-HR-002: RRHH asigna empleado a departamento y puesto
  3. UC-HR-003: RRHH crea contrato de trabajo
  4. UC-HR-004: Empleado registra check-in (entrada)
  5. UC-HR-005: Empleado registra check-out (salida)
  6. UC-HR-006: Empleado solicita vacaciones
  7. UC-HR-007: Manager aprueba/rechaza solicitud de vacaciones
  8. UC-HR-008: Empleado registra timesheet diario
  9. UC-HR-009: Manager valida timesheet de empleado
  10. UC-HR-010: RRHH consulta reporte de asistencias

Validaciones y Constraints

-- Employee number único por company
UNIQUE (tenant_id, company_id, employee_number)

-- Check-out después de check-in
CHECK (check_out > check_in)

-- Worked hours >= 0
CHECK (worked_hours >= 0)

-- Leave date_to >= date_from
CHECK (date_to >= date_from)

-- Days requested > 0
CHECK (days_requested > 0)

-- Timesheet hours > 0
CHECK (hours > 0)

-- Contrato date_end >= date_start
CHECK (date_end IS NULL OR date_end >= date_start)

-- Wage >= 0
CHECK (wage >= 0)

Índices Requeridos

CREATE INDEX idx_employees_department_id ON hr.employees(department_id);
CREATE INDEX idx_employees_manager_id ON hr.employees(manager_id);
CREATE INDEX idx_employees_user_id ON hr.employees(user_id);
CREATE INDEX idx_employees_status ON hr.employees(status);
CREATE INDEX idx_contracts_employee_id ON hr.contracts(employee_id);
CREATE INDEX idx_contracts_status ON hr.contracts(status);
CREATE INDEX idx_attendances_employee_id ON hr.attendances(employee_id);
CREATE INDEX idx_attendances_check_in ON hr.attendances(check_in);
CREATE INDEX idx_leaves_employee_id ON hr.leaves(employee_id);
CREATE INDEX idx_leaves_status ON hr.leaves(status);
CREATE INDEX idx_timesheets_employee_id ON hr.timesheets(employee_id);
CREATE INDEX idx_timesheets_date ON hr.timesheets(date);

Integración con Otros Módulos

Con MGN-001 (Fundamentos)

  • Employee.user_id → User
  • Empleado puede tener acceso al sistema

Con MGN-003 (Catálogos)

  • Employee.partner_id → Partner (is_employee=true)

Con MGN-008 (Analítica)

  • Timesheet genera líneas analíticas
  • Costo de mano de obra por proyecto

Con MGN-011 (Proyectos)

  • Timesheet.task_id → Task
  • Horas trabajadas por tarea

Con MGN-014 (Mensajería)

  • Notificaciones de ausencias aprobadas/rechazadas
  • Recordatorios de timesheet pendiente

Referencias