@@ -383,15 +383,22 @@ async def update_task_locked_with_duration(
383383 try :
384384 # Fetch the last locked task history entry with raw SQL
385385 query = """
386- SELECT id, action_date
387- FROM task_history
388- WHERE task_id = :task_id
389- AND project_id = :project_id
390- AND action = :action
391- AND action_text IS NULL
392- AND user_id = :user_id
393- ORDER BY action_date DESC
394- LIMIT 1
386+ WITH locked_rows AS (
387+ SELECT
388+ id,
389+ action_date,
390+ COUNT(*) OVER() AS total_rows
391+ FROM task_history
392+ WHERE task_id = :task_id
393+ AND project_id = :project_id
394+ AND action = :action
395+ AND action_text IS NULL
396+ AND user_id = :user_id
397+ ORDER BY action_date DESC, id DESC
398+ FETCH FIRST 1 ROW ONLY
399+ )
400+ SELECT id, action_date, total_rows
401+ FROM locked_rows
395402 """
396403 values = {
397404 "task_id" : task_id ,
@@ -410,6 +417,9 @@ async def update_task_locked_with_duration(
410417 # No record found, possibly a race condition or auto-unlock scenario.
411418 return
412419
420+ if last_locked ["total_rows" ] > 1 :
421+ raise MultipleResultsFound ()
422+
413423 # Calculate the duration the task was locked for
414424 duration_task_locked = (
415425 datetime .datetime .utcnow () - last_locked ["action_date" ]
@@ -1183,6 +1193,14 @@ async def unlock_task(
11831193 ):
11841194 """Unlock the task and change its state."""
11851195 # Add task comment history if provided
1196+ if not undo :
1197+ last_history = await TaskHistory .get_last_action (project_id , task_id , db )
1198+ # To unlock a task the last action must have been either lock or extension
1199+ last_action = TaskAction [last_history .action ]
1200+ await TaskHistory .update_task_locked_with_duration (
1201+ task_id , project_id , last_action , user_id , db
1202+ )
1203+
11861204 if comment :
11871205 await Task .set_task_history (
11881206 task_id ,
@@ -1283,12 +1301,6 @@ async def unlock_task(
12831301 "project_id" : project_id ,
12841302 },
12851303 )
1286-
1287- # Update task locked duration in the history when `undo` is False
1288- # Using a slightly evil side effect of Actions and Statuses having the same name here :)
1289- await TaskHistory .update_task_locked_with_duration (
1290- task_id , project_id , TaskStatus (current_status ), user_id , db
1291- )
12921304 # Final query for updating task status
12931305 final_update_query = """
12941306 UPDATE tasks
@@ -1333,10 +1345,12 @@ async def reset_lock(
13331345 db = db ,
13341346 )
13351347 # Update task lock history with duration
1348+ last_history = await TaskHistory .get_last_action (project_id , task_id , db )
1349+ last_action = TaskAction [last_history .action ]
13361350 await TaskHistory .update_task_locked_with_duration (
13371351 task_id = task_id ,
13381352 project_id = project_id ,
1339- lock_action = TaskStatus ( task_status ) ,
1353+ lock_action = last_action ,
13401354 user_id = user_id ,
13411355 db = db ,
13421356 )
0 commit comments