4141 TimeEstimate * time.Duration `db:"time_estimate"`
4242 AssignedToID * gid.GID `db:"assigned_to_profile_id"`
4343 Deadline * time.Time `db:"deadline"`
44+ Priority int `db:"priority"`
4445 CreatedAt time.Time `db:"created_at"`
4546 UpdatedAt time.Time `db:"updated_at"`
4647 }
5051
5152func (c Task ) CursorKey (orderBy TaskOrderField ) page.CursorKey {
5253 switch orderBy {
54+ case TaskOrderFieldPriority :
55+ return page .NewCursorKey (c .ID , c .Priority )
5356 case TaskOrderFieldCreatedAt :
5457 return page .NewCursorKey (c .ID , c .CreatedAt )
5558 }
8992 time_estimate,
9093 assigned_to_profile_id,
9194 deadline,
95+ priority,
9296 created_at,
9397 updated_at
9498FROM
@@ -141,6 +145,7 @@ SELECT
141145 time_estimate,
142146 assigned_to_profile_id,
143147 deadline,
148+ priority,
144149 created_at,
145150 updated_at
146151FROM
@@ -170,12 +175,17 @@ WHERE
170175 return nil
171176}
172177
173- func (c Task ) Insert (
178+ func (c * Task ) Insert (
174179 ctx context.Context ,
175180 conn pg.Conn ,
176181 scope Scoper ,
177182) error {
178183 q := `
184+ WITH next_priority AS (
185+ SELECT COALESCE(MAX(priority), 0) + 1 AS value
186+ FROM tasks
187+ WHERE organization_id = @organization_id AND state = @state
188+ )
179189INSERT INTO
180190 tasks (
181191 tenant_id,
@@ -189,6 +199,7 @@ INSERT INTO
189199 time_estimate,
190200 assigned_to_profile_id,
191201 deadline,
202+ priority,
192203 created_at,
193204 updated_at
194205 )
@@ -204,9 +215,11 @@ VALUES (
204215 @time_estimate,
205216 @assigned_to_profile_id,
206217 @deadline,
218+ (SELECT value FROM next_priority),
207219 @created_at,
208220 @updated_at
209- );
221+ )
222+ RETURNING priority;
210223`
211224
212225 args := pgx.StrictNamedArgs {
@@ -224,8 +237,8 @@ VALUES (
224237 "created_at" : c .CreatedAt ,
225238 "updated_at" : c .UpdatedAt ,
226239 }
227- _ , err := conn .Exec (ctx , q , args )
228240
241+ err := conn .QueryRow (ctx , q , args ).Scan (& c .Priority )
229242 if err != nil {
230243 var pgErr * pgconn.PgError
231244 if errors .As (err , & pgErr ) {
@@ -245,6 +258,11 @@ func (c *Task) Upsert(
245258 scope Scoper ,
246259) error {
247260 q := `
261+ WITH next_priority AS (
262+ SELECT COALESCE(MAX(priority), 0) + 1 AS value
263+ FROM tasks
264+ WHERE organization_id = @organization_id AND state = @state
265+ )
248266INSERT INTO
249267 tasks (
250268 tenant_id,
@@ -258,6 +276,7 @@ INSERT INTO
258276 time_estimate,
259277 assigned_to_profile_id,
260278 deadline,
279+ priority,
261280 created_at,
262281 updated_at
263282 )
@@ -273,6 +292,7 @@ VALUES (
273292 @time_estimate,
274293 @assigned_to_profile_id,
275294 @deadline,
295+ (SELECT value FROM next_priority),
276296 @created_at,
277297 @updated_at
278298)
@@ -292,6 +312,7 @@ RETURNING
292312 time_estimate,
293313 assigned_to_profile_id,
294314 deadline,
315+ priority,
295316 created_at,
296317 updated_at
297318`
@@ -377,6 +398,7 @@ func (c *Tasks) LoadByOrganizationID(
377398 time_estimate,
378399 assigned_to_profile_id,
379400 deadline,
401+ priority,
380402 created_at,
381403 updated_at
382404 FROM
@@ -458,6 +480,7 @@ SELECT
458480 time_estimate,
459481 assigned_to_profile_id,
460482 deadline,
483+ priority,
461484 created_at,
462485 updated_at
463486FROM
@@ -525,6 +548,59 @@ WHERE %s
525548 return err
526549}
527550
551+ func (c * Task ) UpdatePriority (
552+ ctx context.Context ,
553+ conn pg.Conn ,
554+ scope Scoper ,
555+ ) error {
556+ q := `
557+ WITH old AS (
558+ SELECT
559+ priority AS old_priority
560+ FROM tasks
561+ WHERE %s AND id = @id AND organization_id = @organization_id AND state = @state
562+ )
563+
564+ UPDATE tasks
565+ SET
566+ priority = CASE
567+ WHEN id = @id THEN @new_priority
568+ ELSE priority + CASE
569+ WHEN @new_priority < old.old_priority THEN 1
570+ WHEN @new_priority > old.old_priority THEN -1
571+ END
572+ END,
573+ updated_at = @updated_at
574+ FROM old
575+ WHERE %s
576+ AND organization_id = @organization_id
577+ AND state = @state
578+ AND (
579+ id = @id
580+ OR (priority BETWEEN LEAST(old.old_priority, @new_priority) AND GREATEST(old.old_priority, @new_priority))
581+ );
582+ `
583+
584+ scopeFragment := scope .SQLFragment ()
585+ q = fmt .Sprintf (q , scopeFragment , scopeFragment )
586+
587+ args := pgx.StrictNamedArgs {
588+ "id" : c .ID ,
589+ "new_priority" : c .Priority ,
590+ "organization_id" : c .OrganizationID ,
591+ "state" : c .State ,
592+ "updated_at" : c .UpdatedAt ,
593+ }
594+ maps .Copy (args , scope .SQLArguments ())
595+
596+ _ , err := conn .Exec (ctx , q , args )
597+ if err != nil {
598+ return fmt .Errorf ("cannot update task priority: %w" , err )
599+ }
600+
601+ return nil
602+ }
603+
528604func (c * Task ) Delete (
529605 ctx context.Context ,
530606 conn pg.Conn ,
0 commit comments