-- ============================================================================
-- 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
-- ============================================================================
