mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Refactor the POReceive API endpoint
- Lessons learned from the build allocate - Use serializer.save() directly
This commit is contained in:
parent
7ecd4c70e7
commit
29588ff2c5
@ -172,7 +172,7 @@ class TestBuildAPI(APITestCase):
|
|||||||
|
|
||||||
# Filter by 'part' status
|
# Filter by 'part' status
|
||||||
response = self.client.get(url, {'part': 25}, format='json')
|
response = self.client.get(url, {'part': 25}, format='json')
|
||||||
self.assertEqual(len(response.data), 2)
|
self.assertEqual(len(response.data), 1)
|
||||||
|
|
||||||
# Filter by an invalid part
|
# Filter by an invalid part
|
||||||
response = self.client.get(url, {'part': 99999}, format='json')
|
response = self.client.get(url, {'part': 99999}, format='json')
|
||||||
|
@ -252,76 +252,6 @@ class POReceive(generics.CreateAPIView):
|
|||||||
|
|
||||||
return order
|
return order
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
|
||||||
|
|
||||||
# Which purchase order are we receiving against?
|
|
||||||
self.order = self.get_order()
|
|
||||||
|
|
||||||
# Validate the serialized data
|
|
||||||
serializer = self.get_serializer(data=request.data)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
|
|
||||||
# Receive the line items
|
|
||||||
try:
|
|
||||||
self.receive_items(serializer)
|
|
||||||
except DjangoValidationError as exc:
|
|
||||||
# Re-throw a django error as a DRF error
|
|
||||||
raise ValidationError(detail=serializers.as_serializer_error(exc))
|
|
||||||
|
|
||||||
headers = self.get_success_headers(serializer.data)
|
|
||||||
|
|
||||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
|
||||||
|
|
||||||
@transaction.atomic
|
|
||||||
def receive_items(self, serializer):
|
|
||||||
"""
|
|
||||||
Receive the items
|
|
||||||
|
|
||||||
At this point, much of the heavy lifting has been done for us by DRF serializers!
|
|
||||||
|
|
||||||
We have a list of "items", each a dict which contains:
|
|
||||||
- line_item: A PurchaseOrderLineItem matching this order
|
|
||||||
- location: A destination location
|
|
||||||
- quantity: A validated numerical quantity
|
|
||||||
- status: The status code for the received item
|
|
||||||
"""
|
|
||||||
|
|
||||||
data = serializer.validated_data
|
|
||||||
|
|
||||||
location = data['location']
|
|
||||||
|
|
||||||
items = data['items']
|
|
||||||
|
|
||||||
# Check if the location is not specified for any particular item
|
|
||||||
for item in items:
|
|
||||||
|
|
||||||
line = item['line_item']
|
|
||||||
|
|
||||||
if not item.get('location', None):
|
|
||||||
# If a global location is specified, use that
|
|
||||||
item['location'] = location
|
|
||||||
|
|
||||||
if not item['location']:
|
|
||||||
# The line item specifies a location?
|
|
||||||
item['location'] = line.get_destination()
|
|
||||||
|
|
||||||
if not item['location']:
|
|
||||||
raise ValidationError({
|
|
||||||
'location': _("Destination location must be specified"),
|
|
||||||
})
|
|
||||||
|
|
||||||
# Now we can actually receive the items
|
|
||||||
for item in items:
|
|
||||||
|
|
||||||
self.order.receive_line_item(
|
|
||||||
item['line_item'],
|
|
||||||
item['location'],
|
|
||||||
item['quantity'],
|
|
||||||
self.request.user,
|
|
||||||
status=item['status'],
|
|
||||||
barcode=item.get('barcode', ''),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class POLineItemList(generics.ListCreateAPIView):
|
class POLineItemList(generics.ListCreateAPIView):
|
||||||
""" API endpoint for accessing a list of POLineItem objects
|
""" API endpoint for accessing a list of POLineItem objects
|
||||||
|
@ -7,7 +7,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models, transaction
|
||||||
from django.db.models import Case, When, Value
|
from django.db.models import Case, When, Value
|
||||||
from django.db.models import BooleanField, ExpressionWrapper, F
|
from django.db.models import BooleanField, ExpressionWrapper, F
|
||||||
|
|
||||||
@ -301,6 +301,46 @@ class POReceiveSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
|
||||||
|
data = self.validated_data
|
||||||
|
|
||||||
|
order = self.context['order']
|
||||||
|
|
||||||
|
items = data['items']
|
||||||
|
location = data.get('location', None)
|
||||||
|
|
||||||
|
# Check if the location is not specified for any particular item
|
||||||
|
for item in items:
|
||||||
|
|
||||||
|
line = item['line_item']
|
||||||
|
|
||||||
|
if not item.get('location', None):
|
||||||
|
# If a global location is specified, use that
|
||||||
|
item['location'] = location
|
||||||
|
|
||||||
|
if not item['location']:
|
||||||
|
# The line item specifies a location?
|
||||||
|
item['location'] = line.get_destination()
|
||||||
|
|
||||||
|
if not item['location']:
|
||||||
|
raise ValidationError({
|
||||||
|
'location': _("Destination location must be specified"),
|
||||||
|
})
|
||||||
|
|
||||||
|
# Now we can actually receive the items into stock
|
||||||
|
with transaction.atomic():
|
||||||
|
for item in items:
|
||||||
|
order.receive_line_item(
|
||||||
|
item['line_item'],
|
||||||
|
item['location'],
|
||||||
|
item['quantity'],
|
||||||
|
self.request.user,
|
||||||
|
status=item['status'],
|
||||||
|
barcode=item.get('barcode', ''),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = [
|
fields = [
|
||||||
'items',
|
'items',
|
||||||
|
Loading…
Reference in New Issue
Block a user