diff --git a/model.internal.application.user.impl/src/main/java/com/hack23/cia/model/internal/application/data/politician/impl/ViewRiksdagenPoliticianExperienceSummary.java b/model.internal.application.user.impl/src/main/java/com/hack23/cia/model/internal/application/data/politician/impl/ViewRiksdagenPoliticianExperienceSummary.java index 91a9bbeb84..96a691bbdc 100644 --- a/model.internal.application.user.impl/src/main/java/com/hack23/cia/model/internal/application/data/politician/impl/ViewRiksdagenPoliticianExperienceSummary.java +++ b/model.internal.application.user.impl/src/main/java/com/hack23/cia/model/internal/application/data/politician/impl/ViewRiksdagenPoliticianExperienceSummary.java @@ -177,7 +177,9 @@ public enum ExperienceBreadth { /** The medium. */ MEDIUM, /** The low. */ - LOW + LOW, + /** The very low. */ + VERY_LOW } /** diff --git a/service.data.impl/src/main/resources/db-changelog-1.28.xml b/service.data.impl/src/main/resources/db-changelog-1.28.xml index ec981203c4..2436aed6fa 100644 --- a/service.data.impl/src/main/resources/db-changelog-1.28.xml +++ b/service.data.impl/src/main/resources/db-changelog-1.28.xml @@ -1938,7 +1938,502 @@ ORDER BY total_weighted_exp DESC; + + + + + + Other */ + ELSE 'Other' + END AS knowledge_area, + CASE + -- Level 1: Top Leadership (Prime Minister, Party Leader) + WHEN assignment_type = 'Departement' AND role_code = 'Statsminister' THEN 50000 -- Prime Minister + WHEN assignment_type = 'partiuppdrag' AND role_code = 'Partiledare' THEN 45000 -- Party Leader + + -- Level 2: Senior Leadership (Deputy PM, Speaker) + WHEN assignment_type = 'Departement' AND role_code = 'Vice statsminister' THEN 45000 -- Deputy Prime Minister + WHEN assignment_type = 'kammaruppdrag' AND role_code = 'Talman' THEN 40000 -- Speaker of the Parliament + + -- Level 3: Ministers, Key Committee Chairs + WHEN assignment_type = 'Departement' AND role_code ILIKE '%minister%' THEN 40000 -- Ministers + WHEN assignment_type = 'Riksdagsorgan' AND role_code = 'Ordförande' THEN 35000 -- Key Committee Chairs + WHEN assignment_type = 'uppdrag' AND role_code = 'Ordförande' AND org_code IN ('FiU', 'KU', 'UU', 'FÖU', 'JuU') THEN 35000 -- Critical Committees + + -- Level 4: Vice Chairs and Senior Party Leaders + WHEN assignment_type = 'uppdrag' AND role_code = 'Vice ordförande' THEN 30000 -- Committee Vice Chairs + WHEN assignment_type = 'partiuppdrag' AND role_code IN ('Gruppledare', 'Partisekreterare') THEN 30000 -- Party Group Leaders & Secretaries + + -- Level 5: Members of Parliament + WHEN assignment_type = 'kammaruppdrag' AND role_code = 'Riksdagsledamot' THEN 20000 -- MPs + WHEN assignment_type = 'Europaparlamentet' AND role_code = 'Ledamot' THEN 20000 -- Members of European Parliament + + -- Level 6: Committee Members + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND role_code = 'Ledamot' THEN 15000 -- Committee Members + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND role_code = 'Ledamot' AND org_code IN ('FiU', 'KU', 'UU', 'FÖU') THEN 18000 -- Members of Key Committees + + -- Level 7: Substitute Roles + WHEN role_code IN ('Suppleant', 'Ersättare') THEN 10000 -- Parliamentary and Committee Substitutes + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND role_code = 'Suppleant' AND org_code IN ('FiU', 'KU', 'UU') THEN 12000 -- Substitutes in Key Committees + + -- Level 8: Regional and Specialized Roles + WHEN assignment_type = 'Riksdagsorgan' AND org_code IN ('RJ', 'NR', 'RFK', 'RRS') THEN 7000 -- Regional/National Cooperation Roles + WHEN assignment_type = 'uppdrag' AND role_code = 'Ledamot' AND org_code IN ('MJU', 'BoU', 'TU') THEN 6000 -- Specialized Committees + + -- Level 9: Oversight and Advisory Roles + WHEN assignment_type = 'Riksdagsorgan' AND org_code IN ('Systembolaget', 'EUN') THEN 4000 -- Oversight Committees + WHEN assignment_type = 'uppdrag' AND role_code IN ('Adjungerad', 'Sekreterare') THEN 3000 -- Advisory Roles + + ELSE 1000 -- Other roles + END AS role_weight, + + CASE WHEN (a.role_code ILIKE '%ersättare%' OR a.role_code ILIKE '%suppleant%') + THEN 1 ELSE 0 + END AS is_substitute, - + CASE WHEN a.role_code IN ( + 'Ordförande','Vice ordförande','Gruppledare','Partiledare','Partisekreterare', + 'Förste vice gruppledare','Andre vice gruppledare' + ) THEN 1 ELSE 0 + END AS is_leadership, + CASE + /* Level 1: Top Leadership (Prime Minister, Party Leader) */ + WHEN assignment_type = 'Departement' AND role_code = 'Statsminister' THEN 1000.0 + WHEN assignment_type = 'partiuppdrag' AND role_code = 'Partiledare' THEN 950.0 + WHEN assignment_type = 'Departement' AND role_code = 'Vice statsminister' THEN 900.0 + + /* Level 2: Senior Government (Ministers, Speaker) */ + WHEN assignment_type = 'Departement' AND (role_code ILIKE '%minister%' OR role_code = 'Statsråd') THEN 850.0 + WHEN assignment_type = 'kammaruppdrag' AND role_code = 'Talman' THEN 800 + WHEN assignment_type = 'talmansuppdrag' AND role_code IN ('Andre vice talman', 'Tredje vice talman') THEN 750.0 + + /* Level 3: Committee Chairs and Party Leadership */ + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND role_code = 'Ordförande' THEN 700.0 + WHEN assignment_type = 'partiuppdrag' AND role_code IN ('Gruppledare', 'Partisekreterare') THEN 650.0 + + /* Level 4: Committee Vice Chairs and Deputies */ + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND role_code = 'Vice ordförande' THEN 600.0 + WHEN assignment_type = 'partiuppdrag' AND role_code IN ('Förste vice gruppledare', 'Andre vice gruppledare') THEN 550.0 + + /* Level 5: Regular Members (MPs, MEPs) */ + WHEN assignment_type = 'kammaruppdrag' AND role_code = 'Riksdagsledamot' THEN 500.0 + WHEN assignment_type = 'Europaparlamentet' AND role_code = 'Ledamot' THEN 450.0 + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND role_code = 'Ledamot' THEN 400.0 + + /* Level 6: Specialized Committees (Defense, EU Affairs) */ + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND org_code IN ('UFÖU', 'EU') AND role_code = 'Ordförande' THEN 350.0 + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND org_code IN ('UFÖU', 'EU') AND role_code = 'Vice ordförande' THEN 300.0 + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND org_code IN ('UFÖU', 'EU') AND role_code = 'Ledamot' THEN 250.0 + + /* Level 7: Oversight and National Cooperation Roles */ + WHEN assignment_type IN ('Riksdagsorgan') AND org_code IN ('RJ', 'Systembolaget', 'NR', 'RFK', 'RRS') THEN 200.0 + + /* Level 8: Substitute Roles */ + WHEN role_code IN ('Ersättare', 'Statsrådsersättare') THEN 150.0 + WHEN role_code IN ('Suppleant', 'Extra suppleant') THEN 100.0 + + /* Level 9: Less Critical Committees */ + WHEN assignment_type IN ('uppdrag', 'Riksdagsorgan') AND org_code IN ('MJU', 'BoU', 'TU') THEN 50.0 + + /* Level 10: Default for unspecified roles */ + ELSE 10.0 + END AS area_weight + FROM assignment_data a +), +per_role_stats AS ( + SELECT + p.id AS person_id, + MAX(p.first_name) AS first_name, + MAX(p.last_name) AS last_name, + r.assignment_type, + r.role_code, + r.org_code, + r.knowledge_area, + COUNT(*) AS total_assignments, + SUM(r.days_in_role) AS total_days, + SUM(r.days_in_role * r.role_weight * r.area_weight) AS weighted_experience, -- Here + SUM(CASE WHEN r.is_substitute=1 THEN r.days_in_role ELSE 0 END) AS substitute_days, + SUM(CASE WHEN r.is_leadership=1 THEN r.days_in_role ELSE 0 END) AS leadership_days + FROM role_day_spans r + JOIN person_data p ON p.id = r.person_id + GROUP BY p.id, r.assignment_type, r.role_code, r.org_code, r.knowledge_area +), +experience_summary AS ( + SELECT + person_id, + MAX(first_name) AS first_name, + MAX(last_name) AS last_name, + SUM(total_days) AS total_days, + SUM(weighted_experience) AS total_weighted_exp, + SUM(CASE WHEN assignment_type = 'Departement' THEN total_days ELSE 0 END) AS govt_days, + SUM(CASE WHEN assignment_type = 'kammaruppdrag' THEN total_days ELSE 0 END) AS riksdag_days, + SUM(CASE WHEN assignment_type = 'partiuppdrag' THEN total_days ELSE 0 END) AS party_days, + SUM(CASE WHEN assignment_type IN ('uppdrag','Riksdagsorgan') THEN total_days ELSE 0 END) AS committee_days, + SUM(substitute_days) AS total_substitute_days, + SUM(leadership_days) AS total_leadership_days, + + JSON_AGG( + JSON_BUILD_OBJECT( + 'area', knowledge_area, + 'days', total_days, + 'weightedExp', weighted_experience + ) + ORDER BY weighted_experience DESC + ) AS knowledge_areas, + + JSON_AGG( + JSON_BUILD_OBJECT( + 'type', assignment_type, + 'role', role_code, + 'org', org_code, + 'days', total_days, + 'weightedExp', weighted_experience, + 'substituteDays', substitute_days, + 'leadershipDays', leadership_days + ) + ORDER BY weighted_experience DESC + ) AS roles + FROM per_role_stats + GROUP BY person_id +), +political_analysis AS ( + SELECT + es.*, + + CASE + WHEN govt_days > 2500 AND riksdag_days > 4000 AND committee_days > 2500 + THEN 'EXTENSIVE_EXPERIENCE' + WHEN govt_days > 2000 AND (riksdag_days > 3000 OR committee_days > 1500) + THEN 'SIGNIFICANT_GOVERNMENT' + WHEN riksdag_days > 3500 AND (govt_days > 1000 OR committee_days > 1200) + THEN 'LONG_SERVING_PARLIAMENT' + WHEN committee_days > 1500 AND riksdag_days > 1000 + THEN 'ACTIVE_COMMITTEES' + WHEN party_days > 1000 + THEN 'PARTY_LEADERSHIP' + ELSE 'MIXED_EXPERIENCE' + END AS experience_level, + + /* Experience breadth score */ + CASE + WHEN (govt_days > 0)::int + + (riksdag_days > 0)::int + + (party_days > 0)::int + + (committee_days > 0)::int >= 4 + THEN 'HIGH' + WHEN (govt_days > 0)::int + + (riksdag_days > 0)::int + + (party_days > 0)::int + + (committee_days > 0)::int = 3 + THEN 'MEDIUM' + WHEN (govt_days > 0)::int + + (riksdag_days > 0)::int + + (party_days > 0)::int + + (committee_days > 0)::int = 2 + THEN 'LOW' + ELSE 'VERY_LOW' + END AS experience_breadth, + + /* Leadership tendency */ + CASE + WHEN total_leadership_days > 1200 THEN 'SIGNIFICANT_LEADERSHIP' + WHEN total_leadership_days BETWEEN 600 AND 1200 THEN 'MODERATE_LEADERSHIP' + WHEN total_leadership_days BETWEEN 200 AND 600 THEN 'SOME_LEADERSHIP' + ELSE 'NO_LEADERSHIP' + END AS leadership_profile, + + /* Role stability */ + CASE + WHEN total_substitute_days::float / NULLIF(total_days, 0) > 0.5 THEN 'PRIMARILY_SUBSTITUTE' + WHEN total_substitute_days::float / NULLIF(total_days, 0) > 0.3 THEN 'FREQUENT_SUBSTITUTE' + WHEN total_substitute_days::float / NULLIF(total_days, 0) > 0.1 THEN 'OCCASIONAL_SUBSTITUTE' + ELSE 'REGULAR_ROLES' + END AS role_stability, + + /* Career phase */ + CASE + WHEN total_weighted_exp > 120000 THEN 'SENIOR_STATESPERSON' + WHEN total_weighted_exp BETWEEN 60000 AND 120000 THEN 'ESTABLISHED_POLITICIAN' + WHEN total_weighted_exp BETWEEN 20000 AND 60000 THEN 'EXPERIENCED_POLITICIAN' + WHEN total_weighted_exp BETWEEN 7000 AND 20000 THEN 'MID_CAREER' + ELSE 'EARLY_CAREER' + END AS career_phase, + + /* Specialization score */ + CASE + WHEN ( + SELECT COUNT(DISTINCT area) + FROM jsonb_array_elements(knowledge_areas::jsonb) AS ka(area) + ) <= 2 AND total_days > 1000 THEN 'HIGHLY_SPECIALIZED' + WHEN ( + SELECT COUNT(DISTINCT area) + FROM jsonb_array_elements(knowledge_areas::jsonb) AS ka(area) + ) <= 4 THEN 'MODERATELY_SPECIALIZED' + ELSE 'BROADLY_EXPERIENCED' + END AS specialization_level + FROM experience_summary es +) +SELECT + person_id, + first_name, + last_name, + total_days, + total_weighted_exp, + govt_days, + riksdag_days, + party_days, + committee_days, + total_substitute_days, + total_leadership_days, + knowledge_areas::text AS knowledge_areas_json, + roles::text AS roles_json, + experience_level, + experience_breadth, + leadership_profile, + role_stability, + career_phase, + specialization_level, + + /* Generate detailed political analyst comment */ + CONCAT_WS(' || ', + /* Basic Experience Summary */ + CASE experience_level + WHEN 'EXTENSIVE_EXPERIENCE' THEN 'Distinguished career spanning government, parliament, and committees' + WHEN 'SIGNIFICANT_GOVERNMENT' THEN 'Notable government service record' + WHEN 'LONG_SERVING_PARLIAMENT' THEN 'Long-standing parliamentary experience' + WHEN 'ACTIVE_COMMITTEES' THEN 'Significant committee work experience' + WHEN 'PARTY_LEADERSHIP' THEN 'Strong party leadership background' + ELSE 'Diverse political experience' + END, + + /* Experience Breadth Analysis */ + CASE experience_breadth + WHEN 'HIGH' THEN 'Demonstrates broad political competence across multiple domains' + WHEN 'MEDIUM' THEN 'Shows focused expertise in select political areas' + ELSE 'Specialized in specific political domain' + END, + + /* Leadership Commentary */ + CASE leadership_profile + WHEN 'SIGNIFICANT_LEADERSHIP' THEN 'Extensive leadership experience with over 1000 days in key positions' + WHEN 'MODERATE_LEADERSHIP' THEN 'Proven leadership capabilities with over 500 days in leadership roles' + WHEN 'SOME_LEADERSHIP' THEN 'Some leadership experience' + ELSE 'Primarily collaborative roles' + END, + + /* Role Stability Analysis */ + CASE role_stability + WHEN 'PRIMARILY_SUBSTITUTE' THEN 'Frequently serves in substitute positions, showing adaptability' + WHEN 'FREQUENT_SUBSTITUTE' THEN 'Regular substitute experience complementing primary roles' + WHEN 'OCCASIONAL_SUBSTITUTE' THEN 'Mainly stable positions with occasional substitute duties' + ELSE 'Consistent role appointments' + END, + + /* Career Phase Insight */ + CASE career_phase + WHEN 'SENIOR_STATESPERSON' THEN 'Senior political figure with extensive influence' + WHEN 'ESTABLISHED_POLITICIAN' THEN 'Well-established political career' + WHEN 'EXPERIENCED_POLITICIAN' THEN 'Seasoned political operator' + WHEN 'MID_CAREER' THEN 'Building significant political experience' + ELSE 'Developing political career' + END, + + /* Specialization Commentary */ + CASE specialization_level + WHEN 'HIGHLY_SPECIALIZED' THEN 'Deep expertise in specific policy areas' + WHEN 'MODERATELY_SPECIALIZED' THEN 'Balanced mix of specialized knowledge and broader experience' + ELSE 'Broad political portfolio' + END + ) AS political_analysis_comment + +FROM political_analysis +ORDER BY total_weighted_exp DESC; + ]]> + + + \ No newline at end of file