From 953b89a9f96f0bdeb0b672f894ce5aa0299c9fa8 Mon Sep 17 00:00:00 2001 From: Joaquim Nallar Date: Thu, 1 Feb 2024 16:52:06 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20[Fix]=20intervention=20date=20fi?= =?UTF-8?q?lter=20and=20add=20intervention=20years=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/changelog.rst | 1 + geotrek/maintenance/filters.py | 16 ++++++++--- .../locale/de/LC_MESSAGES/django.po | 3 +++ .../locale/en/LC_MESSAGES/django.po | 3 +++ .../locale/es/LC_MESSAGES/django.po | 3 +++ .../locale/fr/LC_MESSAGES/django.po | 7 +++-- .../locale/it/LC_MESSAGES/django.po | 3 +++ .../locale/nl/LC_MESSAGES/django.po | 3 +++ geotrek/maintenance/managers.py | 16 ++++++++--- .../maintenance/static/maintenance/main.js | 27 +++++++++++++++++++ geotrek/maintenance/tests/test_filters.py | 23 ++++++++++++++++ geotrek/maintenance/tests/test_managers.py | 25 +++++++++++++++++ 12 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 geotrek/maintenance/tests/test_managers.py diff --git a/docs/changelog.rst b/docs/changelog.rst index 2ff843d06f..b4050749c6 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,6 +8,7 @@ CHANGELOG **Bug fixes** - Signage & Blade conditions translations + admin BladeCondition entry (#3847) +- Add intervention date filter and add intervention years filter (#3825) **Documentation** diff --git a/geotrek/maintenance/filters.py b/geotrek/maintenance/filters.py index 6ad9c6451c..71b003a407 100644 --- a/geotrek/maintenance/filters.py +++ b/geotrek/maintenance/filters.py @@ -138,8 +138,10 @@ class InterventionFilterSet(AltimetryInterventionFilterSet, ZoningFilterSet, Str ON_CHOICES += (('course', _("Outdoor Course")), ('site', _("Outdoor Site")),) bbox = PolygonTopologyFilter(lookup_expr='intersects') - begin_date = CustomDateFromToRangeFilter(lookup_expr='icontains', widget=OneLineRangeWidget(attrs={'type': 'date', 'class': 'minmax-field', 'title': _('Filter by begin date range')},), label=_('begin date')) - end_date = CustomDateFromToRangeFilter(lookup_expr='icontains', widget=OneLineRangeWidget(attrs={'type': 'date', 'class': 'minmax-field', 'title': _('Filter by end date range')},), label=_('end date')) + begin_date = CustomDateFromToRangeFilter(widget=OneLineRangeWidget(attrs={'type': 'text', 'class': 'minmax-field', 'title': _('Filter by begin date range')},), label=_('begin date')) + end_date = CustomDateFromToRangeFilter(widget=OneLineRangeWidget(attrs={'type': 'text', 'class': 'minmax-field', 'title': _('Filter by end date range')},), label=_('end date')) + year = MultipleChoiceFilter(choices=lambda: Intervention.objects.year_choices(), + method='filter_year', label=_("Year")) on = ChoiceFilter(field_name='target_type__model', choices=ON_CHOICES, label=_("On"), empty_label=_("On")) area_type = InterventionIntersectionFilterRestrictedAreaType(label=_('Restricted area type'), required=False, lookup_expr='intersects') @@ -154,8 +156,14 @@ class Meta(StructureRelatedFilterSet.Meta): 'status', 'type', 'stake', 'subcontracting', 'project', 'on', ] - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + def filter_year(self, qs, name, values): + conditions = Q() + for value in values: + # Filter only with precise begin year + conditions |= Q(begin_date__year=value, end_date__isnull=True) + # Filter year between begin and end date + conditions |= Q(begin_date__year__lte=value, end_date__year__gte=value) + return qs.filter(conditions) class ProjectFilterSet(StructureRelatedFilterSet): diff --git a/geotrek/maintenance/locale/de/LC_MESSAGES/django.po b/geotrek/maintenance/locale/de/LC_MESSAGES/django.po index dc111f7130..a857de0d5e 100644 --- a/geotrek/maintenance/locale/de/LC_MESSAGES/django.po +++ b/geotrek/maintenance/locale/de/LC_MESSAGES/django.po @@ -83,6 +83,9 @@ msgstr "" msgid "end date" msgstr "" +msgid "Year" +msgstr "" + msgid "On" msgstr "" diff --git a/geotrek/maintenance/locale/en/LC_MESSAGES/django.po b/geotrek/maintenance/locale/en/LC_MESSAGES/django.po index dc111f7130..a857de0d5e 100644 --- a/geotrek/maintenance/locale/en/LC_MESSAGES/django.po +++ b/geotrek/maintenance/locale/en/LC_MESSAGES/django.po @@ -83,6 +83,9 @@ msgstr "" msgid "end date" msgstr "" +msgid "Year" +msgstr "" + msgid "On" msgstr "" diff --git a/geotrek/maintenance/locale/es/LC_MESSAGES/django.po b/geotrek/maintenance/locale/es/LC_MESSAGES/django.po index dc111f7130..a857de0d5e 100644 --- a/geotrek/maintenance/locale/es/LC_MESSAGES/django.po +++ b/geotrek/maintenance/locale/es/LC_MESSAGES/django.po @@ -83,6 +83,9 @@ msgstr "" msgid "end date" msgstr "" +msgid "Year" +msgstr "" + msgid "On" msgstr "" diff --git a/geotrek/maintenance/locale/fr/LC_MESSAGES/django.po b/geotrek/maintenance/locale/fr/LC_MESSAGES/django.po index 6d2afc1e59..04f3f4c3c8 100644 --- a/geotrek/maintenance/locale/fr/LC_MESSAGES/django.po +++ b/geotrek/maintenance/locale/fr/LC_MESSAGES/django.po @@ -74,13 +74,16 @@ msgid "Filter by begin date range" msgstr "Filtrer par intervalle de date de début" msgid "begin date" -msgstr "date de début" +msgstr "date début" msgid "Filter by end date range" msgstr "Filtrer par intervalle de date de fin" msgid "end date" -msgstr "date de fin" +msgstr "date fin" + +msgid "Year" +msgstr "Année" msgid "On" msgstr "Sur" diff --git a/geotrek/maintenance/locale/it/LC_MESSAGES/django.po b/geotrek/maintenance/locale/it/LC_MESSAGES/django.po index dc111f7130..a857de0d5e 100644 --- a/geotrek/maintenance/locale/it/LC_MESSAGES/django.po +++ b/geotrek/maintenance/locale/it/LC_MESSAGES/django.po @@ -83,6 +83,9 @@ msgstr "" msgid "end date" msgstr "" +msgid "Year" +msgstr "" + msgid "On" msgstr "" diff --git a/geotrek/maintenance/locale/nl/LC_MESSAGES/django.po b/geotrek/maintenance/locale/nl/LC_MESSAGES/django.po index dc111f7130..a857de0d5e 100644 --- a/geotrek/maintenance/locale/nl/LC_MESSAGES/django.po +++ b/geotrek/maintenance/locale/nl/LC_MESSAGES/django.po @@ -83,6 +83,9 @@ msgstr "" msgid "end date" msgstr "" +msgid "Year" +msgstr "" + msgid "On" msgstr "" diff --git a/geotrek/maintenance/managers.py b/geotrek/maintenance/managers.py index 808ef8f73d..8dc7b5cb39 100644 --- a/geotrek/maintenance/managers.py +++ b/geotrek/maintenance/managers.py @@ -1,13 +1,21 @@ -from django.db.models import Min, Max -from django.db.models.functions import ExtractYear +from django.db.models import Min, Max, Func, Case, When, IntegerField +from django.db.models.functions import ExtractYear, Cast from geotrek.common.mixins.managers import NoDeleteManager class InterventionManager(NoDeleteManager): def year_choices(self): - values = self.existing().filter(begin_date__isnull=False).annotate(year=ExtractYear('begin_date')) \ - .order_by('-year').distinct().values_list('year', flat=True) + """ Get all range years between begin_date and end_date and concatenates distinct years """ + qs = (self.existing().all().annotate( + years=Func( + Cast(ExtractYear("begin_date"), output_field=IntegerField()), + Cast(Case(When(end_date__isnull=False, then=ExtractYear("end_date")), + default=ExtractYear("begin_date")), + output_field=IntegerField()), + function="generate_series"), + )) + values = qs.distinct('years').order_by('-years').values_list('years', flat=True) return [(year, year) for year in values] diff --git a/geotrek/maintenance/static/maintenance/main.js b/geotrek/maintenance/static/maintenance/main.js index 7444366dea..29372bd072 100644 --- a/geotrek/maintenance/static/maintenance/main.js +++ b/geotrek/maintenance/static/maintenance/main.js @@ -32,3 +32,30 @@ $(window).on('entity:map', function (e, data) { } }); }); + + +// Date picker with placeholder on input +function setDatePickerConfig(idList) { + $(idList).datepicker({ + autoclose: true, + language: window.SETTINGS.languages.default, + format: window.SETTINGS.date_format + }); +} +$(window).on('entity:view:add', function (e, data) { + if (data.modelname === "intervention"){ + setDatePickerConfig('#id_begin_date, #id_end_date'); + }; +}); + +$(window).on('entity:view:list', function (e, data) { + if (data.modelname === "intervention"){ + setDatePickerConfig('#id_begin_date_0, #id_begin_date_1, #id_end_date_0, #id_end_date_1'); + }; +}); + +$(window).on('entity:view:update', function (e, data) { + if (data.modelname === "intervention"){ + setDatePickerConfig('#id_begin_date, #id_end_date'); + }; +}); diff --git a/geotrek/maintenance/tests/test_filters.py b/geotrek/maintenance/tests/test_filters.py index 35dfda2d4b..3a307b6edd 100644 --- a/geotrek/maintenance/tests/test_filters.py +++ b/geotrek/maintenance/tests/test_filters.py @@ -97,6 +97,29 @@ def test_filter_zoning_area_type(self): self.assertEqual(len(filter.qs), 0) +class InterventionDateFilterTest(TestCase): + def test_filter_year_without_end_date(self): + InterventionFactory(name="intervention1", begin_date="2020-07-30") + InterventionFactory(name="intervention1", begin_date="2021-07-30") + InterventionFactory(name="intervention1", begin_date="2022-07-30") + intervention_filter = InterventionFilterSet({'year': [2021]}) + self.assertEqual(intervention_filter.qs.count(), 1) + + def test_filter_year_with_range(self): + InterventionFactory(name="intervention1", begin_date="2020-07-30", end_date="2024-07-30") + InterventionFactory(name="intervention1", begin_date="2021-07-30") + InterventionFactory(name="intervention1", begin_date="2022-07-30", end_date="2024-07-30") + intervention_filter = InterventionFilterSet({'year': [2022]}) + self.assertEqual(intervention_filter.qs.count(), 2) + + def test_filter_year_with_end_date(self): + InterventionFactory(name="intervention1", begin_date="2020-07-30", end_date="2023-07-30") + InterventionFactory(name="intervention1", begin_date="2021-07-30") + InterventionFactory(name="intervention1", begin_date="2022-07-30", end_date="2024-07-30") + intervention_filter = InterventionFilterSet({'year': [2023, 2024]}) + self.assertEqual(intervention_filter.qs.count(), 2) + + @skipIf(not settings.TREKKING_TOPOLOGY_ENABLED, 'Test with dynamic segmentation only') class InterventionFilteringByLandTest(TestCase): @classmethod diff --git a/geotrek/maintenance/tests/test_managers.py b/geotrek/maintenance/tests/test_managers.py new file mode 100644 index 0000000000..c7a818546d --- /dev/null +++ b/geotrek/maintenance/tests/test_managers.py @@ -0,0 +1,25 @@ +from django.test import TestCase +from geotrek.maintenance.models import Intervention +from geotrek.maintenance.tests.factories import InterventionFactory + + +class InterventionManagerTest(TestCase): + def test_intervention_with_not_end_date(self): + InterventionFactory(name="test1", begin_date="2020-06-03") + InterventionFactory(name="test2", begin_date="2022-06-03") + self.assertEqual(Intervention.objects.year_choices(), [(2022, 2022), (2020, 2020)]) + + def test_intervention_with_end_date(self): + InterventionFactory(name="test1", begin_date="2018-06-03", end_date="2020-06-03") + InterventionFactory(name="test2", begin_date="2022-06-03", end_date="2024-06-03") + self.assertEqual(Intervention.objects.year_choices(), [(2024, 2024), (2023, 2023), (2022, 2022), (2020, 2020), (2019, 2019), (2018, 2018)]) + + def test_intervention_with_one_have_end_date(self): + InterventionFactory(name="test1", begin_date="2020-06-03") + InterventionFactory(name="test2", begin_date="2022-06-03", end_date="2024-06-03") + self.assertEqual(Intervention.objects.year_choices(), [(2024, 2024), (2023, 2023), (2022, 2022), (2020, 2020)]) + + def test_intervention_return_distinct_year(self): + InterventionFactory(name="test1", begin_date="2020-06-03") + InterventionFactory(name="test2", begin_date="2018-06-03", end_date="2024-06-03") + self.assertEqual(Intervention.objects.year_choices(), [(2024, 2024), (2023, 2023), (2022, 2022), (2021, 2021), (2020, 2020), (2019, 2019), (2018, 2018)])