fix(time-tracking): recalculate duration when start/end time is edited

- TimeTrackingService.update_entry() now calls calculate_duration() when
  start_time or end_time is changed so duration_seconds stays correct.
- Add test_update_entry_recalculates_duration_when_start_end_edited (fixes #451).
This commit is contained in:
Dries Peeters
2026-01-26 14:47:31 +01:00
parent 12074fc29b
commit 259c28e266
2 changed files with 28 additions and 0 deletions
+3
View File
@@ -383,6 +383,9 @@ class TimeTrackingService:
entry.start_time = start_time
if end_time is not None:
entry.end_time = end_time
# Recompute stored duration when start or end time changed
if entry.end_time and (start_time is not None or end_time is not None):
entry.calculate_duration()
if notes is not None:
entry.notes = notes
if tags is not None:
@@ -23,6 +23,31 @@ class TestTimeTrackingServiceComplete:
assert result["entry"].notes == "Updated notes"
assert result["entry"].billable is False
def test_update_entry_recalculates_duration_when_start_end_edited(self, app, user, project, time_entry):
"""Duration should be recomputed when start_time or end_time is updated (issue #451)."""
service = TimeTrackingService()
old_duration = time_entry.duration_seconds
# Change start/end so the span is exactly 15 minutes
new_start = time_entry.start_time.replace(minute=0, second=0, microsecond=0)
new_end = new_start + timedelta(minutes=15)
expected_seconds = 15 * 60 # 900
result = service.update_entry(
entry_id=time_entry.id,
user_id=user.id,
is_admin=False,
start_time=new_start,
end_time=new_end,
)
assert result["success"] is True
assert result["entry"].start_time == new_start
assert result["entry"].end_time == new_end
assert result["entry"].duration_seconds == expected_seconds, (
f"duration_seconds should be {expected_seconds} after editing start/end, got {result['entry'].duration_seconds} (old was {old_duration})"
)
def test_update_entry_not_found(self, app, user):
"""Test update with non-existent entry"""
service = TimeTrackingService()