TrenzaCR

trenza-hr

0
0
# Install this skill:
npx skills add TrenzaCR/trenzaos-config --skill "trenza-hr"

Install specific skill from multi-skill repository

# Description

>

# SKILL.md


name: trenza-hr
description: >
Gestión de RRHH: empleados, nóminas, departamentos para TrenzaOS.
Trigger: Al trabajar con empleados, nóminas, departamentos, posiciones, o recursos humanos.
license: MIT
metadata:
author: trenza
version: "1.0"


TrenzaOS HR Skills

Purpose

Este skill enforce las reglas de negocio para gestión de recursos humanos.

⚠️ Reglas Críticas

  • Datos de nómina son confidenciales
  • Solo RRHH y admins pueden ver salarios
  • No se puede eliminar empleados (soft delete)

Core Rules

1. Estructura de Empleados

CREATE TABLE employees (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,

  -- Datos personales
  user_id         UUID REFERENCES users(id),  -- Si tiene acceso al sistema
  first_name      TEXT NOT NULL,
  last_name       TEXT NOT NULL,
  dni             TEXT NOT NULL,  -- Documento de identidad
  email           TEXT NOT NULL,
  phone           TEXT,

  -- Dirección
  address         TEXT,
  city            TEXT,
  state           TEXT,
  country         TEXT,

  -- Empleo
  department_id   UUID REFERENCES departments(id),
  position_id     UUID REFERENCES positions(id),

  -- Fechas
  hire_date       DATE NOT NULL,
  termination_date DATE,

  -- Estado
  status          TEXT DEFAULT 'active',  -- active, inactive, on_leave, terminated

  -- Metadata
  emergency_contact JSONB,  -- { name, phone, relation }
  bank_account     JSONB,  -- { bank, account } - encriptado
  metadata         JSONB DEFAULT '{}',

  -- Auditoría
  created_by      UUID REFERENCES users(id),
  created_at      TIMESTAMPTZ DEFAULT NOW(),
  updated_at      TIMESTAMPTZ DEFAULT NOW()
);

-- DNI único por tenant
CREATE UNIQUE INDEX idx_employees_dni_tenant ON employees(tenant_id, dni);

2. Departamentos

CREATE TABLE departments (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,

  name            TEXT NOT NULL,
  code            TEXT NOT NULL,  -- HR, IT, SALES
  description     TEXT,

  -- Jerarquía
  parent_id       UUID REFERENCES departments(id),

  -- Manager
  manager_id      UUID REFERENCES employees(id),

  is_active       BOOLEAN DEFAULT true,

  created_at      TIMESTAMPTZ DEFAULT NOW()
);

3. Posiciones

CREATE TABLE positions (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,

  title           TEXT NOT NULL,
  code            TEXT NOT NULL,
  department_id   UUID REFERENCES departments(id),

  -- Salario
  salary_min      NUMERIC(12, 2),
  salary_max      NUMERIC(12, 2),
  salary_currency TEXT DEFAULT 'EUR',

  -- Tipo
  employment_type TEXT DEFAULT 'full_time',  -- full_time, part_time, contractor

  -- Descripción
  description     TEXT,
  requirements    TEXT,

  is_active       BOOLEAN DEFAULT true,

  created_at      TIMESTAMPTZ DEFAULT NOW()
);

4. Nóminas

CREATE TABLE payrolls (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,

  employee_id     UUID NOT NULL REFERENCES employees(id),

  -- Período
  period_start    DATE NOT NULL,
  period_end      DATE NOT NULL,
  pay_date        DATE NOT NULL,

  -- Ingresos
  base_salary     NUMERIC(12, 2) NOT NULL,
  overtime        NUMERIC(12, 2) DEFAULT 0,
  bonuses         NUMERIC(12, 2) DEFAULT 0,
  commissions     NUMERIC(12, 2) DEFAULT 0,
  other_income    NUMERIC(12, 2) DEFAULT 0,

  -- Deducciones
  tax_withholding NUMERIC(12, 2) DEFAULT 0,
  social_security NUMERIC(12, 2) DEFAULT 0,
  health_insurance NUMERIC(12, 2) DEFAULT 0,
  other_deductions NUMERIC(12, 2) DEFAULT 0,

  -- Total
  gross_pay       NUMERIC(12, 2) NOT NULL,
  net_pay         NUMERIC(12, 2) NOT NULL,

  -- Estado
  status          TEXT DEFAULT 'draft',  -- draft, calculated, approved, paid

  -- Metadata
  metadata        JSONB DEFAULT '{}',

  created_by      UUID REFERENCES users(id),
  created_at      TIMESTAMPTZ DEFAULT NOW()
);

5. Server Actions

// Crear empleado
const CreateEmployeeSchema = z.object({
  firstName: z.string().min(1),
  lastName: z.string().min(1),
  dni: z.string().min(5),
  email: z.string().email(),
  phone: z.string().optional(),
  departmentId: z.string().uuid().optional(),
  positionId: z.string().uuid().optional(),
  hireDate: z.string().datetime()
})

async function createEmployee(prevState, formData: FormData) {
  const data = CreateEmployeeSchema.parse(Object.fromEntries(formData))

  // Verificar DNI único
  const existing = await db.query.employees.findFirst({
    where: and(
      eq(employees.tenantId, tenantId),
      eq(employees.dni, data.dni)
    )
  })

  if (existing) {
    return { status: 'error', error_code: 'DUPLICATE_DNI' }
  }

  // Crear usuario en Auth si es necesario
  // ... (crear cuenta de acceso)

  const employee = await db.insert(employees).values({
    tenantId,
    ...data,
    status: 'active'
  }).returning()

  return { status: 'success', data: { employeeId: employee.id } }
}

6. Cálculo de Nómina

async function calculatePayroll(employeeId: string, periodStart: Date, periodEnd: Date) {
  const employee = await getEmployee(employeeId)
  const position = await getPosition(employee.positionId)

  // Calcular días trabajados
  const daysWorked = getWorkingDays(periodStart, periodEnd)
  const dailyRate = position.salaryMax / 30  // Asumiendo 30 días

  const baseSalary = dailyRate * daysWorked

  // Deducciones (simplificado)
  const taxRate = 0.21  // IRPF ejemplo
  const taxWithholding = baseSalary * taxRate

  const socialSecurity = baseSalary * 0.0635  // Contingencias comunes
  const netPay = baseSalary - taxWithholding - socialSecurity

  return {
    periodStart,
    periodEnd,
    baseSalary,
    taxWithholding,
    socialSecurity,
    grossPay: baseSalary,
    netPay
  }
}

7. Vacaciones

CREATE TABLE leaves (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,

  employee_id     UUID NOT NULL REFERENCES employees(id),

  -- Tipo
  leave_type      TEXT NOT NULL,  -- vacation, sick, personal, maternity

  -- Fechas
  start_date      DATE NOT NULL,
  end_date        DATE NOT NULL,
  days_count      INTEGER NOT NULL,

  -- Estado
  status          TEXT DEFAULT 'pending',  -- pending, approved, rejected

  -- Notas
  notes           TEXT,

  -- Aprobación
  approved_by     UUID REFERENCES users(id),
  approved_at     TIMESTAMPTZ,

  created_at      TIMESTAMPTZ DEFAULT NOW()
);

HR Checklist

  • [ ] ¿Eliminación de empleados es soft delete?
  • [ ] ¿Datos de nómina son visibles solo para RRHH?
  • [ ] ¿Tienes control de vacaciones?
  • [ ] ¿El DNI es único por tenant?
  • [ ] ¿Generas nóminas por período?

References

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.