149 lines
3.8 KiB
PL/PgSQL
149 lines
3.8 KiB
PL/PgSQL
-- Add sub-level support to sub_courses and enforce valid level/sub-level combinations.
|
|
ALTER TABLE sub_courses
|
|
ADD COLUMN sub_level VARCHAR(2);
|
|
|
|
UPDATE sub_courses
|
|
SET sub_level = CASE level
|
|
WHEN 'BEGINNER' THEN 'A1'
|
|
WHEN 'INTERMEDIATE' THEN 'B1'
|
|
WHEN 'ADVANCED' THEN 'C1'
|
|
ELSE 'A1'
|
|
END
|
|
WHERE sub_level IS NULL;
|
|
|
|
ALTER TABLE sub_courses
|
|
ALTER COLUMN sub_level SET NOT NULL;
|
|
|
|
ALTER TABLE sub_courses
|
|
ADD CONSTRAINT sub_courses_level_sub_level_check CHECK (
|
|
(level = 'BEGINNER' AND sub_level IN ('A1', 'A2', 'A3')) OR
|
|
(level = 'INTERMEDIATE' AND sub_level IN ('B1', 'B2', 'B3')) OR
|
|
(level = 'ADVANCED' AND sub_level IN ('C1', 'C2', 'C3'))
|
|
);
|
|
|
|
CREATE INDEX idx_sub_courses_level_sub_level ON sub_courses(level, sub_level);
|
|
|
|
-- Ensure each sub-course has an entry-assessment question set.
|
|
CREATE UNIQUE INDEX idx_question_sets_unique_subcourse_initial_assessment
|
|
ON question_sets(owner_type, owner_id, set_type)
|
|
WHERE owner_type = 'SUB_COURSE' AND set_type = 'INITIAL_ASSESSMENT' AND status != 'ARCHIVED';
|
|
|
|
CREATE OR REPLACE FUNCTION clone_default_initial_assessment_items(target_set_id BIGINT)
|
|
RETURNS VOID AS $$
|
|
DECLARE
|
|
template_set_id BIGINT;
|
|
BEGIN
|
|
SELECT id
|
|
INTO template_set_id
|
|
FROM question_sets
|
|
WHERE set_type = 'INITIAL_ASSESSMENT'
|
|
AND owner_type = 'STANDALONE'
|
|
AND status = 'PUBLISHED'
|
|
ORDER BY created_at DESC
|
|
LIMIT 1;
|
|
|
|
IF template_set_id IS NULL THEN
|
|
RETURN;
|
|
END IF;
|
|
|
|
INSERT INTO question_set_items (set_id, question_id, display_order)
|
|
SELECT target_set_id, qsi.question_id, qsi.display_order
|
|
FROM question_set_items qsi
|
|
WHERE qsi.set_id = template_set_id
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM question_set_items existing
|
|
WHERE existing.set_id = target_set_id
|
|
AND existing.question_id = qsi.question_id
|
|
);
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
INSERT INTO question_sets (
|
|
title,
|
|
description,
|
|
set_type,
|
|
owner_type,
|
|
owner_id,
|
|
shuffle_questions,
|
|
status
|
|
)
|
|
SELECT
|
|
sc.title || ' Entry Assessment',
|
|
'Entry assessment used to evaluate learners before joining this sub-course.',
|
|
'INITIAL_ASSESSMENT',
|
|
'SUB_COURSE',
|
|
sc.id,
|
|
false,
|
|
'DRAFT'
|
|
FROM sub_courses sc
|
|
WHERE NOT EXISTS (
|
|
SELECT 1
|
|
FROM question_sets qs
|
|
WHERE qs.owner_type = 'SUB_COURSE'
|
|
AND qs.owner_id = sc.id
|
|
AND qs.set_type = 'INITIAL_ASSESSMENT'
|
|
AND qs.status != 'ARCHIVED'
|
|
);
|
|
|
|
DO $$
|
|
DECLARE
|
|
r RECORD;
|
|
BEGIN
|
|
FOR r IN
|
|
SELECT id
|
|
FROM question_sets
|
|
WHERE owner_type = 'SUB_COURSE'
|
|
AND set_type = 'INITIAL_ASSESSMENT'
|
|
AND status != 'ARCHIVED'
|
|
LOOP
|
|
IF NOT EXISTS (SELECT 1 FROM question_set_items WHERE set_id = r.id) THEN
|
|
PERFORM clone_default_initial_assessment_items(r.id);
|
|
END IF;
|
|
END LOOP;
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION create_sub_course_entry_assessment()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
INSERT INTO question_sets (
|
|
title,
|
|
description,
|
|
set_type,
|
|
owner_type,
|
|
owner_id,
|
|
shuffle_questions,
|
|
status
|
|
)
|
|
VALUES (
|
|
NEW.title || ' Entry Assessment',
|
|
'Entry assessment used to evaluate learners before joining this sub-course.',
|
|
'INITIAL_ASSESSMENT',
|
|
'SUB_COURSE',
|
|
NEW.id,
|
|
false,
|
|
'DRAFT'
|
|
)
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
PERFORM clone_default_initial_assessment_items((
|
|
SELECT id
|
|
FROM question_sets
|
|
WHERE owner_type = 'SUB_COURSE'
|
|
AND owner_id = NEW.id
|
|
AND set_type = 'INITIAL_ASSESSMENT'
|
|
AND status != 'ARCHIVED'
|
|
ORDER BY created_at DESC
|
|
LIMIT 1
|
|
));
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER trg_sub_courses_create_entry_assessment
|
|
AFTER INSERT ON sub_courses
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION create_sub_course_entry_assessment();
|