From c510280f499b3ed734b8f426e74009839871f7f6 Mon Sep 17 00:00:00 2001 From: Nicolas Clerc Date: Fri, 20 Dec 2024 16:11:57 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F(backend)=20remove=20d?= =?UTF-8?q?eprecated=20django=20datetime=5Fsafe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Django is deprecating datetime_safe usage. --- .../tests/core/api/admin/orders/test_list.py | 38 +++++++++---------- .../joanie/tests/core/test_api_certificate.py | 22 ++++++----- 2 files changed, 30 insertions(+), 30 deletions(-) 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..5c816a7eb 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 @@ -25,9 +23,9 @@ class OrdersAdminApiListTestCase(TestCase): 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) + created_on = datetime.combine(created_on, datetime.min.time(), tzinfo=timezone.utc) with mock.patch( - "django.utils.timezone.now", return_value=created_on or timezone.now() + "django.utils.timezone.now", return_value=created_on or datetime.now() ): return factories.OrderGeneratorFactory.create_batch(number) @@ -709,7 +707,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 +731,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 +761,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 +788,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 +828,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 +865,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( From a1fe7ed525e75ebc73487d6207b5412e79f4e00e Mon Sep 17 00:00:00 2001 From: Nicolas Clerc Date: Fri, 20 Dec 2024 16:17:59 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B(backend)=20fix=20order=20creat?= =?UTF-8?q?ed=5Fon=20date=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Order filtering is matching created_on date exactly, which only matches times at 0:00, as query parameter only contains a date. --- CHANGELOG.md | 4 ++++ .../joanie/core/filters/admin/__init__.py | 2 +- .../tests/core/api/admin/orders/test_list.py | 20 +++++++++++++------ 3 files changed, 19 insertions(+), 7 deletions(-) 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 5c816a7eb..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 @@ -22,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 = datetime.combine(created_on, datetime.min.time(), tzinfo=timezone.utc) - with mock.patch( - "django.utils.timezone.now", return_value=created_on or datetime.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): """