Skip to content

Commit f755a88

Browse files
feat: use updatedAt as default sorting for all tasks (#244)
1 parent b731fe9 commit f755a88

File tree

7 files changed

+42
-15
lines changed

7 files changed

+42
-15
lines changed

todo/constants/task.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ class TaskPriority(Enum):
1818
SORT_FIELD_PRIORITY = "priority"
1919
SORT_FIELD_DUE_AT = "dueAt"
2020
SORT_FIELD_CREATED_AT = "createdAt"
21+
SORT_FIELD_UPDATED_AT = "updatedAt"
2122
SORT_FIELD_ASSIGNEE = "assignee"
2223

2324
SORT_FIELDS = [
2425
SORT_FIELD_PRIORITY,
2526
SORT_FIELD_DUE_AT,
2627
SORT_FIELD_CREATED_AT,
28+
SORT_FIELD_UPDATED_AT,
2729
SORT_FIELD_ASSIGNEE,
2830
]
2931

@@ -38,6 +40,7 @@ class TaskPriority(Enum):
3840

3941
SORT_FIELD_DEFAULT_ORDERS = {
4042
SORT_FIELD_CREATED_AT: SORT_ORDER_DESC,
43+
SORT_FIELD_UPDATED_AT: SORT_ORDER_DESC,
4144
SORT_FIELD_DUE_AT: SORT_ORDER_ASC,
4245
SORT_FIELD_PRIORITY: SORT_ORDER_DESC,
4346
SORT_FIELD_ASSIGNEE: SORT_ORDER_ASC,

todo/repositories/task_repository.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
from todo.repositories.common.mongo_repository import MongoRepository
99
from todo.repositories.task_assignment_repository import TaskAssignmentRepository
1010
from todo.constants.messages import ApiErrors, RepositoryErrors
11-
from todo.constants.task import SORT_FIELD_PRIORITY, SORT_FIELD_ASSIGNEE, SORT_ORDER_DESC, TaskStatus
11+
from todo.constants.task import (
12+
SORT_FIELD_PRIORITY,
13+
SORT_FIELD_ASSIGNEE,
14+
SORT_FIELD_UPDATED_AT,
15+
SORT_ORDER_DESC,
16+
TaskStatus,
17+
)
1218
from todo.repositories.team_repository import UserTeamDetailsRepository
1319

1420

@@ -78,6 +84,19 @@ def list(
7884
else:
7985
query_filter = base_filter
8086

87+
if sort_by == SORT_FIELD_UPDATED_AT:
88+
sort_direction = -1 if order == SORT_ORDER_DESC else 1
89+
pipeline = [
90+
{"$match": query_filter},
91+
{"$addFields": {"lastActivity": {"$ifNull": [{"$toDate": "$updatedAt"}, {"$toDate": "$createdAt"}]}}},
92+
{"$sort": {"lastActivity": sort_direction}},
93+
{"$skip": (page - 1) * limit},
94+
{"$limit": limit},
95+
{"$project": {"lastActivity": 0}},
96+
]
97+
tasks_cursor = tasks_collection.aggregate(pipeline)
98+
return [TaskModel(**task) for task in tasks_cursor]
99+
81100
if sort_by == SORT_FIELD_PRIORITY:
82101
sort_direction = 1 if order == SORT_ORDER_DESC else -1
83102
sort_criteria = [(sort_by, sort_direction)]

todo/serializers/get_tasks_serializer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from rest_framework import serializers
22
from django.conf import settings
33

4-
from todo.constants.task import SORT_FIELDS, SORT_ORDERS, SORT_FIELD_CREATED_AT, SORT_FIELD_DEFAULT_ORDERS, TaskStatus
4+
from todo.constants.task import SORT_FIELDS, SORT_ORDERS, SORT_FIELD_UPDATED_AT, SORT_FIELD_DEFAULT_ORDERS, TaskStatus
55

66

77
class CaseInsensitiveChoiceField(serializers.ChoiceField):
@@ -35,7 +35,7 @@ class GetTaskQueryParamsSerializer(serializers.Serializer):
3535
sort_by = serializers.ChoiceField(
3636
choices=SORT_FIELDS,
3737
required=False,
38-
default=SORT_FIELD_CREATED_AT,
38+
default=SORT_FIELD_UPDATED_AT,
3939
)
4040
order = serializers.ChoiceField(
4141
choices=SORT_ORDERS,
@@ -54,7 +54,7 @@ def validate(self, attrs):
5454
validated_data = super().validate(attrs)
5555

5656
if "order" not in validated_data or validated_data["order"] is None:
57-
sort_by = validated_data.get("sort_by", SORT_FIELD_CREATED_AT)
57+
sort_by = validated_data.get("sort_by", SORT_FIELD_UPDATED_AT)
5858
validated_data["order"] = SORT_FIELD_DEFAULT_ORDERS[sort_by]
5959

6060
return validated_data

todo/tests/integration/test_task_sorting_integration.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
SORT_FIELD_PRIORITY,
66
SORT_FIELD_DUE_AT,
77
SORT_FIELD_CREATED_AT,
8+
SORT_FIELD_UPDATED_AT,
89
SORT_FIELD_ASSIGNEE,
910
SORT_ORDER_ASC,
1011
SORT_ORDER_DESC,
@@ -65,6 +66,7 @@ def test_field_specific_defaults_integration(self, mock_list, mock_count):
6566

6667
test_cases = [
6768
(SORT_FIELD_CREATED_AT, SORT_ORDER_DESC),
69+
(SORT_FIELD_UPDATED_AT, SORT_ORDER_DESC),
6870
(SORT_FIELD_DUE_AT, SORT_ORDER_ASC),
6971
(SORT_FIELD_PRIORITY, SORT_ORDER_DESC),
7072
(SORT_FIELD_ASSIGNEE, SORT_ORDER_ASC),
@@ -114,7 +116,7 @@ def test_default_behavior_integration(self, mock_list, mock_count):
114116
self.assertEqual(response.status_code, status.HTTP_200_OK)
115117

116118
mock_list.assert_called_with(
117-
1, 20, SORT_FIELD_CREATED_AT, SORT_ORDER_DESC, str(self.user_id), team_id=None, status_filter=None
119+
1, 20, SORT_FIELD_UPDATED_AT, SORT_ORDER_DESC, str(self.user_id), team_id=None, status_filter=None
118120
)
119121

120122
@patch("todo.services.task_service.reverse_lazy", return_value="/v1/tasks")

todo/tests/integration/test_tasks_pagination.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_pagination_settings_integration(self, mock_get_tasks):
2323
mock_get_tasks.assert_called_with(
2424
page=1,
2525
limit=default_limit,
26-
sort_by="createdAt",
26+
sort_by="updatedAt",
2727
order="desc",
2828
user_id=str(self.user_id),
2929
team_id=None,
@@ -38,7 +38,7 @@ def test_pagination_settings_integration(self, mock_get_tasks):
3838
mock_get_tasks.assert_called_with(
3939
page=1,
4040
limit=10,
41-
sort_by="createdAt",
41+
sort_by="updatedAt",
4242
order="desc",
4343
user_id=str(self.user_id),
4444
team_id=None,

todo/tests/unit/serializers/test_get_tasks_serializer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
SORT_FIELD_PRIORITY,
88
SORT_FIELD_DUE_AT,
99
SORT_FIELD_CREATED_AT,
10+
SORT_FIELD_UPDATED_AT,
1011
SORT_FIELD_ASSIGNEE,
1112
SORT_ORDER_ASC,
1213
SORT_ORDER_DESC,
@@ -133,7 +134,7 @@ def test_invalid_order_value(self):
133134
def test_sort_by_defaults_to_created_at(self):
134135
serializer = GetTaskQueryParamsSerializer(data={})
135136
self.assertTrue(serializer.is_valid())
136-
self.assertEqual(serializer.validated_data["sort_by"], SORT_FIELD_CREATED_AT)
137+
self.assertEqual(serializer.validated_data["sort_by"], SORT_FIELD_UPDATED_AT)
137138

138139
def test_order_has_no_default(self):
139140
serializer = GetTaskQueryParamsSerializer(data={})
@@ -152,7 +153,7 @@ def test_sort_by_with_no_order(self):
152153
def test_order_with_no_sort_by(self):
153154
serializer = GetTaskQueryParamsSerializer(data={"order": SORT_ORDER_ASC})
154155
self.assertTrue(serializer.is_valid())
155-
self.assertEqual(serializer.validated_data["sort_by"], SORT_FIELD_CREATED_AT)
156+
self.assertEqual(serializer.validated_data["sort_by"], SORT_FIELD_UPDATED_AT)
156157
self.assertEqual(serializer.validated_data["order"], SORT_ORDER_ASC)
157158

158159
def test_sorting_with_pagination(self):

todo/tests/unit/views/test_task.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
SORT_FIELD_PRIORITY,
1919
SORT_FIELD_DUE_AT,
2020
SORT_FIELD_CREATED_AT,
21+
SORT_FIELD_UPDATED_AT,
2122
SORT_FIELD_ASSIGNEE,
2223
SORT_ORDER_ASC,
2324
SORT_ORDER_DESC,
@@ -47,7 +48,7 @@ def test_get_tasks_returns_200_for_valid_params(self, mock_get_tasks: Mock):
4748
mock_get_tasks.assert_called_once_with(
4849
page=1,
4950
limit=10,
50-
sort_by="createdAt",
51+
sort_by="updatedAt",
5152
order="desc",
5253
user_id=str(self.user_id),
5354
team_id=None,
@@ -66,7 +67,7 @@ def test_get_tasks_returns_200_without_params(self, mock_get_tasks: Mock):
6667
mock_get_tasks.assert_called_once_with(
6768
page=1,
6869
limit=default_limit,
69-
sort_by="createdAt",
70+
sort_by="updatedAt",
7071
order="desc",
7172
user_id=str(self.user_id),
7273
team_id=None,
@@ -177,7 +178,7 @@ def test_get_tasks_with_default_pagination(self, mock_get_tasks):
177178
mock_get_tasks.assert_called_once_with(
178179
page=1,
179180
limit=default_limit,
180-
sort_by="createdAt",
181+
sort_by="updatedAt",
181182
order="desc",
182183
user_id=str(self.user_id),
183184
team_id=None,
@@ -195,7 +196,7 @@ def test_get_tasks_with_valid_pagination(self, mock_get_tasks):
195196
mock_get_tasks.assert_called_once_with(
196197
page=2,
197198
limit=15,
198-
sort_by="createdAt",
199+
sort_by="updatedAt",
199200
order="desc",
200201
user_id=str(self.user_id),
201202
team_id=None,
@@ -275,6 +276,7 @@ def test_get_tasks_with_all_sort_fields(self, mock_get_tasks):
275276
(SORT_FIELD_PRIORITY, "desc"),
276277
(SORT_FIELD_DUE_AT, "asc"),
277278
(SORT_FIELD_CREATED_AT, "desc"),
279+
(SORT_FIELD_UPDATED_AT, "desc"),
278280
(SORT_FIELD_ASSIGNEE, "asc"),
279281
]
280282

@@ -363,7 +365,7 @@ def test_get_tasks_default_behavior_unchanged(self, mock_get_tasks):
363365
mock_get_tasks.assert_called_once_with(
364366
page=1,
365367
limit=20,
366-
sort_by=SORT_FIELD_CREATED_AT,
368+
sort_by=SORT_FIELD_UPDATED_AT,
367369
order="desc",
368370
user_id=str(self.user_id),
369371
team_id=None,
@@ -380,7 +382,7 @@ def test_get_tasks_edge_case_combinations(self):
380382
mock_get_tasks.assert_called_once_with(
381383
page=1,
382384
limit=20,
383-
sort_by=SORT_FIELD_CREATED_AT,
385+
sort_by=SORT_FIELD_UPDATED_AT,
384386
order=SORT_ORDER_ASC,
385387
user_id=str(self.user_id),
386388
team_id=None,

0 commit comments

Comments
 (0)