mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Allow searching of BOM List API endpoint (#3296)
* Allow searching of BOM List API endpoint * Bump API version * Adds ordering field options to BOM List API endpoint * Add some unit testing for new API features * Fixes for unit tests
This commit is contained in:
parent
1235d47eca
commit
0787264930
@ -7,6 +7,9 @@ INVENTREE_API_VERSION = 61
|
|||||||
"""
|
"""
|
||||||
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
|
||||||
|
|
||||||
|
v62 -> 2022-07-05 : https://github.com/inventree/InvenTree/pull/3296
|
||||||
|
- Allows search on BOM List API endpoint
|
||||||
|
|
||||||
v61 -> 2022-06-12 : https://github.com/inventree/InvenTree/pull/3183
|
v61 -> 2022-06-12 : https://github.com/inventree/InvenTree/pull/3183
|
||||||
- Migrate the "Convert Stock Item" form class to use the API
|
- Migrate the "Convert Stock Item" form class to use the API
|
||||||
- There is now an API endpoint for converting a stock item to a valid variant
|
- There is now an API endpoint for converting a stock item to a valid variant
|
||||||
|
@ -24,6 +24,7 @@ from common.models import InvenTreeSetting
|
|||||||
from company.models import Company, ManufacturerPart, SupplierPart
|
from company.models import Company, ManufacturerPart, SupplierPart
|
||||||
from InvenTree.api import (APIDownloadMixin, AttachmentMixin,
|
from InvenTree.api import (APIDownloadMixin, AttachmentMixin,
|
||||||
ListCreateDestroyAPIView)
|
ListCreateDestroyAPIView)
|
||||||
|
from InvenTree.filters import InvenTreeOrderingFilter
|
||||||
from InvenTree.helpers import DownloadFile, increment, isNull, str2bool
|
from InvenTree.helpers import DownloadFile, increment, isNull, str2bool
|
||||||
from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI, RetrieveAPI,
|
from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI, RetrieveAPI,
|
||||||
RetrieveUpdateAPI, RetrieveUpdateDestroyAPI,
|
RetrieveUpdateAPI, RetrieveUpdateDestroyAPI,
|
||||||
@ -1756,12 +1757,32 @@ class BomList(ListCreateDestroyAPIView):
|
|||||||
filter_backends = [
|
filter_backends = [
|
||||||
DjangoFilterBackend,
|
DjangoFilterBackend,
|
||||||
filters.SearchFilter,
|
filters.SearchFilter,
|
||||||
filters.OrderingFilter,
|
InvenTreeOrderingFilter,
|
||||||
]
|
]
|
||||||
|
|
||||||
filterset_fields = [
|
filterset_fields = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
search_fields = [
|
||||||
|
'reference',
|
||||||
|
'sub_part__name',
|
||||||
|
'sub_part__description',
|
||||||
|
'sub_part__IPN',
|
||||||
|
'sub_part__revision',
|
||||||
|
'sub_part__keywords',
|
||||||
|
'sub_part__category__name',
|
||||||
|
]
|
||||||
|
|
||||||
|
ordering_fields = [
|
||||||
|
'quantity',
|
||||||
|
'sub_part',
|
||||||
|
'available_stock',
|
||||||
|
]
|
||||||
|
|
||||||
|
ordering_field_aliases = {
|
||||||
|
'sub_part': 'sub_part__name',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class BomImportUpload(CreateAPI):
|
class BomImportUpload(CreateAPI):
|
||||||
"""API endpoint for uploading a complete Bill of Materials.
|
"""API endpoint for uploading a complete Bill of Materials.
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
part: 100
|
part: 100
|
||||||
sub_part: 5
|
sub_part: 5
|
||||||
quantity: 25
|
quantity: 25
|
||||||
|
reference: ABCDE
|
||||||
|
|
||||||
# 3 x Orphan
|
# 3 x Orphan
|
||||||
- model: part.bomitem
|
- model: part.bomitem
|
||||||
@ -32,6 +33,7 @@
|
|||||||
part: 100
|
part: 100
|
||||||
sub_part: 50
|
sub_part: 50
|
||||||
quantity: 3
|
quantity: 3
|
||||||
|
reference: VWXYZ
|
||||||
|
|
||||||
- model: part.bomitem
|
- model: part.bomitem
|
||||||
pk: 5
|
pk: 5
|
||||||
@ -39,6 +41,7 @@
|
|||||||
part: 1
|
part: 1
|
||||||
sub_part: 5
|
sub_part: 5
|
||||||
quantity: 3
|
quantity: 3
|
||||||
|
reference: LMNOP
|
||||||
|
|
||||||
# Make "Assembly" from "Bob"
|
# Make "Assembly" from "Bob"
|
||||||
- model: part.bomitem
|
- model: part.bomitem
|
||||||
|
@ -1647,6 +1647,102 @@ class BomItemTest(InvenTreeAPITestCase):
|
|||||||
for key in ['available_stock', 'available_substitute_stock']:
|
for key in ['available_stock', 'available_substitute_stock']:
|
||||||
self.assertTrue(key in el)
|
self.assertTrue(key in el)
|
||||||
|
|
||||||
|
def test_bom_list_search(self):
|
||||||
|
"""Test that we can search the BOM list API endpoint"""
|
||||||
|
|
||||||
|
url = reverse('api-bom-list')
|
||||||
|
|
||||||
|
response = self.get(url, expected_code=200)
|
||||||
|
|
||||||
|
self.assertEqual(len(response.data), 6)
|
||||||
|
|
||||||
|
# Limit the results with a search term
|
||||||
|
response = self.get(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'search': '0805',
|
||||||
|
},
|
||||||
|
expected_code=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(response.data), 3)
|
||||||
|
|
||||||
|
# Search by 'reference' field
|
||||||
|
for q in ['ABCDE', 'LMNOP', 'VWXYZ']:
|
||||||
|
response = self.get(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'search': q,
|
||||||
|
},
|
||||||
|
expected_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(response.data), 1)
|
||||||
|
self.assertEqual(response.data[0]['reference'], q)
|
||||||
|
|
||||||
|
# Search by nonsense data
|
||||||
|
response = self.get(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'search': 'xxxxxxxxxxxxxxxxx',
|
||||||
|
},
|
||||||
|
expected_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(response.data), 0)
|
||||||
|
|
||||||
|
def test_bom_list_ordering(self):
|
||||||
|
"""Test that the BOM list results can be ordered"""
|
||||||
|
|
||||||
|
url = reverse('api-bom-list')
|
||||||
|
|
||||||
|
# Order by increasing quantity
|
||||||
|
response = self.get(
|
||||||
|
f"{url}?ordering=+quantity",
|
||||||
|
expected_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(response.data), 6)
|
||||||
|
|
||||||
|
q1 = response.data[0]['quantity']
|
||||||
|
q2 = response.data[-1]['quantity']
|
||||||
|
|
||||||
|
self.assertTrue(q1 < q2)
|
||||||
|
|
||||||
|
# Order by decreasing quantity
|
||||||
|
response = self.get(
|
||||||
|
f"{url}?ordering=-quantity",
|
||||||
|
expected_code=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(q1, response.data[-1]['quantity'])
|
||||||
|
self.assertEqual(q2, response.data[0]['quantity'])
|
||||||
|
|
||||||
|
# Now test ordering by 'sub_part' (which is actually 'sub_part__name')
|
||||||
|
response = self.get(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'ordering': 'sub_part',
|
||||||
|
'sub_part_detail': True,
|
||||||
|
},
|
||||||
|
expected_code=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
n1 = response.data[0]['sub_part_detail']['name']
|
||||||
|
n2 = response.data[-1]['sub_part_detail']['name']
|
||||||
|
|
||||||
|
response = self.get(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'ordering': '-sub_part',
|
||||||
|
'sub_part_detail': True,
|
||||||
|
},
|
||||||
|
expected_code=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(n1, response.data[-1]['sub_part_detail']['name'])
|
||||||
|
self.assertEqual(n2, response.data[0]['sub_part_detail']['name'])
|
||||||
|
|
||||||
def test_get_bom_detail(self):
|
def test_get_bom_detail(self):
|
||||||
"""Get the detail view for a single BomItem object."""
|
"""Get the detail view for a single BomItem object."""
|
||||||
url = reverse('api-bom-item-detail', kwargs={'pk': 3})
|
url = reverse('api-bom-item-detail', kwargs={'pk': 3})
|
||||||
|
Loading…
Reference in New Issue
Block a user