-- ============================================================================ -- HR EXTENSIONS - FASE 8 ERP-Core -- ERP Vidrio Templado -- ============================================================================ CREATE SCHEMA IF NOT EXISTS hr; DO $$ BEGIN CREATE TYPE hr.expense_status AS ENUM ('draft', 'submitted', 'approved', 'posted', 'paid', 'rejected'); EXCEPTION WHEN duplicate_object THEN NULL; END $$; DO $$ BEGIN CREATE TYPE hr.payslip_status AS ENUM ('draft', 'verify', 'done', 'cancel'); EXCEPTION WHEN duplicate_object THEN NULL; END $$; -- Ubicaciones (áreas de producción) CREATE TABLE IF NOT EXISTS hr.work_locations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, name VARCHAR(100) NOT NULL, -- Extensiones vidrio tipo_area VARCHAR(50), -- 'corte', 'pulido', 'templado', 'almacen', 'instalacion' capacidad_m2 NUMERIC(10,2), tiene_horno BOOLEAN DEFAULT false, temperatura_max INTEGER, active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Tipos de habilidad CREATE TABLE IF NOT EXISTS hr.skill_types ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, name VARCHAR(100) NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Habilidades CREATE TABLE IF NOT EXISTS hr.skills ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, skill_type_id UUID REFERENCES hr.skill_types(id), name VARCHAR(100) NOT NULL, -- Extensiones vidrio tipo_proceso VARCHAR(50), -- 'corte', 'biselado', 'templado', 'instalacion' maquina_habilitado VARCHAR(100), created_at TIMESTAMPTZ DEFAULT NOW() ); -- Niveles CREATE TABLE IF NOT EXISTS hr.skill_levels ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, skill_type_id UUID REFERENCES hr.skill_types(id), name VARCHAR(100) NOT NULL, level INTEGER DEFAULT 1, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Habilidades de empleado CREATE TABLE IF NOT EXISTS hr.employee_skills ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, employee_id UUID NOT NULL, skill_id UUID REFERENCES hr.skills(id), skill_level_id UUID REFERENCES hr.skill_levels(id), created_at TIMESTAMPTZ DEFAULT NOW() ); -- Gastos CREATE TABLE IF NOT EXISTS hr.expense_sheets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, employee_id UUID NOT NULL, name VARCHAR(100) NOT NULL, state hr.expense_status DEFAULT 'draft', total_amount NUMERIC(12,2) DEFAULT 0, proyecto_id UUID, obra_id UUID, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS hr.expenses ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, sheet_id UUID REFERENCES hr.expense_sheets(id) ON DELETE CASCADE, employee_id UUID NOT NULL, name VARCHAR(200) NOT NULL, date DATE DEFAULT CURRENT_DATE, total_amount NUMERIC(12,2) NOT NULL, state hr.expense_status DEFAULT 'draft', created_at TIMESTAMPTZ DEFAULT NOW() ); -- Nómina CREATE TABLE IF NOT EXISTS hr.payslip_structures ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, name VARCHAR(100) NOT NULL, code VARCHAR(20) NOT NULL, tipo_pago VARCHAR(50), active BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT NOW(), CONSTRAINT uq_payslip_structures_code UNIQUE(tenant_id, code) ); CREATE TABLE IF NOT EXISTS hr.payslips ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, employee_id UUID NOT NULL, structure_id UUID REFERENCES hr.payslip_structures(id), date_from DATE NOT NULL, date_to DATE NOT NULL, state hr.payslip_status DEFAULT 'draft', gross NUMERIC(12,2) DEFAULT 0, net NUMERIC(12,2) DEFAULT 0, area_id UUID REFERENCES hr.work_locations(id), metros_producidos NUMERIC(10,2), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS hr.payslip_lines ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, payslip_id UUID REFERENCES hr.payslips(id) ON DELETE CASCADE, name VARCHAR(100) NOT NULL, code VARCHAR(20), amount NUMERIC(12,2) DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Índices CREATE INDEX IF NOT EXISTS idx_work_locations_tenant ON hr.work_locations(tenant_id); CREATE INDEX IF NOT EXISTS idx_skill_types_tenant ON hr.skill_types(tenant_id); CREATE INDEX IF NOT EXISTS idx_skills_tenant ON hr.skills(tenant_id); CREATE INDEX IF NOT EXISTS idx_expense_sheets_tenant ON hr.expense_sheets(tenant_id); CREATE INDEX IF NOT EXISTS idx_payslips_tenant ON hr.payslips(tenant_id); -- RLS ALTER TABLE hr.work_locations ENABLE ROW LEVEL SECURITY; ALTER TABLE hr.skill_types ENABLE ROW LEVEL SECURITY; ALTER TABLE hr.skills ENABLE ROW LEVEL SECURITY; ALTER TABLE hr.skill_levels ENABLE ROW LEVEL SECURITY; ALTER TABLE hr.expense_sheets ENABLE ROW LEVEL SECURITY; ALTER TABLE hr.expenses ENABLE ROW LEVEL SECURITY; ALTER TABLE hr.payslip_structures ENABLE ROW LEVEL SECURITY; ALTER TABLE hr.payslips ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS tenant_isolation_work_locations ON hr.work_locations; CREATE POLICY tenant_isolation_work_locations ON hr.work_locations USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); DROP POLICY IF EXISTS tenant_isolation_skill_types ON hr.skill_types; CREATE POLICY tenant_isolation_skill_types ON hr.skill_types USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); DROP POLICY IF EXISTS tenant_isolation_skills ON hr.skills; CREATE POLICY tenant_isolation_skills ON hr.skills USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); DROP POLICY IF EXISTS tenant_isolation_skill_levels ON hr.skill_levels; CREATE POLICY tenant_isolation_skill_levels ON hr.skill_levels USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); DROP POLICY IF EXISTS tenant_isolation_expense_sheets ON hr.expense_sheets; CREATE POLICY tenant_isolation_expense_sheets ON hr.expense_sheets USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); DROP POLICY IF EXISTS tenant_isolation_expenses ON hr.expenses; CREATE POLICY tenant_isolation_expenses ON hr.expenses USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); DROP POLICY IF EXISTS tenant_isolation_payslip_structures ON hr.payslip_structures; CREATE POLICY tenant_isolation_payslip_structures ON hr.payslip_structures USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); DROP POLICY IF EXISTS tenant_isolation_payslips ON hr.payslips; CREATE POLICY tenant_isolation_payslips ON hr.payslips USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);