2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-16 03:55:41 +00:00

Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters
2022-07-06 10:19:34 +10:00
9 changed files with 136 additions and 11 deletions

View File

@ -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
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
- 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

View File

@ -741,7 +741,7 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
"""Initialization routine for the serializer"""
order_detail = kwargs.pop('order_detail', False)
part_detail = kwargs.pop('part_detail', True)
item_detail = kwargs.pop('item_detail', False)
item_detail = kwargs.pop('item_detail', True)
location_detail = kwargs.pop('location_detail', False)
customer_detail = kwargs.pop('customer_detail', False)

View File

@ -24,6 +24,7 @@ from common.models import InvenTreeSetting
from company.models import Company, ManufacturerPart, SupplierPart
from InvenTree.api import (APIDownloadMixin, AttachmentMixin,
ListCreateDestroyAPIView)
from InvenTree.filters import InvenTreeOrderingFilter
from InvenTree.helpers import DownloadFile, increment, isNull, str2bool
from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI, RetrieveAPI,
RetrieveUpdateAPI, RetrieveUpdateDestroyAPI,
@ -1756,12 +1757,32 @@ class BomList(ListCreateDestroyAPIView):
filter_backends = [
DjangoFilterBackend,
filters.SearchFilter,
filters.OrderingFilter,
InvenTreeOrderingFilter,
]
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):
"""API endpoint for uploading a complete Bill of Materials.

View File

@ -24,6 +24,7 @@
part: 100
sub_part: 5
quantity: 25
reference: ABCDE
# 3 x Orphan
- model: part.bomitem
@ -32,6 +33,7 @@
part: 100
sub_part: 50
quantity: 3
reference: VWXYZ
- model: part.bomitem
pk: 5
@ -39,6 +41,7 @@
part: 1
sub_part: 5
quantity: 3
reference: LMNOP
# Make "Assembly" from "Bob"
- model: part.bomitem

View File

@ -1647,6 +1647,102 @@ class BomItemTest(InvenTreeAPITestCase):
for key in ['available_stock', 'available_substitute_stock']:
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):
"""Get the detail view for a single BomItem object."""
url = reverse('api-bom-item-detail', kwargs={'pk': 3})

View File

@ -3236,10 +3236,12 @@ function showAllocationSubTable(index, row, element, options) {
formatter: function(value, row, index, field) {
var text = '';
if (row.serial != null && row.quantity == 1) {
text = `{% trans "Serial Number" %}: ${row.serial}`;
} else {
text = `{% trans "Quantity" %}: ${row.quantity}`;
var item = row.item_detail;
var text = `{% trans "Quantity" %}: ${row.quantity}`;
if (item && item.serial != null && row.quantity == 1) {
text = `{% trans "Serial Number" %}: ${item.serial}`;
}
return renderLink(text, `/stock/item/${row.item}/`);

View File

@ -94,9 +94,9 @@ distlib==0.3.4 \
--hash=sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b \
--hash=sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579
# via virtualenv
django==3.2.13 \
--hash=sha256:6d93497a0a9bf6ba0e0b1a29cccdc40efbfc76297255b1309b3a884a688ec4b6 \
--hash=sha256:b896ca61edc079eb6bbaa15cf6071eb69d6aac08cce5211583cfb41515644fdf
django==3.2.14 \
--hash=sha256:677182ba8b5b285a4e072f3ac17ceee6aff1b5ce77fd173cc5b6a2d3dc022fcf \
--hash=sha256:a8681e098fa60f7c33a4b628d6fcd3fe983a0939ff1301ecacac21d0b38bad56
# via
# -c requirements.txt
# django-debug-toolbar

View File

@ -1,5 +1,5 @@
# Please keep this list sorted - if you pin a version provide a reason
Django<4 # Django package
Django>=3.2.14,<4 # Django package
coreapi # API documentation for djangorestframework
cryptography==3.4.8 # Core cryptographic functionality
django-allauth # SSO for external providers via OpenID

View File

@ -42,7 +42,7 @@ defusedxml==0.7.1
# python3-openid
diff-match-patch==20200713
# via django-import-export
django==3.2.13
django==3.2.14
# via
# -r requirements.in
# django-allauth