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 examPrepUnitToDomain(u dbgen.ExamPrepUnit) domain.ExamPrepUnit { out := domain.ExamPrepUnit{ ID: u.ID, CatalogCourseID: u.CatalogCourseID, Name: u.Name, SortOrder: int(u.SortOrder), } out.Description = fromPgText(u.Description) out.Thumbnail = fromPgText(u.Thumbnail) out.CreatedAt = u.CreatedAt.Time if u.UpdatedAt.Valid { t := u.UpdatedAt.Time out.UpdatedAt = &t } return out } func (s *Store) CreateExamPrepUnit(ctx context.Context, catalogCourseID int64, input domain.CreateExamPrepUnitInput) (domain.ExamPrepUnit, error) { if input.SortOrder != nil { q, tx, err := s.BeginTx(ctx) if err != nil { return domain.ExamPrepUnit{}, err } defer func() { _ = tx.Rollback(ctx) }() target := int32(*input.SortOrder) if _, err := tx.Exec(ctx, `UPDATE exam_prep.units SET sort_order = sort_order + 1 WHERE catalog_course_id = $1 AND sort_order >= $2`, catalogCourseID, target, ); err != nil { return domain.ExamPrepUnit{}, err } u, err := q.ExamPrepCreateUnit(ctx, dbgen.ExamPrepCreateUnitParams{ CatalogCourseID: catalogCourseID, Name: input.Name, Description: toPgText(input.Description), Thumbnail: toPgText(input.Thumbnail), SortOrder: pgtype.Int4{Int32: target, Valid: true}, }) if err != nil { return domain.ExamPrepUnit{}, err } if err := tx.Commit(ctx); err != nil { return domain.ExamPrepUnit{}, err } return examPrepUnitToDomain(u), nil } u, err := s.queries.ExamPrepCreateUnit(ctx, dbgen.ExamPrepCreateUnitParams{ CatalogCourseID: catalogCourseID, Name: input.Name, Description: toPgText(input.Description), Thumbnail: toPgText(input.Thumbnail), SortOrder: pgtype.Int4{Valid: false}, }) if err != nil { return domain.ExamPrepUnit{}, err } return examPrepUnitToDomain(u), nil } func (s *Store) GetExamPrepUnitByID(ctx context.Context, id int64) (domain.ExamPrepUnit, error) { u, err := s.queries.ExamPrepGetUnitByID(ctx, id) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return domain.ExamPrepUnit{}, pgx.ErrNoRows } return domain.ExamPrepUnit{}, err } out := examPrepUnitToDomain(dbgen.ExamPrepUnit{ ID: u.ID, CatalogCourseID: u.CatalogCourseID, Name: u.Name, Description: u.Description, Thumbnail: u.Thumbnail, SortOrder: u.SortOrder, CreatedAt: u.CreatedAt, UpdatedAt: u.UpdatedAt, }) out.HasPractice = u.HasPractice return out, nil } func (s *Store) ListExamPrepUnitsByCatalogCourse(ctx context.Context, catalogCourseID int64, limit, offset int32) ([]domain.ExamPrepUnit, int64, error) { rows, err := s.queries.ExamPrepListUnitsByCatalogCourse(ctx, dbgen.ExamPrepListUnitsByCatalogCourseParams{ CatalogCourseID: catalogCourseID, Limit: limit, Offset: offset, }) if err != nil { return nil, 0, err } if len(rows) == 0 { return []domain.ExamPrepUnit{}, 0, nil } var total int64 out := make([]domain.ExamPrepUnit, 0, len(rows)) for i, r := range rows { if i == 0 { total = r.TotalCount } item := examPrepUnitToDomain(dbgen.ExamPrepUnit{ ID: r.ID, CatalogCourseID: r.CatalogCourseID, Name: r.Name, Description: r.Description, Thumbnail: r.Thumbnail, SortOrder: r.SortOrder, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt, }) item.ModulesCount = &r.ModulesCount item.LessonsCount = &r.LessonsCount item.PracticesCount = &r.PracticesCount item.HasPractice = r.HasPractice out = append(out, item) } return out, total, nil } func (s *Store) ListExamPrepUnitIDsByCatalogCourse(ctx context.Context, catalogCourseID int64) ([]int64, error) { return s.queries.ExamPrepListUnitIDsByCatalogCourse(ctx, catalogCourseID) } func (s *Store) UpdateExamPrepUnit(ctx context.Context, id int64, input domain.UpdateExamPrepUnitInput) (domain.ExamPrepUnit, error) { var nameText pgtype.Text if input.Name != nil { nameText = pgtype.Text{String: *input.Name, Valid: true} } else { nameText = pgtype.Text{Valid: false} } u, err := s.queries.ExamPrepUpdateUnit(ctx, dbgen.ExamPrepUpdateUnitParams{ ID: id, Name: nameText, Description: optionalTextUpdate(input.Description), Thumbnail: optionalTextUpdate(input.Thumbnail), SortOrder: optionalInt4Update(input.SortOrder), }) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return domain.ExamPrepUnit{}, pgx.ErrNoRows } return domain.ExamPrepUnit{}, err } return examPrepUnitToDomain(u), nil } func (s *Store) DeleteExamPrepUnit(ctx context.Context, id int64) error { return s.queries.ExamPrepDeleteUnit(ctx, id) }