Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Admin): Besoins : répare le filtre par montant exact #1112

Merged
merged 3 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lemarche/tenders/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
30 changes: 1 addition & 29 deletions lemarche/tenders/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down
23 changes: 21 additions & 2 deletions lemarche/tenders/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 = [
Expand Down
30 changes: 30 additions & 0 deletions lemarche/tenders/utils.py
Original file line number Diff line number Diff line change
@@ -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'.")
Loading