diff --git a/internal/repository/lms_reorder.go b/internal/repository/lms_reorder.go index 8093f89..8730217 100644 --- a/internal/repository/lms_reorder.go +++ b/internal/repository/lms_reorder.go @@ -6,12 +6,21 @@ import ( ) // ReorderPrograms sets sort_order to 1..n in the given order (transactional). +// Uses an intermediate bump so UNIQUE (sort_order) is never violated mid-reorder. func (s *Store) ReorderPrograms(ctx context.Context, 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 programs +SET sort_order = sort_order + $1, + updated_at = CURRENT_TIMESTAMP`, lessonReorderSortBump); err != nil { + return err + } + for i, id := range orderedIDs { tag, err := tx.Exec(ctx, `UPDATE programs SET sort_order = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2`, int32(i+1), id) if err != nil { @@ -25,12 +34,22 @@ func (s *Store) ReorderPrograms(ctx context.Context, orderedIDs []int64) error { } // ReorderCoursesInProgram sets sort_order for courses under programID (transactional). +// Uses an intermediate bump so UNIQUE (program_id, sort_order) is never violated mid-reorder. func (s *Store) ReorderCoursesInProgram(ctx context.Context, programID 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 courses +SET sort_order = sort_order + $1, + updated_at = CURRENT_TIMESTAMP +WHERE program_id = $2`, lessonReorderSortBump, programID); err != nil { + return err + } + for i, id := range orderedIDs { tag, err := tx.Exec(ctx, ` UPDATE courses @@ -49,12 +68,22 @@ WHERE id = $2 } // ReorderModulesInCourse sets sort_order for modules under courseID (transactional). +// Uses an intermediate bump so UNIQUE (course_id, sort_order) is never violated mid-reorder. func (s *Store) ReorderModulesInCourse(ctx context.Context, courseID 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 modules +SET sort_order = sort_order + $1, + updated_at = CURRENT_TIMESTAMP +WHERE course_id = $2`, lessonReorderSortBump, courseID); err != nil { + return err + } + for i, id := range orderedIDs { tag, err := tx.Exec(ctx, ` UPDATE modules