mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
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
This commit is contained in:
parent
44614493e9
commit
064caafebb
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
|
|
||||||
# InvenTree API version
|
# 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."""
|
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||||
|
|
||||||
INVENTREE_API_TEXT = """
|
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
|
v154 -> 2023-11-21 : https://github.com/inventree/InvenTree/pull/5944
|
||||||
- Adds "responsible" field to the ProjectCode table
|
- Adds "responsible" field to the ProjectCode table
|
||||||
|
|
||||||
|
@ -19,9 +19,7 @@ class InvenTreeDateFilter(rest_filters.DateFilter):
|
|||||||
"""Override the filter method to handle timezones correctly."""
|
"""Override the filter method to handle timezones correctly."""
|
||||||
|
|
||||||
if settings.USE_TZ:
|
if settings.USE_TZ:
|
||||||
|
if value is not None:
|
||||||
# Check if value is already timezone aware
|
|
||||||
if value is not None and not timezone.is_aware(value):
|
|
||||||
tz = timezone.get_current_timezone()
|
tz = timezone.get_current_timezone()
|
||||||
value = datetime(value.year, value.month, value.day)
|
value = datetime(value.year, value.month, value.day)
|
||||||
value = make_aware(value, tz, True)
|
value = make_aware(value, tz, True)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
description: 'M2x4 low profile head screw'
|
description: 'M2x4 low profile head screw'
|
||||||
category: 8
|
category: 8
|
||||||
link: http://www.acme.com/parts/m2x4lphs
|
link: http://www.acme.com/parts/m2x4lphs
|
||||||
|
creation_date: '2018-01-01'
|
||||||
tree_id: 0
|
tree_id: 0
|
||||||
purchaseable: True
|
purchaseable: True
|
||||||
level: 0
|
level: 0
|
||||||
@ -19,6 +20,7 @@
|
|||||||
name: 'M3x12 SHCS'
|
name: 'M3x12 SHCS'
|
||||||
description: 'M3x12 socket head cap screw'
|
description: 'M3x12 socket head cap screw'
|
||||||
category: 8
|
category: 8
|
||||||
|
creation_date: '2019-02-02'
|
||||||
tree_id: 0
|
tree_id: 0
|
||||||
level: 0
|
level: 0
|
||||||
lft: 0
|
lft: 0
|
||||||
@ -32,6 +34,7 @@
|
|||||||
name: 'R_2K2_0805'
|
name: 'R_2K2_0805'
|
||||||
description: '2.2kOhm resistor in 0805 package'
|
description: '2.2kOhm resistor in 0805 package'
|
||||||
category: 2
|
category: 2
|
||||||
|
creation_date: '2020-03-03'
|
||||||
tree_id: 0
|
tree_id: 0
|
||||||
level: 0
|
level: 0
|
||||||
lft: 0
|
lft: 0
|
||||||
@ -44,6 +47,7 @@
|
|||||||
name: 'R_4K7_0603'
|
name: 'R_4K7_0603'
|
||||||
description: '4.7kOhm resistor in 0603 package'
|
description: '4.7kOhm resistor in 0603 package'
|
||||||
category: 2
|
category: 2
|
||||||
|
creation_date: '2021-04-04'
|
||||||
default_location: 2 # Home/Bathroom
|
default_location: 2 # Home/Bathroom
|
||||||
tree_id: 0
|
tree_id: 0
|
||||||
level: 0
|
level: 0
|
||||||
@ -58,6 +62,7 @@
|
|||||||
description: '22nF capacitor in 0805 package'
|
description: '22nF capacitor in 0805 package'
|
||||||
purchaseable: true
|
purchaseable: true
|
||||||
category: 3
|
category: 3
|
||||||
|
creation_date: '2022-05-05'
|
||||||
tree_id: 0
|
tree_id: 0
|
||||||
level: 0
|
level: 0
|
||||||
lft: 0
|
lft: 0
|
||||||
@ -69,6 +74,7 @@
|
|||||||
name: 'Widget'
|
name: 'Widget'
|
||||||
description: 'A watchamacallit'
|
description: 'A watchamacallit'
|
||||||
category: 7
|
category: 7
|
||||||
|
creation_date: '2023-06-06'
|
||||||
salable: true
|
salable: true
|
||||||
assembly: true
|
assembly: true
|
||||||
trackable: true
|
trackable: true
|
||||||
@ -85,6 +91,7 @@
|
|||||||
description: 'A part without a category'
|
description: 'A part without a category'
|
||||||
category: null
|
category: null
|
||||||
salable: true
|
salable: true
|
||||||
|
creation_date: '2024-07-07'
|
||||||
tree_id: 0
|
tree_id: 0
|
||||||
level: 0
|
level: 0
|
||||||
lft: 0
|
lft: 0
|
||||||
@ -99,6 +106,7 @@
|
|||||||
assembly: true
|
assembly: true
|
||||||
salable: true
|
salable: true
|
||||||
purchaseable: false
|
purchaseable: false
|
||||||
|
creation_date: '2025-08-08'
|
||||||
category: 7
|
category: 7
|
||||||
active: True
|
active: True
|
||||||
IPN: BOB
|
IPN: BOB
|
||||||
@ -114,6 +122,7 @@
|
|||||||
name: 'Assembly'
|
name: 'Assembly'
|
||||||
description: 'A high level assembly part'
|
description: 'A high level assembly part'
|
||||||
salable: true
|
salable: true
|
||||||
|
creation_date: '2026-09-09'
|
||||||
active: True
|
active: True
|
||||||
tree_id: 0
|
tree_id: 0
|
||||||
level: 0
|
level: 0
|
||||||
@ -128,6 +137,7 @@
|
|||||||
description: 'A chair, which is actually just a template part'
|
description: 'A chair, which is actually just a template part'
|
||||||
is_template: True
|
is_template: True
|
||||||
trackable: true
|
trackable: true
|
||||||
|
creation_date: '2027-10-10'
|
||||||
salable: true
|
salable: true
|
||||||
category: 7
|
category: 7
|
||||||
tree_id: 1
|
tree_id: 1
|
||||||
@ -142,6 +152,7 @@
|
|||||||
description: 'A variant chair part which is blue'
|
description: 'A variant chair part which is blue'
|
||||||
variant_of: 10000
|
variant_of: 10000
|
||||||
trackable: true
|
trackable: true
|
||||||
|
creation_date: '2028-11-11'
|
||||||
category: 7
|
category: 7
|
||||||
tree_id: 1
|
tree_id: 1
|
||||||
level: 0
|
level: 0
|
||||||
@ -157,6 +168,7 @@
|
|||||||
IPN: "R.CH"
|
IPN: "R.CH"
|
||||||
trackable: true
|
trackable: true
|
||||||
salable: true
|
salable: true
|
||||||
|
creation_date: '2029-12-12'
|
||||||
category: 7
|
category: 7
|
||||||
tree_id: 1
|
tree_id: 1
|
||||||
level: 0
|
level: 0
|
||||||
@ -171,6 +183,7 @@
|
|||||||
variant_of: 10000
|
variant_of: 10000
|
||||||
category: 7
|
category: 7
|
||||||
trackable: true
|
trackable: true
|
||||||
|
creation_date: '2030-01-01'
|
||||||
tree_id: 1
|
tree_id: 1
|
||||||
level: 0
|
level: 0
|
||||||
lft: 0
|
lft: 0
|
||||||
@ -184,6 +197,7 @@
|
|||||||
variant_of: 10003
|
variant_of: 10003
|
||||||
is_template: true
|
is_template: true
|
||||||
category: 7
|
category: 7
|
||||||
|
creation_date: '2031-02-02'
|
||||||
trackable: true
|
trackable: true
|
||||||
tree_id: 1
|
tree_id: 1
|
||||||
level: 0
|
level: 0
|
||||||
|
@ -504,6 +504,7 @@ class PartSerializer(InvenTree.serializers.RemoteImageMixin, InvenTree.serialize
|
|||||||
'category_detail',
|
'category_detail',
|
||||||
'category_path',
|
'category_path',
|
||||||
'component',
|
'component',
|
||||||
|
'creation_date',
|
||||||
'default_expiry',
|
'default_expiry',
|
||||||
'default_location',
|
'default_location',
|
||||||
'default_supplier',
|
'default_supplier',
|
||||||
@ -558,6 +559,7 @@ class PartSerializer(InvenTree.serializers.RemoteImageMixin, InvenTree.serialize
|
|||||||
|
|
||||||
read_only_fields = [
|
read_only_fields = [
|
||||||
'barcode_hash',
|
'barcode_hash',
|
||||||
|
'creation_date',
|
||||||
]
|
]
|
||||||
|
|
||||||
tags = TagListSerializerField(required=False)
|
tags = TagListSerializerField(required=False)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Unit tests for the various part API endpoints"""
|
"""Unit tests for the various part API endpoints"""
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from random import randint
|
from random import randint
|
||||||
@ -1125,6 +1126,52 @@ class PartAPITest(PartAPITestBase):
|
|||||||
if part.category:
|
if part.category:
|
||||||
self.assertEqual(part.category.name, row['Category Name'])
|
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):
|
class PartCreationTests(PartAPITestBase):
|
||||||
"""Tests for creating new Part instances via the API"""
|
"""Tests for creating new Part instances via the API"""
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
# Note: You *must* un-comment this line, and point it to a path on your local machine
|
# Note: You *must* un-comment this line, and point it to a path on your local machine
|
||||||
|
|
||||||
# e.g. Linux
|
# e.g. Linux
|
||||||
#INVENTREE_EXT_VOLUME=/home/me/inventree-data
|
#INVENTREE_EXT_VOLUME=/home/inventree/data
|
||||||
|
|
||||||
# e.g. Windows (docker desktop)
|
# 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
|
# Default web port for the InvenTree server
|
||||||
INVENTREE_WEB_PORT=1337
|
INVENTREE_WEB_PORT=1337
|
||||||
|
Loading…
x
Reference in New Issue
Block a user