- GetSubModulePracticeByID matches sub_module_practices.id or question_set_id - Prefer primary id when both could match (ORDER BY + LIMIT 1) - Set Success/StatusCode on practice GET/detail and GetQuestionSetsByOwner Made-with: Cursor
587 lines
13 KiB
SQL
587 lines
13 KiB
SQL
-- name: GetCoursesWithHierarchy :many
|
|
SELECT
|
|
cc.id AS category_id,
|
|
cc.name AS category_name,
|
|
csc.id AS sub_category_id,
|
|
csc.name AS sub_category_name,
|
|
c.id AS course_id,
|
|
c.title AS course_title
|
|
FROM course_categories cc
|
|
LEFT JOIN course_sub_categories csc ON csc.category_id = cc.id AND csc.is_active = TRUE
|
|
LEFT JOIN courses c ON c.sub_category_id = csc.id AND c.is_active = TRUE
|
|
WHERE cc.is_active = TRUE
|
|
ORDER BY cc.id, csc.display_order, csc.id, c.id;
|
|
|
|
-- name: GetLevelsByCourseID :many
|
|
SELECT *
|
|
FROM levels
|
|
WHERE course_id = $1
|
|
AND is_active = TRUE
|
|
ORDER BY display_order ASC, id ASC;
|
|
|
|
-- name: GetAllLevels :many
|
|
SELECT
|
|
COUNT(*) OVER () AS total_count,
|
|
l.*
|
|
FROM levels l
|
|
ORDER BY l.display_order ASC, l.id ASC
|
|
LIMIT sqlc.narg('limit')::INT
|
|
OFFSET sqlc.narg('offset')::INT;
|
|
|
|
-- name: GetLevelByID :one
|
|
SELECT *
|
|
FROM levels
|
|
WHERE id = $1;
|
|
|
|
-- name: GetModulesByLevelID :many
|
|
SELECT *
|
|
FROM modules
|
|
WHERE level_id = $1
|
|
AND is_active = TRUE
|
|
ORDER BY display_order ASC, id ASC;
|
|
|
|
-- name: GetAllModules :many
|
|
SELECT
|
|
COUNT(*) OVER () AS total_count,
|
|
m.*
|
|
FROM modules m
|
|
ORDER BY m.display_order ASC, m.id ASC
|
|
LIMIT sqlc.narg('limit')::INT
|
|
OFFSET sqlc.narg('offset')::INT;
|
|
|
|
-- name: GetModuleByID :one
|
|
SELECT *
|
|
FROM modules
|
|
WHERE id = $1;
|
|
|
|
-- name: GetSubModulesByModuleID :many
|
|
SELECT *
|
|
FROM sub_modules
|
|
WHERE module_id = $1
|
|
AND is_active = TRUE
|
|
ORDER BY display_order ASC, id ASC;
|
|
|
|
-- name: GetAllSubModules :many
|
|
SELECT
|
|
COUNT(*) OVER () AS total_count,
|
|
sm.*
|
|
FROM sub_modules sm
|
|
ORDER BY sm.display_order ASC, sm.id ASC
|
|
LIMIT sqlc.narg('limit')::INT
|
|
OFFSET sqlc.narg('offset')::INT;
|
|
|
|
-- name: GetSubModuleByID :one
|
|
SELECT *
|
|
FROM sub_modules
|
|
WHERE id = $1;
|
|
|
|
-- name: GetSubModuleVideos :many
|
|
SELECT *
|
|
FROM sub_module_videos
|
|
WHERE sub_module_id = $1
|
|
AND status != 'ARCHIVED'
|
|
ORDER BY display_order ASC, id ASC;
|
|
|
|
-- name: GetSubModuleLessons :many
|
|
SELECT *
|
|
FROM sub_module_lessons
|
|
WHERE sub_module_id = $1
|
|
AND is_active = TRUE
|
|
ORDER BY display_order ASC, id ASC;
|
|
|
|
-- name: GetSubModuleLessonsAll :many
|
|
SELECT *
|
|
FROM sub_module_lessons
|
|
WHERE sub_module_id = $1
|
|
ORDER BY display_order ASC, id ASC;
|
|
|
|
-- name: GetSubModuleLessonByID :one
|
|
SELECT *
|
|
FROM sub_module_lessons
|
|
WHERE id = $1;
|
|
|
|
-- name: GetSubModulePractices :many
|
|
SELECT
|
|
smp.id,
|
|
smp.sub_module_id,
|
|
smp.title,
|
|
smp.description,
|
|
smp.thumbnail,
|
|
smp.intro_video_url,
|
|
smp.question_set_id,
|
|
smp.display_order,
|
|
smp.is_active,
|
|
smp.inactive_since,
|
|
qs.status,
|
|
qs.set_type,
|
|
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
|
FROM sub_module_practices smp
|
|
JOIN question_sets qs ON qs.id = smp.question_set_id
|
|
WHERE smp.sub_module_id = $1
|
|
AND smp.is_active = TRUE
|
|
ORDER BY smp.display_order ASC, smp.id ASC;
|
|
|
|
-- name: GetSubModulePracticeByID :one
|
|
SELECT
|
|
smp.id,
|
|
smp.sub_module_id,
|
|
smp.title,
|
|
smp.description,
|
|
smp.thumbnail,
|
|
smp.intro_video_url,
|
|
smp.question_set_id,
|
|
smp.display_order,
|
|
smp.is_active,
|
|
smp.inactive_since,
|
|
qs.status,
|
|
qs.set_type,
|
|
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
|
FROM sub_module_practices smp
|
|
JOIN question_sets qs ON qs.id = smp.question_set_id
|
|
WHERE smp.is_active = TRUE
|
|
AND (smp.id = $1 OR smp.question_set_id = $1)
|
|
ORDER BY (smp.id = $1) DESC
|
|
LIMIT 1;
|
|
|
|
-- name: GetSubModuleCapstones :many
|
|
SELECT
|
|
smc.id,
|
|
smc.sub_module_id,
|
|
smc.title,
|
|
smc.description,
|
|
smc.tips,
|
|
smc.thumbnail,
|
|
smc.question_set_id,
|
|
smc.display_order,
|
|
smc.is_active,
|
|
smc.inactive_since,
|
|
qs.status,
|
|
qs.set_type,
|
|
qs.time_limit_minutes,
|
|
qs.passing_score,
|
|
qs.shuffle_questions,
|
|
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
|
FROM sub_module_capstones smc
|
|
JOIN question_sets qs ON qs.id = smc.question_set_id
|
|
WHERE smc.sub_module_id = $1
|
|
AND smc.is_active = TRUE
|
|
AND qs.set_type = 'CAPSTONE'
|
|
ORDER BY smc.display_order ASC, smc.id ASC;
|
|
|
|
-- name: GetSubModuleCapstoneByID :one
|
|
SELECT
|
|
smc.id,
|
|
smc.sub_module_id,
|
|
smc.title,
|
|
smc.description,
|
|
smc.tips,
|
|
smc.thumbnail,
|
|
smc.question_set_id,
|
|
smc.display_order,
|
|
smc.is_active,
|
|
smc.inactive_since,
|
|
qs.status,
|
|
qs.set_type,
|
|
qs.time_limit_minutes,
|
|
qs.passing_score,
|
|
qs.shuffle_questions,
|
|
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
|
FROM sub_module_capstones smc
|
|
JOIN question_sets qs ON qs.id = smc.question_set_id
|
|
WHERE smc.id = $1
|
|
AND smc.is_active = TRUE
|
|
AND qs.set_type = 'CAPSTONE';
|
|
|
|
-- name: GetFullHierarchyByCourseID :many
|
|
SELECT
|
|
c.id AS course_id,
|
|
c.title AS course_title,
|
|
l.id AS level_id,
|
|
l.cefr_level,
|
|
l.title AS level_title,
|
|
l.description AS level_description,
|
|
l.thumbnail AS level_thumbnail,
|
|
m.id AS module_id,
|
|
m.title AS module_title,
|
|
m.icon_url AS module_icon_url,
|
|
sm.id AS sub_module_id,
|
|
sm.title AS sub_module_title,
|
|
sm.description AS sub_module_description,
|
|
sm.thumbnail AS sub_module_thumbnail,
|
|
sm.tips AS sub_module_tips,
|
|
sm.display_order AS sub_module_display_order
|
|
FROM courses c
|
|
LEFT JOIN levels l ON l.course_id = c.id AND l.is_active = TRUE
|
|
LEFT JOIN modules m ON m.level_id = l.id AND m.is_active = TRUE
|
|
LEFT JOIN sub_modules sm ON sm.module_id = m.id AND sm.is_active = TRUE
|
|
WHERE c.id = $1
|
|
ORDER BY l.display_order, l.id, m.display_order, m.id, sm.display_order, sm.id;
|
|
|
|
-- name: CreateCourseSubCategory :one
|
|
INSERT INTO course_sub_categories (
|
|
category_id,
|
|
name,
|
|
description,
|
|
display_order,
|
|
is_active
|
|
)
|
|
VALUES ($1, $2, $3, COALESCE($4, 0), COALESCE($5, TRUE))
|
|
RETURNING *;
|
|
|
|
-- name: GetCourseSubCategories :many
|
|
SELECT
|
|
COUNT(*) OVER () AS total_count,
|
|
csc.id,
|
|
csc.category_id,
|
|
cc.name AS category_name,
|
|
csc.name,
|
|
csc.description,
|
|
csc.display_order,
|
|
csc.is_active,
|
|
csc.created_at
|
|
FROM course_sub_categories csc
|
|
JOIN course_categories cc ON cc.id = csc.category_id
|
|
WHERE csc.is_active = TRUE
|
|
ORDER BY csc.display_order ASC, csc.id ASC
|
|
LIMIT sqlc.narg('limit')::INT
|
|
OFFSET sqlc.narg('offset')::INT;
|
|
|
|
-- name: GetCourseSubCategoriesByCategoryID :many
|
|
SELECT
|
|
COUNT(*) OVER () AS total_count,
|
|
csc.id,
|
|
csc.category_id,
|
|
cc.name AS category_name,
|
|
csc.name,
|
|
csc.description,
|
|
csc.display_order,
|
|
csc.is_active,
|
|
csc.created_at
|
|
FROM course_sub_categories csc
|
|
JOIN course_categories cc ON cc.id = csc.category_id
|
|
WHERE csc.category_id = $1
|
|
AND csc.is_active = TRUE
|
|
ORDER BY csc.display_order ASC, csc.id ASC
|
|
LIMIT sqlc.narg('limit')::INT
|
|
OFFSET sqlc.narg('offset')::INT;
|
|
|
|
-- name: GetHumanLanguageCourseSubCategories :many
|
|
SELECT
|
|
COUNT(*) OVER () AS total_count,
|
|
csc.id,
|
|
csc.category_id,
|
|
cc.name AS category_name,
|
|
csc.name,
|
|
csc.description,
|
|
csc.display_order,
|
|
csc.is_active,
|
|
csc.created_at
|
|
FROM course_sub_categories csc
|
|
JOIN course_categories cc ON cc.id = csc.category_id
|
|
WHERE csc.is_active = TRUE
|
|
AND cc.is_active = TRUE
|
|
AND lower(trim(cc.name)) = 'human language'
|
|
ORDER BY csc.display_order ASC, csc.id ASC
|
|
LIMIT sqlc.narg('limit')::INT
|
|
OFFSET sqlc.narg('offset')::INT;
|
|
|
|
-- name: CreateLevel :one
|
|
INSERT INTO levels (
|
|
course_id,
|
|
cefr_level,
|
|
title,
|
|
description,
|
|
thumbnail,
|
|
display_order,
|
|
is_active
|
|
)
|
|
VALUES ($1, $2, $3, $4, $5, COALESCE($6, 0), COALESCE($7, TRUE))
|
|
RETURNING *;
|
|
|
|
-- name: UpdateLevel :one
|
|
UPDATE levels
|
|
SET
|
|
title = $1,
|
|
description = $2,
|
|
thumbnail = $3,
|
|
display_order = $4,
|
|
is_active = $5
|
|
WHERE id = $6
|
|
RETURNING *;
|
|
|
|
-- name: CreateModule :one
|
|
INSERT INTO modules (
|
|
level_id,
|
|
title,
|
|
description,
|
|
icon_url,
|
|
display_order,
|
|
is_active
|
|
)
|
|
VALUES ($1, $2, $3, $4, COALESCE($5, 0), COALESCE($6, TRUE))
|
|
RETURNING *;
|
|
|
|
-- name: UpdateModule :one
|
|
UPDATE modules
|
|
SET
|
|
title = $1,
|
|
description = $2,
|
|
icon_url = $3,
|
|
display_order = $4,
|
|
is_active = $5
|
|
WHERE id = $6
|
|
RETURNING *;
|
|
|
|
-- name: CreateSubModule :one
|
|
INSERT INTO sub_modules (
|
|
module_id,
|
|
title,
|
|
description,
|
|
thumbnail,
|
|
tips,
|
|
display_order,
|
|
is_active
|
|
)
|
|
VALUES ($1, $2, $3, $4, $5, COALESCE($6, 0), COALESCE($7, TRUE))
|
|
RETURNING *;
|
|
|
|
-- name: UpdateSubModule :one
|
|
UPDATE sub_modules
|
|
SET
|
|
title = $1,
|
|
description = $2,
|
|
thumbnail = $3,
|
|
tips = $4,
|
|
display_order = $5,
|
|
is_active = $6
|
|
WHERE id = $7
|
|
RETURNING *;
|
|
|
|
-- name: CreateSubModuleVideo :one
|
|
INSERT INTO sub_module_videos (
|
|
sub_module_id,
|
|
title,
|
|
description,
|
|
video_url,
|
|
duration,
|
|
resolution,
|
|
is_published,
|
|
publish_date,
|
|
visibility,
|
|
instructor_id,
|
|
thumbnail,
|
|
display_order,
|
|
status,
|
|
vimeo_id,
|
|
vimeo_embed_url,
|
|
vimeo_player_html,
|
|
vimeo_status,
|
|
video_host_provider
|
|
)
|
|
VALUES (
|
|
$1, $2, $3, $4, $5, $6,
|
|
COALESCE($7, FALSE), $8, $9, $10, $11,
|
|
COALESCE($12, 0), COALESCE($13, 'DRAFT'),
|
|
$14, $15, $16, $17, COALESCE($18, 'DIRECT')
|
|
)
|
|
RETURNING *;
|
|
|
|
-- name: CreateSubModuleLesson :one
|
|
INSERT INTO sub_module_lessons (
|
|
sub_module_id,
|
|
title,
|
|
description,
|
|
thumbnail,
|
|
teaching_text,
|
|
teaching_image_url,
|
|
teaching_audio_url,
|
|
teaching_video_url,
|
|
display_order,
|
|
is_active,
|
|
inactive_since
|
|
)
|
|
VALUES (
|
|
$1,
|
|
$2,
|
|
$3,
|
|
$4,
|
|
$5,
|
|
$6,
|
|
$7,
|
|
$8,
|
|
COALESCE($9, 0),
|
|
COALESCE($10, TRUE),
|
|
CASE WHEN COALESCE($10, TRUE) THEN NULL ELSE NOW() END
|
|
)
|
|
RETURNING *;
|
|
|
|
-- name: UpdateSubModuleLesson :one
|
|
UPDATE sub_module_lessons
|
|
SET
|
|
sub_module_id = $1,
|
|
title = $2,
|
|
description = $3,
|
|
thumbnail = $4,
|
|
teaching_text = $5,
|
|
teaching_image_url = $6,
|
|
teaching_audio_url = $7,
|
|
teaching_video_url = $8,
|
|
display_order = $9,
|
|
is_active = $10,
|
|
inactive_since = CASE
|
|
WHEN $10 THEN NULL
|
|
WHEN is_active THEN NOW()
|
|
ELSE inactive_since
|
|
END
|
|
WHERE id = $11
|
|
RETURNING *;
|
|
|
|
-- name: CreateSubModulePractice :one
|
|
INSERT INTO sub_module_practices (
|
|
sub_module_id,
|
|
title,
|
|
description,
|
|
thumbnail,
|
|
intro_video_url,
|
|
question_set_id,
|
|
display_order,
|
|
is_active,
|
|
inactive_since
|
|
)
|
|
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 0), COALESCE($8, TRUE), CASE WHEN COALESCE($8, TRUE) THEN NULL ELSE NOW() END)
|
|
RETURNING *;
|
|
|
|
-- name: CreateSubModuleCapstone :one
|
|
INSERT INTO sub_module_capstones (
|
|
sub_module_id,
|
|
title,
|
|
description,
|
|
tips,
|
|
thumbnail,
|
|
question_set_id,
|
|
display_order,
|
|
is_active,
|
|
inactive_since
|
|
)
|
|
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 0), COALESCE($8, TRUE), CASE WHEN COALESCE($8, TRUE) THEN NULL ELSE NOW() END)
|
|
RETURNING *;
|
|
|
|
-- name: UpdateSubModuleCapstone :one
|
|
UPDATE sub_module_capstones
|
|
SET
|
|
title = $1,
|
|
description = $2,
|
|
tips = $3,
|
|
thumbnail = $4,
|
|
display_order = $5,
|
|
is_active = $6,
|
|
inactive_since = CASE
|
|
WHEN $6 THEN NULL
|
|
WHEN is_active THEN NOW()
|
|
ELSE inactive_since
|
|
END
|
|
WHERE id = $7
|
|
RETURNING *;
|
|
|
|
-- name: PurgeInactiveSubModuleLessonsBefore :execrows
|
|
DELETE FROM sub_module_lessons
|
|
WHERE is_active = FALSE
|
|
AND inactive_since IS NOT NULL
|
|
AND inactive_since < $1;
|
|
|
|
-- name: PurgeInactiveSubModulePracticesBefore :execrows
|
|
DELETE FROM question_sets qs
|
|
USING (
|
|
SELECT question_set_id
|
|
FROM sub_module_practices
|
|
WHERE is_active = FALSE
|
|
AND inactive_since IS NOT NULL
|
|
AND inactive_since < $1
|
|
) doomed
|
|
WHERE qs.id = doomed.question_set_id;
|
|
|
|
-- name: PurgeInactiveSubModuleCapstonesBefore :execrows
|
|
DELETE FROM question_sets qs
|
|
USING (
|
|
SELECT question_set_id
|
|
FROM sub_module_capstones
|
|
WHERE is_active = FALSE
|
|
AND inactive_since IS NOT NULL
|
|
AND inactive_since < $1
|
|
) doomed
|
|
WHERE qs.id = doomed.question_set_id;
|
|
|
|
-- name: GetModuleCapstones :many
|
|
SELECT
|
|
mc.id,
|
|
mc.module_id,
|
|
mc.title,
|
|
mc.description,
|
|
mc.tips,
|
|
mc.thumbnail,
|
|
mc.question_set_id,
|
|
mc.display_order,
|
|
mc.is_active,
|
|
qs.status,
|
|
qs.set_type,
|
|
qs.time_limit_minutes,
|
|
qs.passing_score,
|
|
qs.shuffle_questions,
|
|
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
|
FROM module_capstones mc
|
|
JOIN question_sets qs ON qs.id = mc.question_set_id
|
|
WHERE mc.module_id = $1
|
|
AND mc.is_active = TRUE
|
|
AND qs.set_type = 'CAPSTONE'
|
|
ORDER BY mc.display_order ASC, mc.id ASC;
|
|
|
|
-- name: GetModuleCapstoneByID :one
|
|
SELECT
|
|
mc.id,
|
|
mc.module_id,
|
|
mc.title,
|
|
mc.description,
|
|
mc.tips,
|
|
mc.thumbnail,
|
|
mc.question_set_id,
|
|
mc.display_order,
|
|
mc.is_active,
|
|
qs.status,
|
|
qs.set_type,
|
|
qs.time_limit_minutes,
|
|
qs.passing_score,
|
|
qs.shuffle_questions,
|
|
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
|
FROM module_capstones mc
|
|
JOIN question_sets qs ON qs.id = mc.question_set_id
|
|
WHERE mc.id = $1
|
|
AND mc.is_active = TRUE
|
|
AND qs.set_type = 'CAPSTONE';
|
|
|
|
-- name: CreateModuleCapstone :one
|
|
INSERT INTO module_capstones (
|
|
module_id,
|
|
title,
|
|
description,
|
|
tips,
|
|
thumbnail,
|
|
question_set_id,
|
|
display_order,
|
|
is_active
|
|
)
|
|
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 0), COALESCE($8, TRUE))
|
|
RETURNING *;
|
|
|
|
-- name: UpdateModuleCapstone :one
|
|
UPDATE module_capstones
|
|
SET
|
|
title = $1,
|
|
description = $2,
|
|
tips = $3,
|
|
thumbnail = $4,
|
|
display_order = $5,
|
|
is_active = $6
|
|
WHERE id = $7
|
|
RETURNING *;
|
|
|