Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Oliver Walters 2020-10-19 00:03:15 +11:00
commit c0a18ef244
6 changed files with 114 additions and 22 deletions

View File

@ -42,6 +42,8 @@ class InvenTreeBarcodePlugin(BarcodePlugin):
elif type(self.data) is str:
try:
self.data = json.loads(self.data)
if type(self.data) is not dict:
return False
except json.JSONDecodeError:
return False
else:

View File

@ -56,6 +56,34 @@ class BarcodeAPITest(APITestCase):
self.assertIn('plugin', data)
self.assertIsNone(data['plugin'])
def test_integer_barcode(self):
response = self.postBarcode(self.scan_url, '123456789')
self.assertEqual(response.status_code, status.HTTP_200_OK)
data = response.data
self.assertIn('error', data)
self.assertIn('barcode_data', data)
self.assertIn('hash', data)
self.assertIn('plugin', data)
self.assertIsNone(data['plugin'])
def test_array_barcode(self):
response = self.postBarcode(self.scan_url, "['foo', 'bar']")
self.assertEqual(response.status_code, status.HTTP_200_OK)
data = response.data
self.assertIn('error', data)
self.assertIn('barcode_data', data)
self.assertIn('hash', data)
self.assertIn('plugin', data)
self.assertIsNone(data['plugin'])
def test_barcode_generation(self):
item = StockItem.objects.get(pk=522)

View File

@ -2,30 +2,20 @@
JSON serializers for Part app
"""
import imghdr
from rest_framework import serializers
from .models import Part, PartStar
from .models import PartCategory
from .models import BomItem
from .models import PartParameter, PartParameterTemplate
from .models import PartAttachment
from .models import PartTestTemplate
from .models import PartSellPriceBreak
from stock.models import StockItem
from decimal import Decimal
from sql_util.utils import SubquerySum, SubqueryCount
from django.db.models import Q
from django.db.models.functions import Coalesce
from InvenTree.serializers import (InvenTreeAttachmentSerializerField,
InvenTreeModelSerializer)
from InvenTree.status_codes import BuildStatus, PurchaseOrderStatus
from rest_framework import serializers
from sql_util.utils import SubqueryCount, SubquerySum
from stock.models import StockItem
from InvenTree.status_codes import PurchaseOrderStatus, BuildStatus
from InvenTree.serializers import InvenTreeModelSerializer
from InvenTree.serializers import InvenTreeAttachmentSerializerField
from .models import (BomItem, Part, PartAttachment, PartCategory,
PartParameter, PartParameterTemplate, PartSellPriceBreak,
PartStar, PartTestTemplate)
class CategorySerializer(InvenTreeModelSerializer):
@ -41,6 +31,7 @@ class CategorySerializer(InvenTreeModelSerializer):
'pk',
'name',
'description',
'default_location',
'pathstring',
'url',
'parent',
@ -304,6 +295,7 @@ class PartSerializer(InvenTreeModelSerializer):
'category_detail',
'component',
'description',
'default_location',
'full_name',
'image',
'in_stock',

View File

@ -324,8 +324,31 @@ class StockList(generics.ListCreateAPIView):
serializer_class = StockItemSerializer
queryset = StockItem.objects.all()
# TODO - Override the 'create' method for this view,
# to allow the user to be recorded when a new StockItem object is created
def create(self, request, *args, **kwargs):
"""
Create a new StockItem object via the API.
We override the default 'create' implementation.
If a location is *not* specified, but the linked *part* has a default location,
we can pre-fill the location automatically.
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
item = serializer.save()
# A location was *not* specified - try to infer it
if 'location' not in request.data:
location = item.part.get_default_location()
if location is not None:
item.location = location
item.save()
# Return a response
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def list(self, request, *args, **kwargs):
"""

View File

@ -93,7 +93,7 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% if item.uid %}
<li><a href='#' id='unlink-barcode'><span class='fas fa-unlink'></span> {% trans "Unlink Barcode" %}</a></li>
{% else %}
<li><a href='#' id='link-barcode'><span class='fas fa-link'></span> {% trans "Link Barcode" %}</a></li>\
<li><a href='#' id='link-barcode'><span class='fas fa-link'></span> {% trans "Link Barcode" %}</a></li>
{% endif %}
{% endif %}
</ul>

View File

@ -97,6 +97,53 @@ class StockItemTest(StockAPITestCase):
response = self.client.get(self.list_url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_create_default_location(self):
"""
Test the default location functionality,
if a 'location' is not specified in the creation request.
"""
# The part 'R_4K7_0603' (pk=4) has a default location specified
response = self.client.post(
self.list_url,
data={
'part': 4,
'quantity': 10
}
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['location'], 2)
# What if we explicitly set the location to a different value?
response = self.client.post(
self.list_url,
data={
'part': 4,
'quantity': 20,
'location': 1,
}
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['location'], 1)
# And finally, what if we set the location explicitly to None?
response = self.client.post(
self.list_url,
data={
'part': 4,
'quantity': 20,
'location': '',
}
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['location'], None)
def test_stock_item_create(self):
"""
Test creation of a StockItem via the API