Yimaru-BackEnd/internal/repository/exam_prep_reorder.go

114 lines
3.1 KiB
Go

package repository
import (
"context"
"fmt"
)
const lessonReorderSortBump int32 = 1_000_000
// ReorderExamPrepCatalogCourses sets sort_order to 1..n for all catalog course rows (transactional).
func (s *Store) ReorderExamPrepCatalogCourses(ctx context.Context, orderedIDs []int64) error {
tx, err := s.conn.Begin(ctx)
if err != nil {
return err
}
defer func() { _ = tx.Rollback(ctx) }()
for i, id := range orderedIDs {
tag, err := tx.Exec(ctx, `
UPDATE exam_prep.catalog_courses
SET sort_order = $1,
updated_at = CURRENT_TIMESTAMP
WHERE id = $2`, int32(i+1), id)
if err != nil {
return err
}
if tag.RowsAffected() == 0 {
return fmt.Errorf("exam prep catalog course id %d not found", id)
}
}
return tx.Commit(ctx)
}
// ReorderExamPrepUnitsInCatalogCourse sets sort_order to 1..n for units under catalogCourseID.
func (s *Store) ReorderExamPrepUnitsInCatalogCourse(ctx context.Context, catalogCourseID int64, orderedIDs []int64) error {
tx, err := s.conn.Begin(ctx)
if err != nil {
return err
}
defer func() { _ = tx.Rollback(ctx) }()
for i, id := range orderedIDs {
tag, err := tx.Exec(ctx, `
UPDATE exam_prep.units
SET sort_order = $1,
updated_at = CURRENT_TIMESTAMP
WHERE id = $2
AND catalog_course_id = $3`, int32(i+1), id, catalogCourseID)
if err != nil {
return err
}
if tag.RowsAffected() == 0 {
return fmt.Errorf("unit id %d not in catalog course %d", id, catalogCourseID)
}
}
return tx.Commit(ctx)
}
// ReorderExamPrepUnitModulesInUnit sets sort_order to 1..n for modules under unitID.
func (s *Store) ReorderExamPrepUnitModulesInUnit(ctx context.Context, unitID int64, orderedIDs []int64) error {
tx, err := s.conn.Begin(ctx)
if err != nil {
return err
}
defer func() { _ = tx.Rollback(ctx) }()
for i, id := range orderedIDs {
tag, err := tx.Exec(ctx, `
UPDATE exam_prep.unit_modules
SET sort_order = $1,
updated_at = CURRENT_TIMESTAMP
WHERE id = $2
AND unit_id = $3`, int32(i+1), id, unitID)
if err != nil {
return err
}
if tag.RowsAffected() == 0 {
return fmt.Errorf("module id %d not in unit %d", id, unitID)
}
}
return tx.Commit(ctx)
}
// ReorderExamPrepUnitModuleLessonsInUnitModule sets sort_order to 1..n under unitModuleID.
// Uses an intermediate bump so UNIQUE (unit_module_id, sort_order) is never violated mid-reorder.
func (s *Store) ReorderExamPrepUnitModuleLessonsInUnitModule(ctx context.Context, unitModuleID int64, orderedIDs []int64) error {
tx, err := s.conn.Begin(ctx)
if err != nil {
return err
}
defer func() { _ = tx.Rollback(ctx) }()
if _, err := tx.Exec(ctx, `
UPDATE exam_prep.unit_module_lessons
SET sort_order = sort_order + $1,
updated_at = CURRENT_TIMESTAMP
WHERE unit_module_id = $2`, lessonReorderSortBump, unitModuleID); err != nil {
return err
}
for i, id := range orderedIDs {
tag, err := tx.Exec(ctx, `
UPDATE exam_prep.unit_module_lessons
SET sort_order = $1,
updated_at = CURRENT_TIMESTAMP
WHERE id = $2
AND unit_module_id = $3`, int32(i+1), id, unitModuleID)
if err != nil {
return err
}
if tag.RowsAffected() == 0 {
return fmt.Errorf("lesson id %d not in exam prep module %d", id, unitModuleID)
}
}
return tx.Commit(ctx)
}