diff --git a/lemarche/tenders/admin.py b/lemarche/tenders/admin.py index b9fb1e516..01eaaacd8 100644 --- a/lemarche/tenders/admin.py +++ b/lemarche/tenders/admin.py @@ -67,12 +67,13 @@ def lookups(self, request, model_admin): def queryset(self, request, queryset): value = self.value() - amount_10k = 10 * 10**3 # 10k + amount_5k = 5 * 10**3 + amount_10k = 10 * 10**3 if value == "<10k": return queryset.filter_by_amount_exact(amount_10k, operation="lt") elif value == "5k-10k": return queryset.filter_by_amount_exact(amount_10k, operation="lte").filter_by_amount_exact( - amount_10k, operation="gte" + amount_5k, operation="gte" ) elif value == ">=10k": return queryset.filter_by_amount_exact(amount_10k, operation="gte") diff --git a/lemarche/tenders/models.py b/lemarche/tenders/models.py index 5c3d73d39..20fff59f9 100644 --- a/lemarche/tenders/models.py +++ b/lemarche/tenders/models.py @@ -18,6 +18,7 @@ from lemarche.siaes import constants as siae_constants from lemarche.siaes.models import Siae from lemarche.tenders import constants as tender_constants +from lemarche.tenders.utils import find_amount_ranges from lemarche.users.models import User from lemarche.utils.apis import api_elasticsearch from lemarche.utils.constants import ADMIN_FIELD_HELP_TEXT, MARCHE_BENEFIT_CHOICES, RECALCULATED_FIELD_HELP_TEXT @@ -33,35 +34,6 @@ def get_perimeter_filter(siae): ) -def find_amount_ranges(amount, operation): - """ - Returns the keys from AMOUNT_RANGE that match a given operation on a specified amount. - - :param amount: The amount to compare against. - :param operation: The operation to perform ('lt', 'lte', 'gt', 'gte'). - :return: A list of matching keys. - """ - amount = int(amount) - if operation == "lt": - if amount < tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_0_1): - return [tender_constants.AMOUNT_RANGE_0_1] - return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value < amount] - elif operation == "lte": - if amount <= tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_0_1): - return [tender_constants.AMOUNT_RANGE_0_1] - return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value <= amount] - elif operation == "gt": - if amount >= tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_1000_MORE): - return [tender_constants.AMOUNT_RANGE_1000_MORE] - return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value > amount] - elif operation == "gte": - if amount >= tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_1000_MORE): - return [tender_constants.AMOUNT_RANGE_1000_MORE] - return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value >= amount] - else: - raise ValueError("Unrecognized operation. Use 'lt', 'lte', 'gt', or 'gte'.") - - class TenderQuerySet(models.QuerySet): def prefetch_many_to_many(self): return self.prefetch_related("sectors") # "perimeters", "siaes", "questions" diff --git a/lemarche/tenders/tests.py b/lemarche/tenders/tests.py index 1a24a5dc5..9a9fd106b 100644 --- a/lemarche/tenders/tests.py +++ b/lemarche/tenders/tests.py @@ -20,7 +20,8 @@ from lemarche.tenders import constants as tender_constants from lemarche.tenders.admin import TenderAdmin from lemarche.tenders.factories import PartnerShareTenderFactory, TenderFactory, TenderQuestionFactory -from lemarche.tenders.models import PartnerShareTender, Tender, TenderQuestion, TenderSiae, find_amount_ranges +from lemarche.tenders.models import PartnerShareTender, Tender, TenderQuestion, TenderSiae +from lemarche.tenders.utils import find_amount_ranges from lemarche.users.factories import UserFactory from lemarche.users.models import User from lemarche.utils.admin.admin_site import MarcheAdminSite, get_admin_change_view_url @@ -414,6 +415,24 @@ def test_in_perimeters(self): Tender.objects.in_perimeters(post_code="29000", department="29", region="Bretagne").count(), 0 ) + def test_filter_by_amount_exact(self): + TenderFactory(amount_exact=1000) + TenderFactory(amount_exact=5000) + TenderFactory(amount_exact=7500) + TenderFactory(amount_exact=10000) + TenderFactory(amount_exact=100000) + tender_qs = Tender.objects.has_amount() + self.assertEqual(tender_qs.filter_by_amount_exact(1000, operation="lt").count(), 0) + self.assertEqual(tender_qs.filter_by_amount_exact(1000, operation="gte").count(), 5) + self.assertEqual(tender_qs.filter_by_amount_exact(100000, operation="gt").count(), 0) + self.assertEqual(tender_qs.filter_by_amount_exact(100000, operation="lte").count(), 5) + self.assertEqual( + tender_qs.filter_by_amount_exact(10000, operation="lte") + .filter_by_amount_exact(5000, operation="gte") + .count(), + 3, + ) + class TenderModelQuerysetOrderTest(TestCase): @classmethod @@ -1000,7 +1019,7 @@ def test_duplicate(self): self.assertNotEqual(self.tender_with_siae.siaes.count(), new_tender.siaes.count()) -class FindAmountRangesTests(TestCase): +class TenderUtilsFindAmountRangesTests(TestCase): def test_gte_operation(self): """Test the 'gte' operation.""" expected_keys = [ diff --git a/lemarche/tenders/utils.py b/lemarche/tenders/utils.py new file mode 100644 index 000000000..e13f01cd0 --- /dev/null +++ b/lemarche/tenders/utils.py @@ -0,0 +1,30 @@ +from lemarche.tenders import constants as tender_constants + + +def find_amount_ranges(amount, operation): + """ + Returns the keys from AMOUNT_RANGE that match a given operation on a specified amount. + + :param amount: The amount to compare against. + :param operation: The operation to perform ('lt', 'lte', 'gt', 'gte'). + :return: A list of matching keys. + """ + amount = int(amount) + if operation == "lt": + if amount < tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_0_1): + return [tender_constants.AMOUNT_RANGE_0_1] + return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value < amount] + elif operation == "lte": + if amount <= tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_0_1): + return [tender_constants.AMOUNT_RANGE_0_1] + return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value <= amount] + elif operation == "gt": + if amount >= tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_1000_MORE): + return [tender_constants.AMOUNT_RANGE_1000_MORE] + return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value > amount] + elif operation == "gte": + if amount >= tender_constants.AMOUNT_RANGE_CHOICE_EXACT.get(tender_constants.AMOUNT_RANGE_1000_MORE): + return [tender_constants.AMOUNT_RANGE_1000_MORE] + return [key for key, value in tender_constants.AMOUNT_RANGE_CHOICE_EXACT.items() if value >= amount] + else: + raise ValueError("Unrecognized operation. Use 'lt', 'lte', 'gt', or 'gte'.")