diff --git a/db/query/exam_prep_catalog_courses.sql b/db/query/exam_prep_catalog_courses.sql index aaab51f..193a0be 100644 --- a/db/query/exam_prep_catalog_courses.sql +++ b/db/query/exam_prep_catalog_courses.sql @@ -17,6 +17,17 @@ FROM exam_prep.catalog_courses WHERE id = $1; -- name: ExamPrepListCatalogCourses :many +WITH catalog_course_counts AS ( + SELECT + u.catalog_course_id, + COUNT(DISTINCT u.id)::BIGINT AS units_count, + COUNT(DISTINCT m.id)::BIGINT AS modules_count, + COUNT(DISTINCT l.id)::BIGINT AS lessons_count + FROM exam_prep.units u + LEFT JOIN exam_prep.unit_modules m ON m.unit_id = u.id + LEFT JOIN exam_prep.unit_module_lessons l ON l.unit_module_id = m.id + GROUP BY u.catalog_course_id +) SELECT COUNT(*) OVER () AS total_count, c.id, @@ -24,9 +35,13 @@ SELECT c.description, c.thumbnail, c.sort_order, + COALESCE(cc.units_count, 0)::BIGINT AS units_count, + COALESCE(cc.modules_count, 0)::BIGINT AS modules_count, + COALESCE(cc.lessons_count, 0)::BIGINT AS lessons_count, c.created_at, c.updated_at FROM exam_prep.catalog_courses c +LEFT JOIN catalog_course_counts cc ON cc.catalog_course_id = c.id ORDER BY c.sort_order ASC, c.id ASC LIMIT $1 OFFSET $2; diff --git a/gen/db/exam_prep_catalog_courses.sql.go b/gen/db/exam_prep_catalog_courses.sql.go index 44a9e92..ac6b982 100644 --- a/gen/db/exam_prep_catalog_courses.sql.go +++ b/gen/db/exam_prep_catalog_courses.sql.go @@ -105,6 +105,17 @@ func (q *Queries) ExamPrepListAllCatalogCourseIDs(ctx context.Context) ([]int64, } const ExamPrepListCatalogCourses = `-- name: ExamPrepListCatalogCourses :many +WITH catalog_course_counts AS ( + SELECT + u.catalog_course_id, + COUNT(DISTINCT u.id)::BIGINT AS units_count, + COUNT(DISTINCT m.id)::BIGINT AS modules_count, + COUNT(DISTINCT l.id)::BIGINT AS lessons_count + FROM exam_prep.units u + LEFT JOIN exam_prep.unit_modules m ON m.unit_id = u.id + LEFT JOIN exam_prep.unit_module_lessons l ON l.unit_module_id = m.id + GROUP BY u.catalog_course_id +) SELECT COUNT(*) OVER () AS total_count, c.id, @@ -112,9 +123,13 @@ SELECT c.description, c.thumbnail, c.sort_order, + COALESCE(cc.units_count, 0)::BIGINT AS units_count, + COALESCE(cc.modules_count, 0)::BIGINT AS modules_count, + COALESCE(cc.lessons_count, 0)::BIGINT AS lessons_count, c.created_at, c.updated_at FROM exam_prep.catalog_courses c +LEFT JOIN catalog_course_counts cc ON cc.catalog_course_id = c.id ORDER BY c.sort_order ASC, c.id ASC LIMIT $1 OFFSET $2 ` @@ -125,14 +140,17 @@ type ExamPrepListCatalogCoursesParams struct { } type ExamPrepListCatalogCoursesRow struct { - TotalCount int64 `json:"total_count"` - ID int64 `json:"id"` - Name string `json:"name"` - Description pgtype.Text `json:"description"` - Thumbnail pgtype.Text `json:"thumbnail"` - SortOrder int32 `json:"sort_order"` - CreatedAt pgtype.Timestamptz `json:"created_at"` - UpdatedAt pgtype.Timestamptz `json:"updated_at"` + TotalCount int64 `json:"total_count"` + ID int64 `json:"id"` + Name string `json:"name"` + Description pgtype.Text `json:"description"` + Thumbnail pgtype.Text `json:"thumbnail"` + SortOrder int32 `json:"sort_order"` + UnitsCount int64 `json:"units_count"` + ModulesCount int64 `json:"modules_count"` + LessonsCount int64 `json:"lessons_count"` + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` } func (q *Queries) ExamPrepListCatalogCourses(ctx context.Context, arg ExamPrepListCatalogCoursesParams) ([]ExamPrepListCatalogCoursesRow, error) { @@ -151,6 +169,9 @@ func (q *Queries) ExamPrepListCatalogCourses(ctx context.Context, arg ExamPrepLi &i.Description, &i.Thumbnail, &i.SortOrder, + &i.UnitsCount, + &i.ModulesCount, + &i.LessonsCount, &i.CreatedAt, &i.UpdatedAt, ); err != nil { diff --git a/internal/domain/exam_prep_catalog_course.go b/internal/domain/exam_prep_catalog_course.go index 2095f78..e0d6aaa 100644 --- a/internal/domain/exam_prep_catalog_course.go +++ b/internal/domain/exam_prep_catalog_course.go @@ -4,13 +4,16 @@ import "time" // ExamPrepCatalogCourse is a top-level exam-prep track (e.g. DET, IELTS) in schema exam_prep — separate from LMS Learn English courses. type ExamPrepCatalogCourse struct { - ID int64 `json:"id"` - Name string `json:"name"` - Description *string `json:"description,omitempty"` - Thumbnail *string `json:"thumbnail,omitempty"` - SortOrder int `json:"sort_order"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` + ID int64 `json:"id"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Thumbnail *string `json:"thumbnail,omitempty"` + SortOrder int `json:"sort_order"` + UnitsCount *int64 `json:"units_count,omitempty"` + ModulesCount *int64 `json:"modules_count,omitempty"` + LessonsCount *int64 `json:"lessons_count,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` } type CreateExamPrepCatalogCourseInput struct { diff --git a/internal/repository/exam_prep_catalog_courses.go b/internal/repository/exam_prep_catalog_courses.go index 98e9383..1ae5cd8 100644 --- a/internal/repository/exam_prep_catalog_courses.go +++ b/internal/repository/exam_prep_catalog_courses.go @@ -67,7 +67,7 @@ func (s *Store) ListExamPrepCatalogCourses(ctx context.Context, limit, offset in if i == 0 { total = r.TotalCount } - out = append(out, examPrepCatalogCourseToDomain(dbgen.ExamPrepCatalogCourse{ + item := examPrepCatalogCourseToDomain(dbgen.ExamPrepCatalogCourse{ ID: r.ID, Name: r.Name, Description: r.Description, @@ -75,7 +75,11 @@ func (s *Store) ListExamPrepCatalogCourses(ctx context.Context, limit, offset in SortOrder: r.SortOrder, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt, - })) + }) + item.UnitsCount = &r.UnitsCount + item.ModulesCount = &r.ModulesCount + item.LessonsCount = &r.LessonsCount + out = append(out, item) } return out, total, nil }