From 064caafebbd9016eebdaf04bc846d0ad1a849a5e Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 24 Nov 2023 10:34:56 +1100 Subject: [PATCH] API filter fix (#5979) * Simplify custom date filter * Add creation date data to test fixture * Add 'creation_date' to part serializer * Add unit test * Update API version --- InvenTree/InvenTree/api_version.py | 5 +++- InvenTree/InvenTree/filters.py | 4 +-- InvenTree/part/fixtures/part.yaml | 14 +++++++++ InvenTree/part/serializers.py | 2 ++ InvenTree/part/test_api.py | 47 ++++++++++++++++++++++++++++++ docker/production/.env | 4 +-- 6 files changed, 70 insertions(+), 6 deletions(-) diff --git a/InvenTree/InvenTree/api_version.py b/InvenTree/InvenTree/api_version.py index e23914b191..d5de42303b 100644 --- a/InvenTree/InvenTree/api_version.py +++ b/InvenTree/InvenTree/api_version.py @@ -2,11 +2,14 @@ # InvenTree API version -INVENTREE_API_VERSION = 154 +INVENTREE_API_VERSION = 155 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v155 -> 2023-11-24 : https://github.com/inventree/InvenTree/pull/5979 + - Add "creation_date" field to Part instance serializer + v154 -> 2023-11-21 : https://github.com/inventree/InvenTree/pull/5944 - Adds "responsible" field to the ProjectCode table diff --git a/InvenTree/InvenTree/filters.py b/InvenTree/InvenTree/filters.py index 0f49ebba08..cea9b01b03 100644 --- a/InvenTree/InvenTree/filters.py +++ b/InvenTree/InvenTree/filters.py @@ -19,9 +19,7 @@ class InvenTreeDateFilter(rest_filters.DateFilter): """Override the filter method to handle timezones correctly.""" if settings.USE_TZ: - - # Check if value is already timezone aware - if value is not None and not timezone.is_aware(value): + if value is not None: tz = timezone.get_current_timezone() value = datetime(value.year, value.month, value.day) value = make_aware(value, tz, True) diff --git a/InvenTree/part/fixtures/part.yaml b/InvenTree/part/fixtures/part.yaml index 3ff48e5ca3..f50a48c42d 100644 --- a/InvenTree/part/fixtures/part.yaml +++ b/InvenTree/part/fixtures/part.yaml @@ -7,6 +7,7 @@ description: 'M2x4 low profile head screw' category: 8 link: http://www.acme.com/parts/m2x4lphs + creation_date: '2018-01-01' tree_id: 0 purchaseable: True level: 0 @@ -19,6 +20,7 @@ name: 'M3x12 SHCS' description: 'M3x12 socket head cap screw' category: 8 + creation_date: '2019-02-02' tree_id: 0 level: 0 lft: 0 @@ -32,6 +34,7 @@ name: 'R_2K2_0805' description: '2.2kOhm resistor in 0805 package' category: 2 + creation_date: '2020-03-03' tree_id: 0 level: 0 lft: 0 @@ -44,6 +47,7 @@ name: 'R_4K7_0603' description: '4.7kOhm resistor in 0603 package' category: 2 + creation_date: '2021-04-04' default_location: 2 # Home/Bathroom tree_id: 0 level: 0 @@ -58,6 +62,7 @@ description: '22nF capacitor in 0805 package' purchaseable: true category: 3 + creation_date: '2022-05-05' tree_id: 0 level: 0 lft: 0 @@ -69,6 +74,7 @@ name: 'Widget' description: 'A watchamacallit' category: 7 + creation_date: '2023-06-06' salable: true assembly: true trackable: true @@ -85,6 +91,7 @@ description: 'A part without a category' category: null salable: true + creation_date: '2024-07-07' tree_id: 0 level: 0 lft: 0 @@ -99,6 +106,7 @@ assembly: true salable: true purchaseable: false + creation_date: '2025-08-08' category: 7 active: True IPN: BOB @@ -114,6 +122,7 @@ name: 'Assembly' description: 'A high level assembly part' salable: true + creation_date: '2026-09-09' active: True tree_id: 0 level: 0 @@ -128,6 +137,7 @@ description: 'A chair, which is actually just a template part' is_template: True trackable: true + creation_date: '2027-10-10' salable: true category: 7 tree_id: 1 @@ -142,6 +152,7 @@ description: 'A variant chair part which is blue' variant_of: 10000 trackable: true + creation_date: '2028-11-11' category: 7 tree_id: 1 level: 0 @@ -157,6 +168,7 @@ IPN: "R.CH" trackable: true salable: true + creation_date: '2029-12-12' category: 7 tree_id: 1 level: 0 @@ -171,6 +183,7 @@ variant_of: 10000 category: 7 trackable: true + creation_date: '2030-01-01' tree_id: 1 level: 0 lft: 0 @@ -184,6 +197,7 @@ variant_of: 10003 is_template: true category: 7 + creation_date: '2031-02-02' trackable: true tree_id: 1 level: 0 diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 8bf7db4d03..561cc69111 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -504,6 +504,7 @@ class PartSerializer(InvenTree.serializers.RemoteImageMixin, InvenTree.serialize 'category_detail', 'category_path', 'component', + 'creation_date', 'default_expiry', 'default_location', 'default_supplier', @@ -558,6 +559,7 @@ class PartSerializer(InvenTree.serializers.RemoteImageMixin, InvenTree.serialize read_only_fields = [ 'barcode_hash', + 'creation_date', ] tags = TagListSerializerField(required=False) diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index 219d13b7d2..895ced7ee8 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -1,5 +1,6 @@ """Unit tests for the various part API endpoints""" +from datetime import datetime from decimal import Decimal from enum import IntEnum from random import randint @@ -1125,6 +1126,52 @@ class PartAPITest(PartAPITestBase): if part.category: self.assertEqual(part.category.name, row['Category Name']) + def test_date_filters(self): + """Test that the creation date filters work correctly""" + + url = reverse('api-part-list') + + response = self.get(url) + + n = len(response.data) + + date_compare = datetime.fromisoformat('2019-01-01') + + # Filter by creation date + response = self.get( + url, + { + 'created_before': '2019-01-01', + }, + expected_code=200 + ) + + self.assertTrue(len(response.data) < n) + self.assertTrue(len(response.data) > 0) + + for item in response.data: + self.assertIsNotNone(item['creation_date']) + + date = datetime.fromisoformat(item['creation_date']) + self.assertLessEqual(date, date_compare) + + response = self.get( + url, + { + 'created_after': '2019-01-01', + }, + expected_code=200 + ) + + self.assertTrue(len(response.data) < n) + self.assertTrue(len(response.data) > 0) + + for item in response.data: + self.assertIsNotNone(item['creation_date']) + + date = datetime.fromisoformat(item['creation_date']) + self.assertGreaterEqual(date, date_compare) + class PartCreationTests(PartAPITestBase): """Tests for creating new Part instances via the API""" diff --git a/docker/production/.env b/docker/production/.env index 96c1fff3df..75f7486037 100644 --- a/docker/production/.env +++ b/docker/production/.env @@ -4,10 +4,10 @@ # Note: You *must* un-comment this line, and point it to a path on your local machine # e.g. Linux -#INVENTREE_EXT_VOLUME=/home/me/inventree-data +#INVENTREE_EXT_VOLUME=/home/inventree/data # e.g. Windows (docker desktop) -#INVENTREE_EXT_VOLUME=c:/Users/me/inventree-data +#INVENTREE_EXT_VOLUME=c:/Users/inventree/data # Default web port for the InvenTree server INVENTREE_WEB_PORT=1337