157 lines
6.2 KiB
SQL
157 lines
6.2 KiB
SQL
-- ============================================================================
|
|
-- HR Schema DDL - Extension de RRHH para Construccion
|
|
-- Modulo: MAI-007 RRHH y Asistencias
|
|
-- Version: 1.0.0
|
|
-- Fecha: 2025-12-06
|
|
-- ============================================================================
|
|
-- POLITICA: CARGA LIMPIA (ver DIRECTIVA-POLITICA-CARGA-LIMPIA.md)
|
|
-- Este archivo es parte de la fuente de verdad DDL.
|
|
-- ============================================================================
|
|
|
|
-- Verificar prerequisitos
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'auth') THEN
|
|
RAISE EXCEPTION 'Schema auth no existe. ERP-Core debe estar instalado';
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'auth' AND tablename = 'tenants') THEN
|
|
RAISE EXCEPTION 'Tabla auth.tenants no existe. ERP-Core debe estar instalado';
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'construction') THEN
|
|
RAISE EXCEPTION 'Schema construction no existe. Ejecutar primero 01-construction-schema-ddl.sql';
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Crear schema si no existe
|
|
CREATE SCHEMA IF NOT EXISTS hr;
|
|
|
|
-- Configurar search_path
|
|
SET search_path TO hr, construction, core, core_shared, public;
|
|
|
|
-- ============================================================================
|
|
-- TABLAS BASE (requeridas por HSE y otros modulos)
|
|
-- ============================================================================
|
|
|
|
-- Tabla: Empleados
|
|
CREATE TABLE IF NOT EXISTS hr.employees (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
|
|
codigo VARCHAR(20) NOT NULL,
|
|
nombre VARCHAR(100) NOT NULL,
|
|
apellido_paterno VARCHAR(100) NOT NULL,
|
|
apellido_materno VARCHAR(100),
|
|
curp VARCHAR(18),
|
|
rfc VARCHAR(13),
|
|
nss VARCHAR(11),
|
|
fecha_nacimiento DATE,
|
|
genero VARCHAR(1),
|
|
email VARCHAR(255),
|
|
telefono VARCHAR(20),
|
|
direccion TEXT,
|
|
fecha_ingreso DATE NOT NULL,
|
|
fecha_baja DATE,
|
|
puesto_id UUID,
|
|
departamento VARCHAR(100),
|
|
tipo_contrato VARCHAR(50),
|
|
salario_diario DECIMAL(10,2),
|
|
estado VARCHAR(20) NOT NULL DEFAULT 'activo',
|
|
foto_url VARCHAR(500),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_employees_codigo UNIQUE (tenant_id, codigo),
|
|
CONSTRAINT uq_employees_curp UNIQUE (tenant_id, curp)
|
|
);
|
|
|
|
-- Tabla: Puestos
|
|
CREATE TABLE IF NOT EXISTS hr.puestos (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
|
|
codigo VARCHAR(20) NOT NULL,
|
|
nombre VARCHAR(100) NOT NULL,
|
|
descripcion TEXT,
|
|
nivel_riesgo VARCHAR(20),
|
|
requiere_capacitacion_especial BOOLEAN DEFAULT false,
|
|
activo BOOLEAN NOT NULL DEFAULT true,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
CONSTRAINT uq_puestos_codigo UNIQUE (tenant_id, codigo)
|
|
);
|
|
|
|
-- Agregar FK de puesto a empleados
|
|
ALTER TABLE hr.employees
|
|
ADD CONSTRAINT fk_employees_puesto
|
|
FOREIGN KEY (puesto_id) REFERENCES hr.puestos(id);
|
|
|
|
-- Tabla: Asignacion de empleados a obras
|
|
CREATE TABLE IF NOT EXISTS hr.employee_fraccionamientos (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
|
|
employee_id UUID NOT NULL REFERENCES hr.employees(id),
|
|
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
|
|
fecha_inicio DATE NOT NULL,
|
|
fecha_fin DATE,
|
|
rol VARCHAR(50),
|
|
activo BOOLEAN NOT NULL DEFAULT true,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
CONSTRAINT uq_employee_fraccionamiento UNIQUE (employee_id, fraccionamiento_id, fecha_inicio)
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- INDICES
|
|
-- ============================================================================
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_employees_tenant ON hr.employees(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_employees_estado ON hr.employees(estado);
|
|
CREATE INDEX IF NOT EXISTS idx_employees_puesto ON hr.employees(puesto_id);
|
|
CREATE INDEX IF NOT EXISTS idx_puestos_tenant ON hr.puestos(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_employee_fraccionamientos_employee ON hr.employee_fraccionamientos(employee_id);
|
|
CREATE INDEX IF NOT EXISTS idx_employee_fraccionamientos_fraccionamiento ON hr.employee_fraccionamientos(fraccionamiento_id);
|
|
|
|
-- ============================================================================
|
|
-- ROW LEVEL SECURITY
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE hr.employees ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE hr.puestos ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE hr.employee_fraccionamientos ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_employees ON hr.employees
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
CREATE POLICY tenant_isolation_puestos ON hr.puestos
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
CREATE POLICY tenant_isolation_employee_fraccionamientos ON hr.employee_fraccionamientos
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
-- ============================================================================
|
|
-- TRIGGERS
|
|
-- ============================================================================
|
|
|
|
CREATE TRIGGER trg_employees_updated_at
|
|
BEFORE UPDATE ON hr.employees
|
|
FOR EACH ROW EXECUTE FUNCTION core_shared.set_updated_at();
|
|
|
|
CREATE TRIGGER trg_puestos_updated_at
|
|
BEFORE UPDATE ON hr.puestos
|
|
FOR EACH ROW EXECUTE FUNCTION core_shared.set_updated_at();
|
|
|
|
-- ============================================================================
|
|
-- COMENTARIOS
|
|
-- ============================================================================
|
|
|
|
COMMENT ON TABLE hr.employees IS 'Empleados de la empresa';
|
|
COMMENT ON TABLE hr.puestos IS 'Catalogo de puestos de trabajo';
|
|
COMMENT ON TABLE hr.employee_fraccionamientos IS 'Asignacion de empleados a obras/fraccionamientos';
|
|
|
|
-- ============================================================================
|
|
-- FIN
|
|
-- ============================================================================
|