-- HR Workforce Platform - PostgreSQL production schema draft -- Stage 6 artifact: use this as the foundation when replacing JSON storage. CREATE TABLE companies ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, legal_name TEXT, status TEXT NOT NULL DEFAULT 'active', created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE branches ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), company_id UUID NOT NULL REFERENCES companies(id), name TEXT NOT NULL, location TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE departments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), branch_id UUID NOT NULL REFERENCES branches(id), name TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE employees ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), company_id UUID REFERENCES companies(id), branch_id UUID REFERENCES branches(id), department_id UUID REFERENCES departments(id), employee_code TEXT NOT NULL UNIQUE, full_name_en TEXT NOT NULL, full_name_ar TEXT, designation TEXT, manager_employee_id UUID REFERENCES employees(id), status TEXT NOT NULL DEFAULT 'active', joining_date DATE, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), employee_id UUID REFERENCES employees(id), name TEXT NOT NULL, email TEXT UNIQUE, password_hash TEXT, role TEXT NOT NULL CHECK (role IN ('HR Admin','Manager','Employee')), is_active BOOLEAN NOT NULL DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE documents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), employee_id UUID NOT NULL REFERENCES employees(id), document_type TEXT NOT NULL, dropbox_url TEXT, expiry_date DATE, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE leave_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), employee_id UUID NOT NULL REFERENCES employees(id), leave_type TEXT NOT NULL, from_date DATE NOT NULL, to_date DATE NOT NULL, reason TEXT, status TEXT NOT NULL DEFAULT 'Submitted' CHECK (status IN ('Submitted','Manager Approved','HR Approved','Rejected')), last_action_by UUID REFERENCES users(id), last_action_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE performance_evaluations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), employee_id UUID NOT NULL REFERENCES employees(id), period TEXT NOT NULL, score NUMERIC(4,2), comments TEXT, status TEXT NOT NULL DEFAULT 'Draft' CHECK (status IN ('Draft','Self Submitted','Manager Reviewed','HR Closed')), created_by UUID REFERENCES users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), closed_at TIMESTAMPTZ ); CREATE TABLE employee_feedback ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), employee_id UUID NOT NULL REFERENCES employees(id), area TEXT NOT NULL, rating INTEGER CHECK (rating BETWEEN 1 AND 5), feedback_text TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE recruitment_vacancies ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), department_id UUID REFERENCES departments(id), position TEXT NOT NULL, required_date DATE, priority TEXT, status TEXT NOT NULL DEFAULT 'Open', created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE audit_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), actor_user_id UUID REFERENCES users(id), actor_name TEXT, action TEXT NOT NULL, details JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE notifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), employee_id UUID REFERENCES employees(id), notification_type TEXT NOT NULL, severity TEXT NOT NULL DEFAULT 'info', message TEXT NOT NULL, due_date DATE, is_read BOOLEAN NOT NULL DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_employees_department ON employees(department_id); CREATE INDEX idx_leave_employee_status ON leave_requests(employee_id, status); CREATE INDEX idx_documents_expiry ON documents(expiry_date); CREATE INDEX idx_evaluations_employee_status ON performance_evaluations(employee_id, status); CREATE INDEX idx_audit_created_at ON audit_logs(created_at DESC);