commit 30/9
tests / ci (push) Canceled after 0s

This commit is contained in:
2026-09-30 09:05:43 +02:00
parent 67dad461d9
commit 3dc7c5c649
75 changed files with 4123 additions and 107 deletions
+63
View File
@@ -0,0 +1,63 @@
CREATE TABLE skills_edu.skill_details (
id uuid PRIMARY KEY REFERENCES public.skills(id) ON DELETE RESTRICT,
name_en varchar(255),
description_pt text,
description_en text,
category varchar(30) NOT NULL CHECK (category IN ('technical','transversal','digital','management','language','other')),
skill_type varchar(30) NOT NULL DEFAULT 'competency',
default_level varchar(30),
source_name varchar(255),
source_version varchar(100),
status varchar(20) NOT NULL DEFAULT 'active' CHECK (status IN ('draft','active','inactive','archived')),
created_by bigint,
updated_by bigint,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
CREATE TABLE skills_edu.occupation_details (
id uuid PRIMARY KEY REFERENCES public.occupations(id) ON DELETE RESTRICT,
name_en varchar(255),
description_pt text,
description_en text,
occupational_family varchar(150),
sector_master_id bigint,
qualification_level varchar(80),
minimum_experience_months integer CHECK (minimum_experience_months IS NULL OR minimum_experience_months >= 0),
status varchar(20) NOT NULL DEFAULT 'active' CHECK (status IN ('draft','active','inactive','archived')),
created_by bigint,
updated_by bigint,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
CREATE TABLE skills_edu.occupation_skills (
occupation_id uuid NOT NULL REFERENCES public.occupations(id) ON DELETE CASCADE,
skill_id uuid NOT NULL REFERENCES public.skills(id) ON DELETE RESTRICT,
requirement_type varchar(20) NOT NULL DEFAULT 'required' CHECK (requirement_type IN ('required','desired')),
minimum_level varchar(30),
weight numeric(5,2) CHECK (weight IS NULL OR weight BETWEEN 0 AND 100),
approved_at timestamptz,
approved_by bigint,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (occupation_id, skill_id, requirement_type)
);
CREATE INDEX idx_skills_category_status ON skills_edu.skill_details(category,status) WHERE deleted_at IS NULL;
CREATE INDEX idx_occupations_sector_status ON skills_edu.occupation_details(sector_master_id,status) WHERE deleted_at IS NULL;
CREATE TRIGGER trg_skills_updated_at BEFORE UPDATE ON skills_edu.skill_details FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_occupations_updated_at BEFORE UPDATE ON skills_edu.occupation_details FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
ALTER TABLE skills_edu.skill_details ADD FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.skill_details ADD FOREIGN KEY (updated_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.occupation_details ADD FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.occupation_details ADD FOREIGN KEY (updated_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.occupation_details ADD FOREIGN KEY (sector_master_id) REFERENCES public.sectors(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.occupation_skills ADD FOREIGN KEY (approved_by) REFERENCES public.users(id) ON DELETE RESTRICT;
+123
View File
@@ -0,0 +1,123 @@
CREATE TABLE skills_edu.professional_profiles (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_master_id bigint,
registration_mode varchar(20) NOT NULL CHECK (registration_mode IN ('individual','institution')),
full_name varchar(255) NOT NULL,
identity_hash char(64),
professional_title varchar(255),
professional_summary text,
occupation_id uuid REFERENCES public.occupations(id) ON DELETE SET NULL,
location_master_id uuid,
location_level varchar(30) CHECK (location_level IS NULL OR location_level IN ('national','region','corridor','province','district','municipality','influence_area','zee','zfi','industrial_park','indicative')),
available_from date,
availability_type varchar(30),
visibility_level varchar(20) NOT NULL DEFAULT 'private' CHECK (visibility_level IN ('private','validated_investors','institutional','public_summary')),
status varchar(30) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','submitted','in_validation','validated','rejected','suspended','deactivated')),
submitted_at timestamptz,
validated_at timestamptz,
validated_by bigint,
created_by bigint,
updated_by bigint,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
CREATE UNIQUE INDEX uq_professional_profiles_user_active ON skills_edu.professional_profiles(user_master_id) WHERE user_master_id IS NOT NULL AND deleted_at IS NULL AND status <> 'deactivated';
CREATE UNIQUE INDEX uq_professional_profiles_identity_active ON skills_edu.professional_profiles(identity_hash) WHERE identity_hash IS NOT NULL AND deleted_at IS NULL AND status <> 'deactivated';
CREATE TABLE skills_edu.profile_contacts (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
contact_type varchar(20) NOT NULL CHECK (contact_type IN ('email','phone')),
contact_value_encrypted text NOT NULL,
contact_hash char(64) NOT NULL,
is_primary boolean NOT NULL DEFAULT false,
is_confirmed boolean NOT NULL DEFAULT false,
confirmed_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (profile_id, contact_type, contact_hash)
);
CREATE TABLE skills_edu.profile_skills (
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
skill_id uuid NOT NULL REFERENCES public.skills(id) ON DELETE RESTRICT,
proficiency_level varchar(30) NOT NULL,
verification_status varchar(20) NOT NULL DEFAULT 'declared' CHECK (verification_status IN ('declared','assessed','validated','rejected','expired')),
years_experience numeric(5,2) CHECK (years_experience IS NULL OR years_experience >= 0),
verified_by bigint,
verified_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (profile_id, skill_id)
);
CREATE TABLE skills_edu.profile_experiences (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
job_title varchar(255) NOT NULL,
sector_master_id bigint,
organisation_name varchar(255),
started_on date NOT NULL,
ended_on date,
description text,
verification_status varchar(20) NOT NULL DEFAULT 'declared' CHECK (verification_status IN ('declared','in_validation','validated','rejected')),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CHECK (ended_on IS NULL OR ended_on >= started_on)
);
CREATE TABLE skills_edu.profile_languages (
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
language_code varchar(10) NOT NULL,
proficiency_level varchar(30) NOT NULL,
verification_status varchar(20) NOT NULL DEFAULT 'declared' CHECK (verification_status IN ('declared','assessed','validated')),
PRIMARY KEY (profile_id, language_code)
);
CREATE TABLE skills_edu.institutional_candidate_registrations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id uuid NOT NULL UNIQUE REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
institution_master_id uuid NOT NULL,
program_master_id uuid,
internal_candidate_code varchar(100),
academic_level varchar(100),
class_name varchar(100),
study_status varchar(30) CHECK (study_status IS NULL OR study_status IN ('enrolled','finalist','completed','suspended','withdrawn')),
expected_completion_date date,
institution_operator_user_id bigint NOT NULL,
institution_validation_status varchar(20) NOT NULL DEFAULT 'pending' CHECK (institution_validation_status IN ('pending','validated','rejected','suspended')),
candidate_confirmation_status varchar(20) NOT NULL DEFAULT 'pending' CHECK (candidate_confirmation_status IN ('pending','confirmed','rejected','revoked')),
candidate_confirmed_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (institution_master_id, internal_candidate_code)
);
CREATE INDEX idx_profiles_searchable ON skills_edu.professional_profiles(status,visibility_level,occupation_id,location_master_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_profile_skills_skill ON skills_edu.profile_skills(skill_id,verification_status);
CREATE INDEX idx_profile_contacts_hash ON skills_edu.profile_contacts(contact_hash);
CREATE UNIQUE INDEX uq_profile_primary_contact_type ON skills_edu.profile_contacts(profile_id,contact_type) WHERE is_primary = true;
CREATE TRIGGER trg_profiles_updated_at BEFORE UPDATE ON skills_edu.professional_profiles FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_profile_skills_updated_at BEFORE UPDATE ON skills_edu.profile_skills FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
ALTER TABLE skills_edu.professional_profiles ADD FOREIGN KEY (user_master_id) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.professional_profiles ADD FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.professional_profiles ADD FOREIGN KEY (updated_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.professional_profiles ADD FOREIGN KEY (validated_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.professional_profiles ADD FOREIGN KEY (location_master_id) REFERENCES public.geo_locations(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.profile_skills ADD FOREIGN KEY (verified_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.profile_experiences ADD FOREIGN KEY (sector_master_id) REFERENCES public.sectors(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.institutional_candidate_registrations ADD FOREIGN KEY (institution_operator_user_id) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.institutional_candidate_registrations ADD FOREIGN KEY (institution_master_id) REFERENCES public.training_providers(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.institutional_candidate_registrations ADD FOREIGN KEY (program_master_id) REFERENCES public.courses(id) ON DELETE RESTRICT;
+101
View File
@@ -0,0 +1,101 @@
CREATE TABLE skills_edu.profile_qualifications (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
qualification_type varchar(30) NOT NULL CHECK (qualification_type IN ('degree','diploma','certificate','licence','completion_statement','other')),
name varchar(255) NOT NULL,
field_of_study varchar(255),
qualification_level varchar(100),
issuing_institution_name varchar(255) NOT NULL,
institution_master_id uuid,
issued_on date NOT NULL,
expires_on date,
holder_name varchar(255) NOT NULL,
verification_status varchar(20) NOT NULL DEFAULT 'declared' CHECK (verification_status IN ('declared','in_validation','validated','rejected','expired')),
verified_by bigint,
verified_at timestamptz,
verification_reason text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
CHECK (expires_on IS NULL OR expires_on >= issued_on)
);
CREATE TABLE skills_edu.qualification_document_details (
id uuid PRIMARY KEY REFERENCES public.documents(id) ON DELETE RESTRICT,
qualification_id uuid REFERENCES skills_edu.profile_qualifications(id) ON DELETE RESTRICT,
experience_id uuid REFERENCES skills_edu.profile_experiences(id) ON DELETE RESTRICT,
document_type varchar(30) NOT NULL CHECK (document_type IN ('diploma','certificate','licence','completion_statement','academic_record','experience_proof','other')),
file_size_bytes bigint NOT NULL CHECK (file_size_bytes > 0),
document_group_id uuid NOT NULL DEFAULT gen_random_uuid(),
version_no integer NOT NULL DEFAULT 1 CHECK (version_no > 0),
replaces_document_id uuid REFERENCES skills_edu.qualification_document_details(id) ON DELETE RESTRICT,
malware_scan_status varchar(20) NOT NULL DEFAULT 'pending' CHECK (malware_scan_status IN ('pending','clean','infected','error')),
malware_scanned_at timestamptz,
quarantine_status varchar(20) NOT NULL DEFAULT 'quarantined' CHECK (quarantine_status IN ('quarantined','released','blocked','deleted')),
validation_status varchar(20) NOT NULL DEFAULT 'pending' CHECK (validation_status IN ('pending','in_validation','validated','rejected','expired','replaced')),
validation_reason text,
validated_by bigint,
validated_at timestamptz,
uploaded_by bigint NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
CHECK (((qualification_id IS NOT NULL)::integer + (experience_id IS NOT NULL)::integer) = 1),
CHECK (replaces_document_id IS NULL OR replaces_document_id <> id),
UNIQUE (document_group_id, version_no)
);
CREATE TABLE skills_edu.consent_details (
id uuid PRIMARY KEY REFERENCES public.consents(id) ON DELETE RESTRICT,
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
legal_basis varchar(100),
policy_version varchar(50) NOT NULL,
channel varchar(30) NOT NULL,
expires_at timestamptz,
evidence jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE skills_edu.institutional_authorisations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
institution_master_id uuid NOT NULL,
purpose_code varchar(100) NOT NULL,
policy_version varchar(50) NOT NULL,
status varchar(20) NOT NULL CHECK (status IN ('granted','expired','revoked')),
granted_at timestamptz NOT NULL,
expires_at timestamptz,
revoked_at timestamptz,
evidence jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamptz NOT NULL DEFAULT now(),
CHECK (expires_at IS NULL OR expires_at > granted_at),
CHECK (revoked_at IS NULL OR revoked_at >= granted_at)
);
CREATE INDEX idx_qualifications_profile_status ON skills_edu.profile_qualifications(profile_id,verification_status) WHERE deleted_at IS NULL;
CREATE INDEX idx_documents_qualification_status ON skills_edu.qualification_document_details(qualification_id,validation_status) WHERE deleted_at IS NULL;
CREATE INDEX idx_documents_scan_status ON skills_edu.qualification_document_details(malware_scan_status,quarantine_status);
CREATE UNIQUE INDEX uq_documents_current_version ON skills_edu.qualification_document_details(document_group_id) WHERE deleted_at IS NULL AND validation_status <> 'replaced';
CREATE INDEX idx_authorisations_profile_institution ON skills_edu.institutional_authorisations(profile_id,institution_master_id,status);
ALTER TABLE skills_edu.profile_qualifications ADD FOREIGN KEY (verified_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.profile_qualifications ADD FOREIGN KEY (institution_master_id) REFERENCES public.training_providers(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.qualification_document_details ADD FOREIGN KEY (validated_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.qualification_document_details ADD FOREIGN KEY (uploaded_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.institutional_authorisations ADD FOREIGN KEY (institution_master_id) REFERENCES public.training_providers(id) ON DELETE RESTRICT;
CREATE FUNCTION skills_edu.validate_consent_dates() RETURNS trigger LANGUAGE plpgsql SET search_path=pg_catalog AS $$
DECLARE granted timestamptz; subject text;
BEGIN
SELECT granted_at,subject_ref INTO granted,subject FROM public.consents WHERE id=NEW.id;
IF subject IS DISTINCT FROM NEW.profile_id::text OR granted IS NULL OR (NEW.expires_at IS NOT NULL AND NEW.expires_at<=granted) THEN
RAISE EXCEPTION 'Consent master profile or validity mismatch' USING ERRCODE='23514';
END IF;
RETURN NEW;
END $$;
CREATE TRIGGER validate_consent_master BEFORE INSERT OR UPDATE ON skills_edu.consent_details
FOR EACH ROW EXECUTE FUNCTION skills_edu.validate_consent_dates();
+83
View File
@@ -0,0 +1,83 @@
CREATE TABLE skills_edu.human_resource_need_details (
id uuid PRIMARY KEY REFERENCES public.labour_demands(id) ON DELETE RESTRICT,
company_master_id uuid NOT NULL,
cluster_master_id uuid,
corridor_master_id uuid,
zee_master_id uuid,
zfi_master_id uuid,
requires_qualified_hr boolean NOT NULL,
profile_description text,
field_of_study varchar(255),
minimum_experience_months integer CHECK (minimum_experience_months IS NULL OR minimum_experience_months >= 0),
quantity_unit varchar(50) DEFAULT 'professionals',
engagement_type varchar(50),
training_available boolean NOT NULL DEFAULT false,
internship_places integer CHECK (internship_places IS NULL OR internship_places >= 0),
priority varchar(20) CHECK (priority IS NULL OR priority IN ('low','medium','high','critical')),
source_version varchar(100),
confidence_level varchar(20) CHECK (confidence_level IS NULL OR confidence_level IN ('low','medium','high','confirmed')),
visibility_level varchar(20) NOT NULL DEFAULT 'private' CHECK (visibility_level IN ('private','validated_users','public_summary')),
responsible_user_id bigint NOT NULL,
approved_by bigint,
approved_at timestamptz,
created_by bigint NOT NULL,
updated_by bigint,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
CHECK ((requires_qualified_hr = false AND profile_description IS NULL) OR (requires_qualified_hr = true AND profile_description IS NOT NULL))
);
CREATE TABLE skills_edu.human_resource_need_skills (
need_id uuid NOT NULL REFERENCES skills_edu.human_resource_need_details(id) ON DELETE CASCADE,
skill_id uuid NOT NULL REFERENCES public.skills(id) ON DELETE RESTRICT,
requirement_type varchar(20) NOT NULL CHECK (requirement_type IN ('required','desired')),
minimum_level varchar(30),
weight numeric(5,2) CHECK (weight IS NULL OR weight BETWEEN 0 AND 100),
is_approved boolean NOT NULL DEFAULT false,
approved_by bigint,
approved_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (need_id, skill_id, requirement_type)
);
CREATE TABLE skills_edu.human_resource_need_languages (
need_id uuid NOT NULL REFERENCES skills_edu.human_resource_need_details(id) ON DELETE CASCADE,
language_code varchar(10) NOT NULL,
minimum_level varchar(30) NOT NULL,
requirement_type varchar(20) NOT NULL CHECK (requirement_type IN ('required','desired')),
PRIMARY KEY (need_id, language_code)
);
CREATE TABLE skills_edu.human_resource_need_certifications (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
need_id uuid NOT NULL REFERENCES skills_edu.human_resource_need_details(id) ON DELETE CASCADE,
certification_name varchar(255) NOT NULL,
issuer_name varchar(255),
requirement_type varchar(20) NOT NULL CHECK (requirement_type IN ('required','desired')),
must_be_valid_on date,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX idx_hr_need_skills_skill ON skills_edu.human_resource_need_skills(skill_id,requirement_type,is_approved);
CREATE TRIGGER trg_hr_needs_updated_at BEFORE UPDATE ON skills_edu.human_resource_need_details FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (updated_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (approved_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (responsible_user_id) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (company_master_id) REFERENCES public.organizations(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (cluster_master_id) REFERENCES public.economic_clusters(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (corridor_master_id) REFERENCES public.development_corridors(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (zee_master_id) REFERENCES public.investment_zones(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_details ADD FOREIGN KEY (zfi_master_id) REFERENCES public.investment_zones(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.human_resource_need_skills ADD FOREIGN KEY (approved_by) REFERENCES public.users(id) ON DELETE RESTRICT;
+137
View File
@@ -0,0 +1,137 @@
CREATE TABLE skills_edu.program_details (
id uuid PRIMARY KEY REFERENCES public.courses(id) ON DELETE RESTRICT,
title_en varchar(255),
study_area varchar(255),
qualification_level varchar(100),
duration_value integer CHECK (duration_value IS NULL OR duration_value > 0),
duration_unit varchar(20),
delivery_mode varchar(20) CHECK (delivery_mode IS NULL OR delivery_mode IN ('in_person','hybrid','distance')),
capacity integer CHECK (capacity IS NULL OR capacity >= 0),
available_places integer CHECK (available_places IS NULL OR available_places >= 0),
cost_amount numeric(18,2) CHECK (cost_amount IS NULL OR cost_amount >= 0),
currency char(3),
location_master_id uuid,
accreditation_status varchar(30) NOT NULL DEFAULT 'declared' CHECK (accreditation_status IN ('declared','in_validation','confirmed','expired','not_accredited')),
accrediting_authority varchar(255),
accreditation_valid_until date,
source_name varchar(255),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
CHECK (available_places IS NULL OR capacity IS NULL OR available_places <= capacity)
);
CREATE TABLE skills_edu.education_program_skills (
program_id uuid NOT NULL REFERENCES public.courses(id) ON DELETE CASCADE,
skill_id uuid NOT NULL REFERENCES public.skills(id) ON DELETE RESTRICT,
target_level varchar(30),
verification_status varchar(20) NOT NULL DEFAULT 'declared' CHECK (verification_status IN ('declared','validated','rejected')),
PRIMARY KEY (program_id, skill_id)
);
CREATE TABLE skills_edu.skill_gaps (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
skill_id uuid NOT NULL REFERENCES public.skills(id) ON DELETE RESTRICT,
occupation_id uuid REFERENCES public.occupations(id) ON DELETE SET NULL,
cluster_master_id uuid,
corridor_master_id uuid,
project_master_id uuid,
location_master_id uuid,
period_start date NOT NULL,
period_end date,
demand_quantity numeric(18,2) NOT NULL DEFAULT 0,
supply_quantity numeric(18,2) NOT NULL DEFAULT 0,
gap_quantity numeric(18,2) GENERATED ALWAYS AS (demand_quantity - supply_quantity) STORED,
criticality varchar(20) CHECK (criticality IS NULL OR criticality IN ('low','medium','high','critical')),
evidence jsonb NOT NULL DEFAULT '{}'::jsonb,
validation_status varchar(20) NOT NULL DEFAULT 'draft' CHECK (validation_status IN ('draft','in_validation','validated','rejected')),
responsible_user_id bigint,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CHECK (period_end IS NULL OR period_end >= period_start)
);
CREATE TABLE skills_edu.educational_opportunity_details (
id uuid PRIMARY KEY REFERENCES public.education_investment_proposals(id) ON DELETE RESTRICT,
gap_id uuid REFERENCES skills_edu.skill_gaps(id) ON DELETE SET NULL,
title_en varchar(255),
opportunity_type varchar(40) NOT NULL CHECK (opportunity_type IN ('new_course','course_expansion','training_centre','laboratory','internship','apprenticeship','upskilling','reskilling','trainer_training','certification_support','digital_learning','infrastructure','scholarship_fund','partnership','other')),
description_en text,
target_audience text,
required_capacity integer CHECK (required_capacity IS NULL OR required_capacity > 0),
cluster_master_id uuid,
corridor_master_id uuid,
project_master_id uuid,
zee_master_id uuid,
zfi_master_id uuid,
location_master_id uuid,
investment_mode varchar(100),
maturity varchar(30),
risks jsonb NOT NULL DEFAULT '[]'::jsonb,
source_records jsonb NOT NULL DEFAULT '[]'::jsonb,
visibility_level varchar(20) NOT NULL DEFAULT 'private' CHECK (visibility_level IN ('private','validated_users','public_summary')),
valid_until date,
created_by bigint NOT NULL,
updated_by bigint,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
CREATE TABLE skills_edu.educational_opportunity_skills (
opportunity_id uuid NOT NULL REFERENCES skills_edu.educational_opportunity_details(id) ON DELETE CASCADE,
skill_id uuid NOT NULL REFERENCES public.skills(id) ON DELETE RESTRICT,
target_level varchar(30),
PRIMARY KEY (opportunity_id, skill_id)
);
CREATE TABLE skills_edu.profile_need_matches (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id uuid NOT NULL REFERENCES skills_edu.professional_profiles(id) ON DELETE CASCADE,
need_id uuid NOT NULL REFERENCES skills_edu.human_resource_need_details(id) ON DELETE CASCADE,
rule_version varchar(50) NOT NULL,
score numeric(5,2) CHECK (score IS NULL OR score BETWEEN 0 AND 100),
required_conditions_met boolean NOT NULL DEFAULT false,
matched_skills jsonb NOT NULL DEFAULT '[]'::jsonb,
skill_gaps jsonb NOT NULL DEFAULT '[]'::jsonb,
explanation jsonb NOT NULL DEFAULT '{}'::jsonb,
confidence_level varchar(20) CHECK (confidence_level IS NULL OR confidence_level IN ('low','medium','high')),
review_status varchar(20) NOT NULL DEFAULT 'pending' CHECK (review_status IN ('pending','approved','rejected','contested')),
reviewed_by bigint,
reviewed_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (profile_id, need_id, rule_version)
);
CREATE INDEX idx_skill_gaps_context ON skills_edu.skill_gaps(skill_id,cluster_master_id,corridor_master_id,project_master_id,validation_status);
CREATE INDEX idx_matches_need_score ON skills_edu.profile_need_matches(need_id,required_conditions_met,score DESC);
ALTER TABLE skills_edu.program_details ADD FOREIGN KEY (location_master_id) REFERENCES public.geo_locations(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.skill_gaps ADD FOREIGN KEY (responsible_user_id) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.skill_gaps ADD FOREIGN KEY (project_master_id) REFERENCES public.projects(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.skill_gaps ADD FOREIGN KEY (cluster_master_id) REFERENCES public.economic_clusters(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.skill_gaps ADD FOREIGN KEY (corridor_master_id) REFERENCES public.development_corridors(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.skill_gaps ADD FOREIGN KEY (location_master_id) REFERENCES public.geo_locations(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (updated_by) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (project_master_id) REFERENCES public.projects(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (cluster_master_id) REFERENCES public.economic_clusters(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (corridor_master_id) REFERENCES public.development_corridors(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (zee_master_id) REFERENCES public.investment_zones(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (zfi_master_id) REFERENCES public.investment_zones(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.educational_opportunity_details ADD FOREIGN KEY (location_master_id) REFERENCES public.geo_locations(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.profile_need_matches ADD FOREIGN KEY (reviewed_by) REFERENCES public.users(id) ON DELETE RESTRICT;
+46
View File
@@ -0,0 +1,46 @@
CREATE TABLE skills_edu.audit_events (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
occurred_at timestamptz NOT NULL DEFAULT now(),
actor_user_id bigint,
actor_role varchar(100),
organisation_master_id uuid,
action varchar(100) NOT NULL,
object_type varchar(100) NOT NULL,
object_id uuid,
previous_state jsonb,
new_state jsonb,
result varchar(20) NOT NULL CHECK (result IN ('success','denied','failed')),
reason text,
correlation_id uuid NOT NULL,
ip_hash char(64),
user_agent_hash char(64),
metadata jsonb NOT NULL DEFAULT '{}'::jsonb
);
REVOKE UPDATE, DELETE, TRUNCATE ON skills_edu.audit_events FROM PUBLIC;
CREATE INDEX idx_audit_object ON skills_edu.audit_events(object_type,object_id,occurred_at DESC);
CREATE INDEX idx_audit_actor ON skills_edu.audit_events(actor_user_id,occurred_at DESC);
CREATE INDEX idx_audit_correlation ON skills_edu.audit_events(correlation_id);
CREATE INDEX idx_profiles_location ON skills_edu.professional_profiles(location_master_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_documents_uploaded_by ON skills_edu.qualification_document_details(uploaded_by,created_at DESC);
CREATE INDEX idx_opportunity_skills_skill ON skills_edu.educational_opportunity_skills(skill_id);
CREATE INDEX idx_program_skills_skill ON skills_edu.education_program_skills(skill_id);
CREATE TRIGGER trg_profile_contacts_updated_at BEFORE UPDATE ON skills_edu.profile_contacts FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_profile_experiences_updated_at BEFORE UPDATE ON skills_edu.profile_experiences FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_institutional_registrations_updated_at BEFORE UPDATE ON skills_edu.institutional_candidate_registrations FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_qualifications_updated_at BEFORE UPDATE ON skills_edu.profile_qualifications FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_documents_updated_at BEFORE UPDATE ON skills_edu.qualification_document_details FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_programs_updated_at BEFORE UPDATE ON skills_edu.program_details FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_skill_gaps_updated_at BEFORE UPDATE ON skills_edu.skill_gaps FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
CREATE TRIGGER trg_opportunities_updated_at BEFORE UPDATE ON skills_edu.educational_opportunity_details FOR EACH ROW EXECUTE FUNCTION skills_edu.set_updated_at();
COMMENT ON COLUMN skills_edu.professional_profiles.identity_hash IS 'Hash normalizado para deduplicação; nunca guardar o identificador em claro nesta coluna.';
COMMENT ON COLUMN skills_edu.profile_contacts.contact_value_encrypted IS 'Valor cifrado pela aplicação ou serviço de segredos; não indexar.';
COMMENT ON COLUMN skills_edu.profile_need_matches.explanation IS 'Critérios, pesos, dados, fonte, limitações e lacunas usados na recomendação.';
ALTER TABLE skills_edu.audit_events ADD FOREIGN KEY (actor_user_id) REFERENCES public.users(id) ON DELETE RESTRICT;
ALTER TABLE skills_edu.audit_events ADD FOREIGN KEY (organisation_master_id) REFERENCES public.organizations(id) ON DELETE RESTRICT;