Yimaru-BackEnd/internal/repository/exam_prep_catalog_courses.go
Yared Yemane e56bea3abf feat: add hierarchy publish status and resolve question type definition IDs
Extend DRAFT/PUBLISHED to programs, courses, modules, and exam-prep hierarchy entities with learner visibility gating and progress exclusion. Resolve question_type_definition_id in question responses for legacy system types and unlinked dynamic questions.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 02:40:16 -07:00

139 lines
4.3 KiB
Go

package repository
import (
"context"
"errors"
dbgen "Yimaru-Backend/gen/db"
"Yimaru-Backend/internal/domain"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
)
func examPrepCatalogCourseToDomain(c dbgen.ExamPrepCatalogCourse) domain.ExamPrepCatalogCourse {
out := domain.ExamPrepCatalogCourse{
ID: c.ID,
Name: c.Name,
Category: c.Category,
SortOrder: int(c.SortOrder),
PublishStatus: domain.ContentPublishStatusFromDB(c.PublishStatus),
}
out.Description = fromPgText(c.Description)
out.Thumbnail = fromPgText(c.Thumbnail)
out.CreatedAt = c.CreatedAt.Time
if c.UpdatedAt.Valid {
t := c.UpdatedAt.Time
out.UpdatedAt = &t
}
return out
}
func (s *Store) CreateExamPrepCatalogCourse(ctx context.Context, input domain.CreateExamPrepCatalogCourseInput) (domain.ExamPrepCatalogCourse, error) {
c, err := s.queries.ExamPrepCreateCatalogCourse(ctx, dbgen.ExamPrepCreateCatalogCourseParams{
Name: input.Name,
Description: toPgText(input.Description),
Category: input.Category,
Thumbnail: toPgText(input.Thumbnail),
PublishStatus: string(domain.ContentPublishStatusFromCreateInput(input.PublishStatus)),
})
if err != nil {
return domain.ExamPrepCatalogCourse{}, err
}
return examPrepCatalogCourseToDomain(c), nil
}
func (s *Store) GetExamPrepCatalogCourseByID(ctx context.Context, id int64) (domain.ExamPrepCatalogCourse, error) {
c, err := s.queries.ExamPrepGetCatalogCourseByID(ctx, id)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return domain.ExamPrepCatalogCourse{}, pgx.ErrNoRows
}
return domain.ExamPrepCatalogCourse{}, err
}
out := examPrepCatalogCourseToDomain(dbgen.ExamPrepCatalogCourse{
ID: c.ID,
Name: c.Name,
Description: c.Description,
Category: c.Category,
Thumbnail: c.Thumbnail,
SortOrder: c.SortOrder,
CreatedAt: c.CreatedAt,
UpdatedAt: c.UpdatedAt,
PublishStatus: c.PublishStatus,
})
out.HasPractice = c.HasPractice
return out, nil
}
func (s *Store) ListExamPrepCatalogCourses(ctx context.Context, publishedOnly bool, limit, offset int32) ([]domain.ExamPrepCatalogCourse, int64, error) {
rows, err := s.queries.ExamPrepListCatalogCourses(ctx, dbgen.ExamPrepListCatalogCoursesParams{
Limit: limit,
Offset: offset,
PublishedOnly: publishedOnly,
})
if err != nil {
return nil, 0, err
}
if len(rows) == 0 {
return []domain.ExamPrepCatalogCourse{}, 0, nil
}
var total int64
out := make([]domain.ExamPrepCatalogCourse, 0, len(rows))
for i, r := range rows {
if i == 0 {
total = r.TotalCount
}
item := examPrepCatalogCourseToDomain(dbgen.ExamPrepCatalogCourse{
ID: r.ID,
Name: r.Name,
Description: r.Description,
Category: r.Category,
Thumbnail: r.Thumbnail,
SortOrder: r.SortOrder,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
PublishStatus: r.PublishStatus,
})
item.UnitsCount = &r.UnitsCount
item.ModulesCount = &r.ModulesCount
item.LessonsCount = &r.LessonsCount
item.HasPractice = r.HasPractice
out = append(out, item)
}
return out, total, nil
}
func (s *Store) ListAllExamPrepCatalogCourseIDs(ctx context.Context) ([]int64, error) {
return s.queries.ExamPrepListAllCatalogCourseIDs(ctx)
}
func (s *Store) UpdateExamPrepCatalogCourse(ctx context.Context, id int64, input domain.UpdateExamPrepCatalogCourseInput) (domain.ExamPrepCatalogCourse, error) {
var nameText pgtype.Text
if input.Name != nil {
nameText = pgtype.Text{String: *input.Name, Valid: true}
} else {
nameText = pgtype.Text{Valid: false}
}
c, err := s.queries.ExamPrepUpdateCatalogCourse(ctx, dbgen.ExamPrepUpdateCatalogCourseParams{
ID: id,
Name: nameText,
Description: optionalTextUpdate(input.Description),
Category: optionalTextUpdate(input.Category),
Thumbnail: optionalTextUpdate(input.Thumbnail),
SortOrder: optionalInt4Update(input.SortOrder),
PublishStatus: optionalPublishStatusUpdate(input.PublishStatus),
})
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return domain.ExamPrepCatalogCourse{}, pgx.ErrNoRows
}
return domain.ExamPrepCatalogCourse{}, err
}
return examPrepCatalogCourseToDomain(c), nil
}
func (s *Store) DeleteExamPrepCatalogCourse(ctx context.Context, id int64) error {
return s.queries.ExamPrepDeleteCatalogCourse(ctx, id)
}