Skip to content

Commit

Permalink
build exclusivite reparation filter when reparer is checked (#718)
Browse files Browse the repository at this point in the history
* build exclusivite reparation filter when reparer is checked

* refactor method in address view

* Follow up refactor

* fix tests

* wip

* Fix tests. Finally
  • Loading branch information
fabienheureux authored Jul 18, 2024
1 parent 8355ff5 commit 6ec0053
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 63 deletions.
105 changes: 52 additions & 53 deletions qfdmo/views/adresses.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,24 +114,15 @@ def get_form(self, form_class: type | None = None) -> BaseForm:
def get_context_data(self, **kwargs):
kwargs["location"] = "{}"
kwargs["carte"] = self.request.GET.get("carte") is not None

# TODO : voir pour utiliser davantage le form dans cette vue
form = self.get_form_class()(self.request.GET)
form.is_valid()
self.cleaned_data = form.cleaned_data

# Manage the selection of sous_categorie_objet and actions
acteurs = self._manage_sous_categorie_objet_and_actions()

if self.request.GET.get("ess"):
acteurs = acteurs.filter(labels__code="ess")

if self.request.GET.get("bonus"):
acteurs = acteurs.filter(labels__bonus=True)

if (
"reparer" not in form.cleaned_data["action_list"]
or form.cleaned_data["pas_exclusivite_reparation"]
):
acteurs = acteurs.exclude(exclusivite_de_reprisereparation=True)

# Case of digital acteurs
if self.request.GET.get("digital") and self.request.GET.get("digital") == "1":
kwargs["acteurs"] = (
Expand All @@ -142,6 +133,8 @@ def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs)

# Case of physical acteurs
# TODO : refactoriser ci-dessous pour passer dans
# _manage_sous_categorie_objet_and_actions ou autre
else:
# Exclude digital acteurs
acteurs = acteurs.exclude(
Expand Down Expand Up @@ -306,7 +299,14 @@ def _get_selected_action_code(self):
return []

def _get_selected_action_ids(self):
return [a.id for a in self._get_selected_action()]
if self.request.GET.get("carte") is not None:
return [a.id for a in self._get_selected_action()]

return [a["id"] for a in self.get_action_list()]

def _get_reparer_action_id(self):
"""Sert essentiellement à faciliter le teste de AddressesView"""
return CachedDirectionAction.get_reparer_action_id()

def _get_selected_action(self) -> List[Action]:
"""
Expand Down Expand Up @@ -357,60 +357,58 @@ def get_action_list(self) -> List[dict]:
return [model_to_dict(a, exclude=["directions"]) for a in actions]

def _manage_sous_categorie_objet_and_actions(self) -> QuerySet[DisplayedActeur]:
sous_categorie_id = None
if (
self.request.GET.get("sous_categorie_objet")
and self.request.GET.get("sc_id", "").isnumeric()
):
sous_categorie_id = int(self.request.GET.get("sc_id", "0"))

action_selection_ids = (
self._get_selected_action_ids()
if self.request.GET.get("carte") is not None
else [a["id"] for a in self.get_action_list()]
)

ps_filter = self._build_ps_filter(action_selection_ids, sous_categorie_id)

acteurs = DisplayedActeur.objects.filter(ps_filter)

filters, excludes = self._compile_acteurs_queryset()
acteurs = DisplayedActeur.objects.filter(filters).exclude(excludes)
acteurs = acteurs.prefetch_related(
"proposition_services__sous_categories",
"proposition_services__sous_categories__categorie",
"proposition_services__action",
"proposition_services__acteur_service",
).distinct()

if sous_categorie_id:
acteurs = acteurs.filter(
proposition_services__sous_categories__id=sous_categorie_id
)

return acteurs

def _build_ps_filter(self, action_selection_ids, sous_categorie_id: int | None):
reparer_action_id = None
def _compile_acteurs_queryset(self):
filters = Q()
excludes = Q()

selected_actions_ids = self._get_selected_action_ids()
reparer_action_id = self._get_reparer_action_id()
reparer_is_checked = reparer_action_id in selected_actions_ids

if (
self.request.GET.get("label_reparacteur")
and CachedDirectionAction.get_reparer_action_id() in action_selection_ids
self.cleaned_data["pas_exclusivite_reparation"] is not False
or not reparer_is_checked
):
reparer_action_id = CachedDirectionAction.get_reparer_action_id()
action_selection_ids = [
a for a in action_selection_ids if a != reparer_action_id
excludes |= Q(exclusivite_de_reprisereparation=True)

if self.cleaned_data["label_reparacteur"] and reparer_is_checked:
selected_actions_ids = [
a for a in selected_actions_ids if a != reparer_action_id
]

ps_filter = Q()
if sous_categorie_id:
if action_selection_ids:
ps_filter = ps_filter | Q(
if self.cleaned_data["ess"]:
filters |= Q(labels__code="ess")

if self.cleaned_data["bonus"]:
filters |= Q(labels__bonus=True)

if self.cleaned_data.get("sous_categorie_objet") and self.cleaned_data.get(
"sc_id"
):
sous_categorie_id = self.cleaned_data.get("sc_id", 0)
filters |= Q(proposition_services__sous_categories__id=sous_categorie_id)

if selected_actions_ids:
filters |= Q(
proposition_services__in=DisplayedPropositionService.objects.filter(
action_id__in=action_selection_ids,
action_id__in=selected_actions_ids,
sous_categories__id=sous_categorie_id,
),
statut=ActeurStatus.ACTIF,
)
if reparer_action_id:
ps_filter = ps_filter | Q(
filters |= Q(
proposition_services__in=DisplayedPropositionService.objects.filter(
action_id=reparer_action_id,
sous_categories__id=sous_categorie_id,
Expand All @@ -419,18 +417,19 @@ def _build_ps_filter(self, action_selection_ids, sous_categorie_id: int | None):
statut=ActeurStatus.ACTIF,
)
else:
if action_selection_ids:
ps_filter = ps_filter | Q(
proposition_services__action_id__in=action_selection_ids,
if selected_actions_ids:
filters |= Q(
proposition_services__action_id__in=selected_actions_ids,
statut=ActeurStatus.ACTIF,
)
if reparer_action_id:
ps_filter = ps_filter | Q(
filters |= Q(
proposition_services__action_id=reparer_action_id,
labels__code="reparacteur",
statut=ActeurStatus.ACTIF,
)
return ps_filter

return filters, excludes

def _get_grouped_action_choices(
self, action_displayed: list[Action]
Expand Down
4 changes: 3 additions & 1 deletion unit_tests/qfdmo/acteur_factory.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import factory.fuzzy
from django.contrib.gis.geos import Point
from factory import SubFactory
from factory import SubFactory, Faker
from factory.django import DjangoModelFactory as Factory

from qfdmo.models import (
Expand All @@ -20,6 +20,8 @@ class SourceFactory(Factory):
class Meta:
model = Source

libelle = Faker("word")
code = Faker("word")
afficher = True


Expand Down
31 changes: 22 additions & 9 deletions unit_tests/qfdmo/test_addresses_view.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from django.contrib.gis.geos import Point
import pytest
from unittest.mock import MagicMock
import pytest
from django.http import HttpRequest

from qfdmo.models.acteur import DisplayedActeur
from qfdmo.models.acteur import ActeurStatus
from qfdmo.views.adresses import AddressesView
from unit_tests.core.test_utils import query_dict_from
from unit_tests.qfdmo.acteur_factory import DisplayedActeurFactory
from unit_tests.qfdmo.acteur_factory import (
DisplayedActeurFactory,
DisplayedPropositionServiceFactory,
LabelQualiteFactory,
)
from unit_tests.qfdmo.action_factory import ActionFactory


class TestAdessesViewGetActionList:
Expand Down Expand Up @@ -69,14 +74,21 @@ def test_get_action_list(self, params, action_list):

@pytest.fixture
def adresses_view():
DisplayedActeurFactory(
reparacteur = LabelQualiteFactory(code="reparacteur")
action = ActionFactory()

displayed_acteur = DisplayedActeurFactory(
exclusivite_de_reprisereparation=True,
location=Point(1, 1),
statut=ActeurStatus.ACTIF,
)
display_proposition_service = DisplayedPropositionServiceFactory(action=action)
displayed_acteur.labels.add(reparacteur)
displayed_acteur.proposition_services.add(display_proposition_service)

adresses_view = AddressesView()
adresses_view._manage_sous_categorie_objet_and_actions = MagicMock(
return_value=DisplayedActeur.objects.all()
)
adresses_view._get_reparer_action_id = MagicMock(return_value=action.id)
adresses_view._get_selected_action_ids = MagicMock(return_value=[action.id])
return adresses_view


Expand All @@ -89,7 +101,7 @@ def test_pas_action_reparer_exclut_acteurs_avec_exclusivite(self, adresses_view)
"action_list": ["preter"],
"latitude": [1],
"longitude": [1],
"pas_exclusivite_reparation": ["on"],
"pas_exclusivite_reparation": ["true"],
}
)
adresses_view.request = request
Expand All @@ -104,9 +116,9 @@ def test_action_reparer_exclut_par_defaut_acteurs_avec_exclusivite(
request.GET = query_dict_from(
{
"action_list": ["preter|reparer"],
"pas_exclusivite_reparation": ["on"],
"latitude": [1],
"longitude": [1],
"pas_exclusivite_reparation": ["true"],
}
)
adresses_view.request = request
Expand All @@ -123,6 +135,7 @@ def test_action_reparer_et_exclusivite_inclut_acteurs_avec_exclusivite(
"action_list": ["preter|reparer"],
"latitude": [1],
"longitude": [1],
"pas_exclusivite_reparation": ["false"],
}
)
adresses_view.request = request
Expand Down

0 comments on commit 6ec0053

Please sign in to comment.