-- Create enums for OCR models, AI models, and user roles CREATE TYPE app.ocr_model AS ENUM ( 'tesseract', 'azure_cognitive', 'aws_textract', 'google_vision', 'manual_entry' ); CREATE TYPE app.ai_model AS ENUM ( 'gpt-five', 'claude-three-opus', 'claude-three-sonnet', 'claude-three-haiku', 'gemini-pro' ); CREATE TYPE app.user_role AS ENUM ( 'admin', 'recruiter', 'candidate' ); CREATE TYPE app.nurse_recognition AS ENUM ( 'nurse', 'assistant_nurse', 'nursing_helper' ); -- Update User Table ALTER TABLE app.user ADD COLUMN role app.user_role DEFAULT 'candidate'; -- Update Candidate Document Table ALTER TABLE app.candidate_document ADD COLUMN ocr_text TEXT, ADD COLUMN ocr_model app.ocr_model, ADD COLUMN ocr_started_at TIMESTAMPTZ, ADD COLUMN ocr_ended_at TIMESTAMPTZ; -- Update Candidate Table (user-provided data only) ALTER TABLE app.candidate ADD COLUMN phone VARCHAR, ADD COLUMN date_of_birth DATE, ADD COLUMN current_residence VARCHAR, ADD COLUMN recognition_status app.nurse_recognition; -- Create Education Table CREATE TABLE app.candidate_education ( education_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), candidate_id UUID NOT NULL REFERENCES app.candidate(candidate_id), source_document_id UUID REFERENCES app.candidate_document(document_id), -- Admin-confirmed data institution VARCHAR, country VARCHAR, program VARCHAR, duration_years INTEGER, completion_date DATE, is_accredited BOOLEAN, -- AI-extracted data ai_institution VARCHAR, ai_country VARCHAR, ai_program VARCHAR, ai_duration_years INTEGER, ai_completion_date DATE, ai_is_accredited BOOLEAN, -- Metadata ai_extracted_by app.ai_model, ai_extraction_date TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, last_updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, -- Constraint: AI data requires source document CONSTRAINT ai_data_requires_document CHECK ( (source_document_id IS NOT NULL) OR (ai_institution IS NULL AND ai_country IS NULL AND ai_program IS NULL AND ai_duration_years IS NULL AND ai_completion_date IS NULL AND ai_is_accredited IS NULL AND ai_extracted_by IS NULL AND ai_extraction_date IS NULL) ) ); -- Create Transcript Table CREATE TABLE app.candidate_transcript ( transcript_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), candidate_id UUID NOT NULL REFERENCES app.candidate(candidate_id), source_document_id UUID REFERENCES app.candidate_document(document_id), education_id UUID REFERENCES app.candidate_education(education_id), -- Admin-confirmed data total_theory_hours INTEGER, total_practical_hours INTEGER, -- AI-extracted data ai_total_theory_hours INTEGER, ai_total_practical_hours INTEGER, -- Metadata ai_extracted_by app.ai_model, ai_extraction_date TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, last_updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, -- Constraint CONSTRAINT ai_data_requires_document CHECK ( (source_document_id IS NOT NULL) OR (ai_total_theory_hours IS NULL AND ai_total_practical_hours IS NULL AND ai_extracted_by IS NULL AND ai_extraction_date IS NULL) ) ); -- Create Transcript Course Table CREATE TABLE app.candidate_transcript_course ( course_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), transcript_id UUID NOT NULL REFERENCES app.candidate_transcript(transcript_id), -- Admin-confirmed data course_name VARCHAR, hours INTEGER, grade VARCHAR, -- AI-extracted data ai_course_name VARCHAR, ai_hours INTEGER, ai_grade VARCHAR, -- Metadata ai_extracted_by app.ai_model ); -- Create Clinical Placement Table CREATE TABLE app.candidate_clinical_placement ( placement_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), transcript_id UUID NOT NULL REFERENCES app.candidate_transcript(transcript_id), -- Admin-confirmed data institution VARCHAR, department VARCHAR, duration_hours INTEGER, duration_weeks INTEGER, -- AI-extracted data ai_institution VARCHAR, ai_department VARCHAR, ai_duration_hours INTEGER, ai_duration_weeks INTEGER, -- Metadata ai_extracted_by app.ai_model ); -- Create License Table CREATE TABLE app.candidate_license ( license_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), candidate_id UUID NOT NULL REFERENCES app.candidate(candidate_id), source_document_id UUID REFERENCES app.candidate_document(document_id), -- Admin-confirmed data license_number VARCHAR, issuing_authority VARCHAR, issue_date DATE, expiry_date DATE, status VARCHAR, license_type VARCHAR, -- AI-extracted data ai_license_number VARCHAR, ai_issuing_authority VARCHAR, ai_issue_date DATE, ai_expiry_date DATE, ai_status VARCHAR, ai_license_type VARCHAR, -- Metadata ai_extracted_by app.ai_model, ai_extraction_date TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, last_updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, -- Constraint CONSTRAINT ai_data_requires_document CHECK ( (source_document_id IS NOT NULL) OR (ai_license_number IS NULL AND ai_issuing_authority IS NULL AND ai_issue_date IS NULL AND ai_expiry_date IS NULL AND ai_status IS NULL AND ai_license_type IS NULL AND ai_extracted_by IS NULL AND ai_extraction_date IS NULL) ) ); -- Create Language Certificate Table CREATE TABLE app.candidate_language ( language_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), candidate_id UUID NOT NULL REFERENCES app.candidate(candidate_id), source_document_id UUID REFERENCES app.candidate_document(document_id), -- Admin-confirmed data language VARCHAR DEFAULT 'German', level app.language_level, issuing_body VARCHAR, issue_date DATE, certified_skills TEXT[], -- AI-extracted data ai_language VARCHAR DEFAULT 'German', ai_level app.language_level, ai_issuing_body VARCHAR, ai_issue_date DATE, ai_certified_skills TEXT[], -- Metadata ai_extracted_by app.ai_model, ai_extraction_date TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, last_updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, -- Constraint CONSTRAINT ai_data_requires_document CHECK ( (source_document_id IS NOT NULL) OR (ai_language IS NULL AND ai_level IS NULL AND ai_issuing_body IS NULL AND ai_issue_date IS NULL AND ai_certified_skills IS NULL AND ai_extracted_by IS NULL AND ai_extraction_date IS NULL) ) ); -- Create Work Experience Table CREATE TABLE app.candidate_experience ( experience_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), candidate_id UUID NOT NULL REFERENCES app.candidate(candidate_id), source_document_id UUID REFERENCES app.candidate_document(document_id), -- Admin-confirmed data employer VARCHAR, position VARCHAR, department VARCHAR, start_date DATE, end_date DATE, duration_months INTEGER, is_full_time BOOLEAN, duties TEXT[], -- AI-extracted data ai_employer VARCHAR, ai_position VARCHAR, ai_department VARCHAR, ai_start_date DATE, ai_end_date DATE, ai_duration_months INTEGER, ai_is_full_time BOOLEAN, ai_duties TEXT[], -- Metadata ai_extracted_by app.ai_model, ai_extraction_date TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, last_updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, -- Constraint CONSTRAINT ai_data_requires_document CHECK ( (source_document_id IS NOT NULL) OR (ai_employer IS NULL AND ai_position IS NULL AND ai_department IS NULL AND ai_start_date IS NULL AND ai_end_date IS NULL AND ai_duration_months IS NULL AND ai_is_full_time IS NULL AND ai_duties IS NULL AND ai_extracted_by IS NULL AND ai_extraction_date IS NULL) ) ); -- Add Indexes CREATE INDEX idx_education_candidate ON app.candidate_education(candidate_id); CREATE INDEX idx_transcript_candidate ON app.candidate_transcript(candidate_id); CREATE INDEX idx_license_candidate ON app.candidate_license(candidate_id); CREATE INDEX idx_language_candidate ON app.candidate_language(candidate_id); CREATE INDEX idx_experience_candidate ON app.candidate_experience(candidate_id); CREATE INDEX idx_user_role ON app.user(role); CREATE INDEX idx_document_ocr_status ON app.candidate_document(ocr_started_at, ocr_ended_at); -- Add Update Triggers CREATE TRIGGER update_candidate_education_timestamp BEFORE UPDATE ON app.candidate_education FOR EACH ROW EXECUTE PROCEDURE app.update_lastupdated_timestamp(); CREATE TRIGGER update_candidate_transcript_timestamp BEFORE UPDATE ON app.candidate_transcript FOR EACH ROW EXECUTE PROCEDURE app.update_lastupdated_timestamp(); CREATE TRIGGER update_candidate_license_timestamp BEFORE UPDATE ON app.candidate_license FOR EACH ROW EXECUTE PROCEDURE app.update_lastupdated_timestamp(); CREATE TRIGGER update_candidate_language_timestamp BEFORE UPDATE ON app.candidate_language FOR EACH ROW EXECUTE PROCEDURE app.update_lastupdated_timestamp(); CREATE TRIGGER update_candidate_experience_timestamp BEFORE UPDATE ON app.candidate_experience FOR EACH ROW EXECUTE PROCEDURE app.update_lastupdated_timestamp();