diff --git a/CHANGELOG.md b/CHANGELOG.md index c5c46620a..d5d5acbad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to ## [Unreleased] +### Fixed + +- Fix order filtering by creation date + ## [2.12.0] - 2024-12-18 ### Added diff --git a/src/backend/joanie/core/filters/admin/__init__.py b/src/backend/joanie/core/filters/admin/__init__.py index 72eda7762..a2f2e7f27 100755 --- a/src/backend/joanie/core/filters/admin/__init__.py +++ b/src/backend/joanie/core/filters/admin/__init__.py @@ -280,7 +280,7 @@ class Meta: field_name="product__type", choices=enums.PRODUCT_TYPE_CHOICES, ) - created_on = filters.DateFilter(field_name="created_on", lookup_expr="exact") + created_on = filters.DateFilter(field_name="created_on", lookup_expr="date") created_on_date_range = filters.DateFromToRangeFilter(field_name="created_on") def filter_by_query(self, queryset, _name, value): diff --git a/src/backend/joanie/tests/core/api/admin/orders/test_list.py b/src/backend/joanie/tests/core/api/admin/orders/test_list.py index c5e160266..27d36e77d 100644 --- a/src/backend/joanie/tests/core/api/admin/orders/test_list.py +++ b/src/backend/joanie/tests/core/api/admin/orders/test_list.py @@ -1,14 +1,12 @@ """Test suite for the admin orders API list endpoint.""" import uuid -from datetime import date +from datetime import date, datetime, timezone from http import HTTPStatus from unittest import mock from django.conf import settings from django.test import TestCase -from django.utils import timezone -from django.utils.datetime_safe import datetime as django_datetime from joanie.core import enums, factories from joanie.core.models import CourseState, Order @@ -24,12 +22,20 @@ class OrdersAdminApiListTestCase(TestCase): @staticmethod def generate_orders_created_on(number: int, created_on=None): """Generate a batch of orders with a specific creation date.""" - if created_on: - created_on = timezone.make_aware(created_on) - with mock.patch( - "django.utils.timezone.now", return_value=created_on or timezone.now() - ): - return factories.OrderGeneratorFactory.create_batch(number) + orders = [] + for _ in range(number): + if created_on: + created_on = datetime.combine( + created_on, datetime.now().time(), tzinfo=timezone.utc + ) + with mock.patch( + "django.utils.timezone.now", + return_value=created_on or datetime.now(), + ): + orders.append(factories.OrderFactory()) + # orders default orderings are by creation date + orders.sort(key=lambda x: x.created_on, reverse=True) + return orders def test_api_admin_orders_request_without_authentication(self): """ @@ -709,7 +715,7 @@ def test_api_admin_orders_list_filter_by_created_on_no_result(self): """ admin = factories.UserFactory(is_staff=True, is_superuser=True) self.client.login(username=admin.username, password="password") - self.generate_orders_created_on(3, django_datetime(2024, 11, 30)) + self.generate_orders_created_on(3, date(2024, 11, 30)) isoformat_searched_date = date(2024, 12, 1).isoformat() # YYYY-MM-DD @@ -733,9 +739,9 @@ def test_api_admin_orders_list_filter_by_created_on(self): # Create orders that are on runtime of this test factories.OrderGeneratorFactory.create_batch(10) # Create orders with a date in the past - self.generate_orders_created_on(4, django_datetime(2024, 2, 17)) + self.generate_orders_created_on(4, date(2024, 2, 17)) # Create orders with the date we will query with - orders = self.generate_orders_created_on(3, django_datetime(2024, 11, 30)) + orders = self.generate_orders_created_on(3, date(2024, 11, 30)) isoformat_searched_date = date(2024, 11, 30).isoformat() # YYYY-MM-DD @@ -763,9 +769,9 @@ def test_api_admin_order_list_filter_by_created_on_before_and_after_date_no_resu self.client.login(username=admin.username, password="password") # Create orders with a date in the past - self.generate_orders_created_on(3, django_datetime(2024, 11, 20)) + self.generate_orders_created_on(3, date(2024, 11, 20)) # Create orders with a date not inside the date range - self.generate_orders_created_on(2, django_datetime(2024, 12, 8)) + self.generate_orders_created_on(2, date(2024, 12, 8)) isoformat_after_date = date(2024, 12, 1).isoformat() isoformat_before_date = date(2024, 12, 7).isoformat() @@ -790,12 +796,12 @@ def test_api_admin_order_list_filter_by_created_on_before_and_after(self): # py self.client.login(username=admin.username, password="password") # Create orders within the given range dates - orders_1 = self.generate_orders_created_on(3, django_datetime(2024, 11, 20)) + orders_1 = self.generate_orders_created_on(3, date(2024, 11, 20)) # Create another batch within the given range dates - orders_2 = self.generate_orders_created_on(3, django_datetime(2024, 11, 30)) + orders_2 = self.generate_orders_created_on(3, date(2024, 11, 30)) # Create orders that will be outside the range of the given dates - self.generate_orders_created_on(20, django_datetime(2024, 11, 9)) - self.generate_orders_created_on(20, django_datetime(2024, 12, 2)) + self.generate_orders_created_on(20, date(2024, 11, 9)) + self.generate_orders_created_on(20, date(2024, 12, 2)) isoformat_after_date = date(2024, 11, 10).isoformat() isoformat_before_date = date(2024, 12, 1).isoformat() @@ -830,10 +836,10 @@ def test_api_admin_order_list_filter_by_created_on_date_range_only_with_after_da self.client.login(username=admin.username, password="password") # Create orders that will be outside the range of the given dates - self.generate_orders_created_on(10, django_datetime(2024, 11, 30)) + self.generate_orders_created_on(10, date(2024, 11, 30)) # Create orders that are on the exact date and after the creation passed date in filter - orders_1 = self.generate_orders_created_on(2, django_datetime(2024, 12, 2)) - orders_2 = self.generate_orders_created_on(2, django_datetime(2024, 12, 10)) + orders_1 = self.generate_orders_created_on(2, date(2024, 12, 2)) + orders_2 = self.generate_orders_created_on(2, date(2024, 12, 10)) isoformat_after_date = date(2024, 12, 2).isoformat() @@ -867,10 +873,10 @@ def test_api_admin_order_list_filter_by_created_on_date_range_only_with_before_d self.client.login(username=admin.username, password="password") # Create orders that will match the filter before date in the query - orders_1 = self.generate_orders_created_on(2, django_datetime(2024, 11, 30)) - orders_2 = self.generate_orders_created_on(3, django_datetime(2024, 11, 1)) + orders_1 = self.generate_orders_created_on(2, date(2024, 11, 30)) + orders_2 = self.generate_orders_created_on(3, date(2024, 11, 1)) # Create orders that are later than the passed before date - self.generate_orders_created_on(7, django_datetime(2024, 12, 2)) + self.generate_orders_created_on(7, date(2024, 12, 2)) isoformat_before_date = date(2024, 11, 30).isoformat() diff --git a/src/backend/joanie/tests/core/test_api_certificate.py b/src/backend/joanie/tests/core/test_api_certificate.py index 6c1c29b10..c6087da70 100644 --- a/src/backend/joanie/tests/core/test_api_certificate.py +++ b/src/backend/joanie/tests/core/test_api_certificate.py @@ -1,13 +1,11 @@ """Tests for the Certificate API""" import uuid +from datetime import date, datetime, timezone from http import HTTPStatus from io import BytesIO from unittest import mock -from django.utils import timezone -from django.utils.datetime_safe import datetime as django_datetime - from pdfminer.high_level import extract_text as pdf_extract_text from rest_framework.pagination import PageNumberPagination @@ -33,11 +31,13 @@ def generate_certificate_created_on_and_issued_on( Generate a certificate for a user with a specific `created_on` date and `issued_on` date """ if created_on: - created_on = timezone.make_aware(created_on) + created_on = datetime.combine( + created_on, datetime.now().time(), tzinfo=timezone.utc + ) with mock.patch( "django.utils.timezone.now", - return_value=created_on or timezone.now(), + return_value=created_on or datetime.now(), ): certificate = factories.OrderCertificateFactory( order=factories.OrderFactory( @@ -46,7 +46,9 @@ def generate_certificate_created_on_and_issued_on( ) if issued_on: - issued_on = timezone.make_aware(issued_on) + issued_on = datetime.combine( + issued_on, datetime.now().time(), tzinfo=timezone.utc + ) # Using the update method to by pass the auto_now and editable is False parameters # on the field set on the model. Certificate.objects.filter(pk=certificate.id).update(issued_on=issued_on) @@ -79,16 +81,16 @@ def test_api_certificate_read_list_should_be_in_the_order_of_issued_on_field_val factories.OrderCertificateFactory.create_batch(5) # Create the certificates of the user certificate_0 = self.generate_certificate_created_on_and_issued_on( - user, django_datetime(2024, 11, 12), django_datetime(2024, 11, 28) + user, date(2024, 11, 12), date(2024, 11, 28) ) certificate_1 = self.generate_certificate_created_on_and_issued_on( - user, django_datetime(2024, 11, 13), django_datetime(2024, 11, 22) + user, date(2024, 11, 13), date(2024, 11, 22) ) certificate_2 = self.generate_certificate_created_on_and_issued_on( - user, django_datetime(2024, 11, 15), django_datetime(2024, 11, 24) + user, date(2024, 11, 15), date(2024, 11, 24) ) certificate_3 = self.generate_certificate_created_on_and_issued_on( - user, django_datetime(2024, 11, 15), django_datetime(2024, 11, 26) + user, date(2024, 11, 15), date(2024, 11, 26) ) response = self.client.get(