From d32e8c5350dca23fb358032e161bc518cbc2539a Mon Sep 17 00:00:00 2001 From: daniel Date: Sun, 25 Feb 2024 16:58:57 +0100 Subject: [PATCH] :sparkles: Filter on latest record of an object --- src/objects/api/v1/filters.py | 7 +++ src/objects/api/v2/filters.py | 7 +++ src/objects/core/query.py | 10 ++++ src/objects/tests/v2/test_filters.py | 81 ++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) diff --git a/src/objects/api/v1/filters.py b/src/objects/api/v1/filters.py index 49b9e70d..a23d1829 100644 --- a/src/objects/api/v1/filters.py +++ b/src/objects/api/v1/filters.py @@ -75,6 +75,10 @@ class ObjectRecordFilterSet(FilterSet): ) % {"operator_choices": display_choice_values_for_help_text(Operators)}, ) + latest_record = filters.BooleanFilter( + method="filter_on_latest_record", + help_text=_("Search only in the latest record."), + ) class Meta: model = ObjectRecord @@ -113,3 +117,6 @@ def filter_date(self, queryset, name, value: date): def filter_registration_date(self, queryset, name, value: date): return queryset.filter_for_registration_date(value) + + def filter_on_latest_record(self, queryset, name, value: bool): + return queryset.filter_on_latest_record(value) diff --git a/src/objects/api/v2/filters.py b/src/objects/api/v2/filters.py index cccdc19a..18178033 100644 --- a/src/objects/api/v2/filters.py +++ b/src/objects/api/v2/filters.py @@ -85,6 +85,10 @@ class ObjectRecordFilterSet(FilterSet): method="filter_data_icontains", help_text=_("Search in all `data` values of string properties."), ) + latest_record = filters.BooleanFilter( + method="filter_on_latest_record", + help_text=_("Search only in the latest record."), + ) class Meta: model = ObjectRecord @@ -128,3 +132,6 @@ def filter_date(self, queryset, name, value: date_): def filter_registration_date(self, queryset, name, value: date_): return queryset.filter_for_registration_date(value) + + def filter_on_latest_record(self, queryset, name, value: bool): + return queryset.filter_on_latest_record(value) diff --git a/src/objects/core/query.py b/src/objects/core/query.py index 84514c6e..ca0cfbcc 100644 --- a/src/objects/core/query.py +++ b/src/objects/core/query.py @@ -68,3 +68,13 @@ def filter_for_registration_date(self, date): perspective. """ return self.filter(registration_at__lte=date) + + def filter_on_latest_record(self, value: bool): + """ + Filter only on data in latest record if True. + + """ + if not value: + return self + else: + return self.filter(corrected__isnull=True) diff --git a/src/objects/tests/v2/test_filters.py b/src/objects/tests/v2/test_filters.py index 52ed5ddc..89e89c93 100644 --- a/src/objects/tests/v2/test_filters.py +++ b/src/objects/tests/v2/test_filters.py @@ -377,6 +377,24 @@ def test_filter_exclude_old_records(self): data = response.json()["results"] self.assertEqual(len(data), 0) + def test_filter_exclude_old_records_same_day_regression_test(self): + record_old = ObjectRecordFactory.create( + data={"diameter": 45}, + object__object_type=self.object_type, + start_at=date.today() - timedelta(days=10), + end_at=date.today(), + ) + record_new = ObjectRecordFactory.create( + data={"diameter": 50}, object=record_old.object, start_at=record_old.end_at + ) + + response = self.client.get(self.url, {"data_attrs": "diameter__exact__45"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 1) + def test_filter_date_field_gte(self): record = ObjectRecordFactory.create( data={"dateField": "2000-10-10"}, object__object_type=self.object_type @@ -652,3 +670,66 @@ def test_filter_unkown_version(self): data = response.json()["results"] self.assertEqual(len(data), 0) + + +class FilterLatestVersionTests(TokenAuthMixin, APITestCase): + url = reverse_lazy("object-list") + + @classmethod + def setUpTestData(cls): + super().setUpTestData() + + cls.object_type = ObjectTypeFactory(service__api_root=OBJECT_TYPES_API) + PermissionFactory.create( + object_type=cls.object_type, + mode=PermissionModes.read_only, + token_auth=cls.token_auth, + ) + + def test_filter_latest_version_true(self): + record_old = ObjectRecordFactory.create( + data={"diameter": 45}, + object__object_type=self.object_type, + start_at=date.today() - timedelta(days=10), + end_at=date.today(), + ) + record_new = ObjectRecordFactory.create( + data={"diameter": 50}, + object=record_old.object, + start_at=record_old.end_at, + ) + record_new.correct = record_old + record_new.save() + + response = self.client.get( + self.url, {"data_attrs": "diameter__exact__45", "latest_record": True} + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 0) + + def test_filter_latest_version_false(self): + record_old = ObjectRecordFactory.create( + data={"diameter": 45}, + object__object_type=self.object_type, + start_at=date.today() - timedelta(days=10), + end_at=date.today(), + ) + record_new = ObjectRecordFactory.create( + data={"diameter": 50}, + object=record_old.object, + start_at=record_old.end_at, + ) + record_new.correct = record_old + record_new.save() + + response = self.client.get( + self.url, {"data_attrs": "diameter__exact__45", "latest_version": False} + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 1)