Compare commits
3 Commits
1026354c24
...
7ff0b639cf
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ff0b639cf | |||
| c5d3935062 | |||
| 518c3ee751 |
|
|
@ -0,0 +1,18 @@
|
|||
-- Restores legacy lesson columns. Rows will have NULL question_set_id until repopulated.
|
||||
|
||||
ALTER TABLE sub_module_lessons
|
||||
ADD COLUMN IF NOT EXISTS question_set_id BIGINT REFERENCES question_sets(id) ON DELETE CASCADE,
|
||||
ADD COLUMN IF NOT EXISTS intro_video_url TEXT;
|
||||
|
||||
UPDATE sub_module_lessons
|
||||
SET intro_video_url = teaching_video_url
|
||||
WHERE teaching_video_url IS NOT NULL;
|
||||
|
||||
ALTER TABLE sub_module_lessons
|
||||
DROP COLUMN IF EXISTS title,
|
||||
DROP COLUMN IF EXISTS description,
|
||||
DROP COLUMN IF EXISTS thumbnail,
|
||||
DROP COLUMN IF EXISTS teaching_text,
|
||||
DROP COLUMN IF EXISTS teaching_image_url,
|
||||
DROP COLUMN IF EXISTS teaching_audio_url,
|
||||
DROP COLUMN IF EXISTS teaching_video_url;
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
-- Lessons are teaching content only (text, images, audio, video, thumbnail).
|
||||
-- Question sets remain linked to practices, not lessons.
|
||||
|
||||
ALTER TABLE sub_module_lessons
|
||||
ADD COLUMN IF NOT EXISTS title VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS description TEXT,
|
||||
ADD COLUMN IF NOT EXISTS thumbnail TEXT,
|
||||
ADD COLUMN IF NOT EXISTS teaching_text TEXT,
|
||||
ADD COLUMN IF NOT EXISTS teaching_image_url TEXT,
|
||||
ADD COLUMN IF NOT EXISTS teaching_audio_url TEXT,
|
||||
ADD COLUMN IF NOT EXISTS teaching_video_url TEXT;
|
||||
|
||||
UPDATE sub_module_lessons sml
|
||||
SET
|
||||
title = qs.title,
|
||||
description = qs.description
|
||||
FROM question_sets qs
|
||||
WHERE sml.question_set_id IS NOT NULL
|
||||
AND qs.id = sml.question_set_id;
|
||||
|
||||
UPDATE sub_module_lessons
|
||||
SET title = 'Lesson'
|
||||
WHERE title IS NULL OR trim(title) = '';
|
||||
|
||||
UPDATE sub_module_lessons
|
||||
SET teaching_video_url = intro_video_url
|
||||
WHERE intro_video_url IS NOT NULL;
|
||||
|
||||
ALTER TABLE sub_module_lessons DROP CONSTRAINT IF EXISTS sub_module_lessons_question_set_id_fkey;
|
||||
ALTER TABLE sub_module_lessons DROP CONSTRAINT IF EXISTS sub_module_lessons_question_set_id_key;
|
||||
|
||||
ALTER TABLE sub_module_lessons DROP COLUMN IF EXISTS question_set_id;
|
||||
ALTER TABLE sub_module_lessons DROP COLUMN IF EXISTS intro_video_url;
|
||||
|
||||
ALTER TABLE sub_module_lessons
|
||||
ALTER COLUMN title SET NOT NULL,
|
||||
ALTER COLUMN title SET DEFAULT 'Lesson';
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE levels
|
||||
DROP COLUMN IF EXISTS title,
|
||||
DROP COLUMN IF EXISTS description,
|
||||
DROP COLUMN IF EXISTS thumbnail;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
ALTER TABLE levels
|
||||
ADD COLUMN IF NOT EXISTS title VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS description TEXT,
|
||||
ADD COLUMN IF NOT EXISTS thumbnail TEXT;
|
||||
|
||||
UPDATE levels
|
||||
SET title = cefr_level
|
||||
WHERE title IS NULL OR trim(title) = '';
|
||||
|
||||
ALTER TABLE levels
|
||||
ALTER COLUMN title SET NOT NULL;
|
||||
12
db/migrations/000035_sub_module_capstones.down.sql
Normal file
12
db/migrations/000035_sub_module_capstones.down.sql
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
DROP INDEX IF EXISTS idx_sub_module_capstones_sub_module_id;
|
||||
DROP TABLE IF EXISTS sub_module_capstones;
|
||||
|
||||
ALTER TABLE question_sets DROP CONSTRAINT IF EXISTS question_sets_set_type_check;
|
||||
ALTER TABLE question_sets ADD CONSTRAINT question_sets_set_type_check
|
||||
CHECK (set_type IN (
|
||||
'PRACTICE',
|
||||
'INITIAL_ASSESSMENT',
|
||||
'QUIZ',
|
||||
'EXAM',
|
||||
'SURVEY'
|
||||
));
|
||||
29
db/migrations/000035_sub_module_capstones.up.sql
Normal file
29
db/migrations/000035_sub_module_capstones.up.sql
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
-- Capstone assessments: sub-module scoped, backed by question_sets (type CAPSTONE).
|
||||
|
||||
ALTER TABLE question_sets DROP CONSTRAINT IF EXISTS question_sets_set_type_check;
|
||||
ALTER TABLE question_sets ADD CONSTRAINT question_sets_set_type_check
|
||||
CHECK (set_type IN (
|
||||
'PRACTICE',
|
||||
'INITIAL_ASSESSMENT',
|
||||
'QUIZ',
|
||||
'EXAM',
|
||||
'SURVEY',
|
||||
'CAPSTONE'
|
||||
));
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sub_module_capstones (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
sub_module_id BIGINT NOT NULL REFERENCES sub_modules(id) ON DELETE CASCADE,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
tips TEXT,
|
||||
thumbnail TEXT,
|
||||
question_set_id BIGINT NOT NULL REFERENCES question_sets(id) ON DELETE CASCADE,
|
||||
display_order INT NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (question_set_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sub_module_capstones_sub_module_id
|
||||
ON sub_module_capstones (sub_module_id);
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
DROP INDEX IF EXISTS idx_module_capstones_module_id;
|
||||
DROP TABLE IF EXISTS module_capstones;
|
||||
|
||||
ALTER TABLE modules DROP COLUMN IF EXISTS icon_url;
|
||||
19
db/migrations/000036_module_icon_and_module_capstones.up.sql
Normal file
19
db/migrations/000036_module_icon_and_module_capstones.up.sql
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
ALTER TABLE modules
|
||||
ADD COLUMN IF NOT EXISTS icon_url TEXT;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS module_capstones (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
module_id BIGINT NOT NULL REFERENCES modules(id) ON DELETE CASCADE,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
tips TEXT,
|
||||
thumbnail TEXT,
|
||||
question_set_id BIGINT NOT NULL REFERENCES question_sets(id) ON DELETE CASCADE,
|
||||
display_order INT NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (question_set_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_module_capstones_module_id
|
||||
ON module_capstones (module_id);
|
||||
3
db/migrations/000037_sub_modules_thumbnail_tips.down.sql
Normal file
3
db/migrations/000037_sub_modules_thumbnail_tips.down.sql
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE sub_modules
|
||||
DROP COLUMN IF EXISTS tips,
|
||||
DROP COLUMN IF EXISTS thumbnail;
|
||||
3
db/migrations/000037_sub_modules_thumbnail_tips.up.sql
Normal file
3
db/migrations/000037_sub_modules_thumbnail_tips.up.sql
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE sub_modules
|
||||
ADD COLUMN IF NOT EXISTS thumbnail TEXT,
|
||||
ADD COLUMN IF NOT EXISTS tips TEXT;
|
||||
|
|
@ -83,43 +83,17 @@ WHERE sub_module_id = $1
|
|||
ORDER BY display_order ASC, id ASC;
|
||||
|
||||
-- name: GetSubModuleLessons :many
|
||||
SELECT
|
||||
smp.id,
|
||||
smp.sub_module_id,
|
||||
smp.question_set_id,
|
||||
smp.intro_video_url,
|
||||
smp.display_order,
|
||||
smp.is_active,
|
||||
qs.title,
|
||||
qs.description,
|
||||
qs.status,
|
||||
qs.set_type,
|
||||
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
||||
FROM sub_module_lessons smp
|
||||
JOIN question_sets qs ON qs.id = smp.question_set_id
|
||||
WHERE smp.sub_module_id = $1
|
||||
AND smp.is_active = TRUE
|
||||
AND qs.set_type = 'QUIZ'
|
||||
ORDER BY smp.display_order ASC, smp.id ASC;
|
||||
SELECT *
|
||||
FROM sub_module_lessons
|
||||
WHERE sub_module_id = $1
|
||||
AND is_active = TRUE
|
||||
ORDER BY display_order ASC, id ASC;
|
||||
|
||||
-- name: GetSubModuleLessonByID :one
|
||||
SELECT
|
||||
smp.id,
|
||||
smp.sub_module_id,
|
||||
smp.question_set_id,
|
||||
smp.intro_video_url,
|
||||
smp.display_order,
|
||||
smp.is_active,
|
||||
qs.title,
|
||||
qs.description,
|
||||
qs.status,
|
||||
qs.set_type,
|
||||
(SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
|
||||
FROM sub_module_lessons smp
|
||||
JOIN question_sets qs ON qs.id = smp.question_set_id
|
||||
WHERE smp.id = $1
|
||||
AND smp.is_active = TRUE
|
||||
AND qs.set_type = 'QUIZ';
|
||||
SELECT *
|
||||
FROM sub_module_lessons
|
||||
WHERE id = $1
|
||||
AND is_active = TRUE;
|
||||
|
||||
-- name: GetSubModulePractices :many
|
||||
SELECT
|
||||
|
|
@ -162,16 +136,71 @@ WHERE smp.id = $1
|
|||
AND smp.is_active = TRUE
|
||||
AND qs.set_type = 'PRACTICE';
|
||||
|
||||
-- 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,
|
||||
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,
|
||||
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.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
|
||||
|
|
@ -232,10 +261,24 @@ OFFSET sqlc.narg('offset')::INT;
|
|||
INSERT INTO levels (
|
||||
course_id,
|
||||
cefr_level,
|
||||
title,
|
||||
description,
|
||||
thumbnail,
|
||||
display_order,
|
||||
is_active
|
||||
)
|
||||
VALUES ($1, $2, COALESCE($3, 0), COALESCE($4, TRUE))
|
||||
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
|
||||
|
|
@ -243,10 +286,22 @@ INSERT INTO modules (
|
|||
level_id,
|
||||
title,
|
||||
description,
|
||||
icon_url,
|
||||
display_order,
|
||||
is_active
|
||||
)
|
||||
VALUES ($1, $2, $3, COALESCE($4, 0), COALESCE($5, TRUE))
|
||||
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
|
||||
|
|
@ -254,10 +309,24 @@ INSERT INTO sub_modules (
|
|||
module_id,
|
||||
title,
|
||||
description,
|
||||
thumbnail,
|
||||
tips,
|
||||
display_order,
|
||||
is_active
|
||||
)
|
||||
VALUES ($1, $2, $3, COALESCE($4, 0), COALESCE($5, TRUE))
|
||||
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
|
||||
|
|
@ -289,26 +358,47 @@ VALUES (
|
|||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: AttachQuestionSetLessonToSubModule :one
|
||||
-- name: CreateSubModuleLesson :one
|
||||
INSERT INTO sub_module_lessons (
|
||||
sub_module_id,
|
||||
question_set_id,
|
||||
intro_video_url,
|
||||
title,
|
||||
description,
|
||||
thumbnail,
|
||||
teaching_text,
|
||||
teaching_image_url,
|
||||
teaching_audio_url,
|
||||
teaching_video_url,
|
||||
display_order,
|
||||
is_active
|
||||
)
|
||||
VALUES ($1, $2, $3, COALESCE($4, 0), COALESCE($5, TRUE))
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
COALESCE($9, 0),
|
||||
COALESCE($10, TRUE)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateSubModuleLesson :one
|
||||
UPDATE sub_module_lessons
|
||||
SET
|
||||
sub_module_id = $1,
|
||||
question_set_id = $2,
|
||||
intro_video_url = $3,
|
||||
display_order = $4,
|
||||
is_active = $5
|
||||
WHERE id = $6
|
||||
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
|
||||
WHERE id = $11
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateSubModulePractice :one
|
||||
|
|
@ -325,3 +415,102 @@ INSERT INTO sub_module_practices (
|
|||
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 0), COALESCE($8, TRUE))
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateSubModuleCapstone :one
|
||||
INSERT INTO sub_module_capstones (
|
||||
sub_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: UpdateSubModuleCapstone :one
|
||||
UPDATE sub_module_capstones
|
||||
SET
|
||||
title = $1,
|
||||
description = $2,
|
||||
tips = $3,
|
||||
thumbnail = $4,
|
||||
display_order = $5,
|
||||
is_active = $6
|
||||
WHERE id = $7
|
||||
RETURNING *;
|
||||
|
||||
-- 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 *;
|
||||
|
||||
|
|
|
|||
1803
docs/docs.go
1803
docs/docs.go
File diff suppressed because it is too large
Load Diff
1803
docs/swagger.json
1803
docs/swagger.json
File diff suppressed because it is too large
Load Diff
1211
docs/swagger.yaml
1211
docs/swagger.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
func (q *Queries) GetSubModuleByIDCompat(ctx context.Context, id int64) (SubModule, error) {
|
||||
row := q.db.QueryRow(ctx, `
|
||||
SELECT id, module_id, title, description, display_order, is_active, created_at, legacy_sub_course_id
|
||||
SELECT id, module_id, title, description, display_order, is_active, created_at, legacy_sub_course_id, thumbnail, tips
|
||||
FROM sub_modules
|
||||
WHERE id = $1
|
||||
`, id)
|
||||
|
|
@ -22,19 +22,24 @@ WHERE id = $1
|
|||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.LegacySubCourseID,
|
||||
&i.Thumbnail,
|
||||
&i.Tips,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSubModuleCompat(ctx context.Context, id int64, title string, description string, isActive bool) error {
|
||||
func (q *Queries) UpdateSubModuleCompat(ctx context.Context, id int64, title string, description string, thumbnail string, tips string, displayOrder int32, isActive bool) error {
|
||||
_, err := q.db.Exec(ctx, `
|
||||
UPDATE sub_modules
|
||||
SET
|
||||
title = $1,
|
||||
description = NULLIF($2, ''),
|
||||
is_active = $3
|
||||
WHERE id = $4
|
||||
`, title, description, isActive, id)
|
||||
thumbnail = NULLIF($3, ''),
|
||||
tips = NULLIF($4, ''),
|
||||
display_order = $5,
|
||||
is_active = $6
|
||||
WHERE id = $7
|
||||
`, title, description, thumbnail, tips, displayOrder, isActive, id)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +124,24 @@ func (q *Queries) DeletePracticeCompat(ctx context.Context, id int64) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// DeleteCapstoneCompat removes the backing question set (and cascades sub_module_capstones).
|
||||
func (q *Queries) DeleteCapstoneCompat(ctx context.Context, capstoneID int64) error {
|
||||
_, err := q.db.Exec(ctx, `
|
||||
DELETE FROM question_sets
|
||||
WHERE id = (SELECT question_set_id FROM sub_module_capstones WHERE id = $1)
|
||||
`, capstoneID)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteModuleCapstoneCompat removes the backing question set (and cascades module_capstones).
|
||||
func (q *Queries) DeleteModuleCapstoneCompat(ctx context.Context, capstoneID int64) error {
|
||||
_, err := q.db.Exec(ctx, `
|
||||
DELETE FROM question_sets
|
||||
WHERE id = (SELECT question_set_id FROM module_capstones WHERE id = $1)
|
||||
`, capstoneID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCourseCompat(
|
||||
ctx context.Context,
|
||||
categoryID int64,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -76,6 +76,9 @@ type Level struct {
|
|||
DisplayOrder int32 `json:"display_order"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
Title string `json:"title"`
|
||||
Description pgtype.Text `json:"description"`
|
||||
Thumbnail pgtype.Text `json:"thumbnail"`
|
||||
}
|
||||
|
||||
type LevelToSubCourse struct {
|
||||
|
|
@ -91,6 +94,20 @@ type Module struct {
|
|||
DisplayOrder int32 `json:"display_order"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
IconUrl pgtype.Text `json:"icon_url"`
|
||||
}
|
||||
|
||||
type ModuleCapstone struct {
|
||||
ID int64 `json:"id"`
|
||||
ModuleID int64 `json:"module_id"`
|
||||
Title string `json:"title"`
|
||||
Description pgtype.Text `json:"description"`
|
||||
Tips pgtype.Text `json:"tips"`
|
||||
Thumbnail pgtype.Text `json:"thumbnail"`
|
||||
QuestionSetID int64 `json:"question_set_id"`
|
||||
DisplayOrder int32 `json:"display_order"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type ModuleToSubCourse struct {
|
||||
|
|
@ -353,18 +370,38 @@ type SubModule struct {
|
|||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
LegacySubCourseID pgtype.Int8 `json:"legacy_sub_course_id"`
|
||||
Thumbnail pgtype.Text `json:"thumbnail"`
|
||||
Tips pgtype.Text `json:"tips"`
|
||||
}
|
||||
|
||||
type SubModuleLesson struct {
|
||||
type SubModuleCapstone struct {
|
||||
ID int64 `json:"id"`
|
||||
SubModuleID int64 `json:"sub_module_id"`
|
||||
Title string `json:"title"`
|
||||
Description pgtype.Text `json:"description"`
|
||||
Tips pgtype.Text `json:"tips"`
|
||||
Thumbnail pgtype.Text `json:"thumbnail"`
|
||||
QuestionSetID int64 `json:"question_set_id"`
|
||||
IntroVideoUrl pgtype.Text `json:"intro_video_url"`
|
||||
DisplayOrder int32 `json:"display_order"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type SubModuleLesson struct {
|
||||
ID int64 `json:"id"`
|
||||
SubModuleID int64 `json:"sub_module_id"`
|
||||
DisplayOrder int32 `json:"display_order"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
Title string `json:"title"`
|
||||
Description pgtype.Text `json:"description"`
|
||||
Thumbnail pgtype.Text `json:"thumbnail"`
|
||||
TeachingText pgtype.Text `json:"teaching_text"`
|
||||
TeachingImageUrl pgtype.Text `json:"teaching_image_url"`
|
||||
TeachingAudioUrl pgtype.Text `json:"teaching_audio_url"`
|
||||
TeachingVideoUrl pgtype.Text `json:"teaching_video_url"`
|
||||
}
|
||||
|
||||
type SubModulePractice struct {
|
||||
ID int64 `json:"id"`
|
||||
SubModuleID int64 `json:"sub_module_id"`
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ type LearningPathSubCourse struct {
|
|||
Title string `json:"title"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Thumbnail *string `json:"thumbnail,omitempty"`
|
||||
Tips *string `json:"tips,omitempty"`
|
||||
DisplayOrder int32 `json:"display_order"`
|
||||
Level string `json:"level"`
|
||||
SubLevel string `json:"sub_level"`
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ const (
|
|||
QuestionSetTypeQuiz QuestionSetType = "QUIZ"
|
||||
QuestionSetTypeExam QuestionSetType = "EXAM"
|
||||
QuestionSetTypeSurvey QuestionSetType = "SURVEY"
|
||||
QuestionSetTypeCapstone QuestionSetType = "CAPSTONE"
|
||||
)
|
||||
|
||||
type PracticeAccessBlock struct {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -515,7 +515,7 @@ func (h *Handler) DeleteQuestion(c *fiber.Ctx) error {
|
|||
type createQuestionSetReq struct {
|
||||
Title string `json:"title" validate:"required"`
|
||||
Description *string `json:"description"`
|
||||
SetType string `json:"set_type" validate:"required,oneof=PRACTICE INITIAL_ASSESSMENT QUIZ EXAM SURVEY"`
|
||||
SetType string `json:"set_type" validate:"required,oneof=PRACTICE INITIAL_ASSESSMENT QUIZ EXAM SURVEY CAPSTONE"`
|
||||
OwnerType *string `json:"owner_type"`
|
||||
OwnerID *int64 `json:"owner_id"`
|
||||
BannerImage *string `json:"banner_image"`
|
||||
|
|
@ -791,7 +791,7 @@ func (h *Handler) GetQuestionSetByID(c *fiber.Ctx) error {
|
|||
// @Description Returns a paginated list of question sets filtered by type
|
||||
// @Tags question-sets
|
||||
// @Produce json
|
||||
// @Param set_type query string true "Set type (PRACTICE, INITIAL_ASSESSMENT, QUIZ, EXAM, SURVEY)"
|
||||
// @Param set_type query string true "Set type (PRACTICE, INITIAL_ASSESSMENT, QUIZ, EXAM, SURVEY, CAPSTONE)"
|
||||
// @Param limit query int false "Limit" default(10)
|
||||
// @Param offset query int false "Offset" default(0)
|
||||
// @Success 200 {object} domain.Response
|
||||
|
|
|
|||
|
|
@ -108,7 +108,9 @@ func (a *App) initAppRoutes() {
|
|||
groupV1.Post("/course-management/sub-categories", a.authMiddleware, a.RequirePermission("course_categories.create"), h.CreateCourseSubCategory)
|
||||
groupV1.Delete("/course-management/sub-categories/:subCategoryId", a.authMiddleware, a.RequirePermission("course_categories.delete"), h.DeleteCourseSubCategory)
|
||||
groupV1.Post("/course-management/levels", a.authMiddleware, a.RequirePermission("subcourses.create"), h.CreateLevel)
|
||||
groupV1.Put("/course-management/levels/:levelId", a.authMiddleware, a.RequirePermission("subcourses.update"), h.UpdateLevel)
|
||||
groupV1.Post("/course-management/modules", a.authMiddleware, a.RequirePermission("subcourses.create"), h.CreateModule)
|
||||
groupV1.Put("/course-management/modules/:moduleId", a.authMiddleware, a.RequirePermission("subcourses.update"), h.UpdateModule)
|
||||
groupV1.Delete("/course-management/modules/:moduleId", a.authMiddleware, a.RequirePermission("subcourses.delete"), h.DeleteModule)
|
||||
groupV1.Post("/course-management/sub-modules", a.authMiddleware, a.RequirePermission("subcourses.create"), h.CreateSubModule)
|
||||
groupV1.Put("/course-management/sub-modules/:subModuleId", a.authMiddleware, a.RequirePermission("subcourses.update"), h.UpdateSubModule)
|
||||
|
|
@ -116,15 +118,25 @@ func (a *App) initAppRoutes() {
|
|||
groupV1.Post("/course-management/sub-module-videos", a.authMiddleware, a.RequirePermission("videos.create"), h.CreateSubModuleVideo)
|
||||
groupV1.Put("/course-management/sub-module-videos/:videoId", a.authMiddleware, a.RequirePermission("videos.update"), h.UpdateSubModuleVideo)
|
||||
groupV1.Delete("/course-management/sub-module-videos/:videoId", a.authMiddleware, a.RequirePermission("videos.delete"), h.DeleteSubModuleVideo)
|
||||
groupV1.Get("/course-management/sub-modules/:subModuleId/lessons", a.authMiddleware, a.RequirePermission("question_sets.list"), h.GetSubModuleLessons)
|
||||
groupV1.Get("/course-management/sub-module-lessons/:lessonId", a.authMiddleware, a.RequirePermission("question_sets.get"), h.GetSubModuleLessonByID)
|
||||
groupV1.Put("/course-management/sub-module-lessons/:lessonId", a.authMiddleware, a.RequirePermission("question_sets.update"), h.UpdateSubModuleLesson)
|
||||
groupV1.Post("/course-management/sub-module-lessons", a.authMiddleware, a.RequirePermission("question_sets.update"), h.AttachSubModuleLesson)
|
||||
groupV1.Get("/course-management/sub-modules/:subModuleId/lessons", a.authMiddleware, a.RequirePermission("learning_tree.get"), h.GetSubModuleLessons)
|
||||
groupV1.Get("/course-management/sub-module-lessons/:lessonId", a.authMiddleware, a.RequirePermission("learning_tree.get"), h.GetSubModuleLessonByID)
|
||||
groupV1.Put("/course-management/sub-module-lessons/:lessonId", a.authMiddleware, a.RequirePermission("subcourses.update"), h.UpdateSubModuleLesson)
|
||||
groupV1.Post("/course-management/sub-module-lessons", a.authMiddleware, a.RequirePermission("subcourses.create"), h.CreateSubModuleLesson)
|
||||
groupV1.Get("/course-management/sub-modules/:subModuleId/practices", a.authMiddleware, a.RequirePermission("question_sets.list"), h.GetSubModulePractices)
|
||||
groupV1.Get("/course-management/practices/:practiceId", a.authMiddleware, a.RequirePermission("question_sets.get"), h.GetSubModulePracticeByID)
|
||||
groupV1.Post("/course-management/sub-module-practices", a.authMiddleware, a.RequirePermission("question_sets.update"), h.CreateSubModulePractice)
|
||||
groupV1.Put("/course-management/practices/:practiceId", a.authMiddleware, a.RequirePermission("question_sets.update"), h.UpdatePractice)
|
||||
groupV1.Delete("/course-management/practices/:practiceId", a.authMiddleware, a.RequirePermission("question_sets.delete"), h.DeletePractice)
|
||||
groupV1.Get("/course-management/sub-modules/:subModuleId/capstones", a.authMiddleware, a.RequirePermission("question_sets.list"), h.GetSubModuleCapstones)
|
||||
groupV1.Get("/course-management/capstones/:capstoneId", a.authMiddleware, a.RequirePermission("question_sets.get"), h.GetSubModuleCapstoneByID)
|
||||
groupV1.Post("/course-management/sub-module-capstones", a.authMiddleware, a.RequirePermission("question_sets.update"), h.CreateSubModuleCapstone)
|
||||
groupV1.Put("/course-management/capstones/:capstoneId", a.authMiddleware, a.RequirePermission("question_sets.update"), h.UpdateSubModuleCapstone)
|
||||
groupV1.Delete("/course-management/capstones/:capstoneId", a.authMiddleware, a.RequirePermission("question_sets.delete"), h.DeleteCapstone)
|
||||
groupV1.Get("/course-management/modules/:moduleId/capstones", a.authMiddleware, a.RequirePermission("question_sets.list"), h.GetModuleCapstones)
|
||||
groupV1.Get("/course-management/module-capstones/:moduleCapstoneId", a.authMiddleware, a.RequirePermission("question_sets.get"), h.GetModuleCapstoneByID)
|
||||
groupV1.Post("/course-management/module-capstones", a.authMiddleware, a.RequirePermission("question_sets.update"), h.CreateModuleCapstone)
|
||||
groupV1.Put("/course-management/module-capstones/:moduleCapstoneId", a.authMiddleware, a.RequirePermission("question_sets.update"), h.UpdateModuleCapstone)
|
||||
groupV1.Delete("/course-management/module-capstones/:moduleCapstoneId", a.authMiddleware, a.RequirePermission("question_sets.delete"), h.DeleteModuleCapstone)
|
||||
|
||||
// Questions
|
||||
groupV1.Post("/questions", a.authMiddleware, a.RequirePermission("questions.create"), h.CreateQuestion)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user