Serializer improvements

- Pass the "order" down to the nested serializers for validation
This commit is contained in:
Oliver 2021-08-24 00:29:38 +10:00
parent dc53a433a7
commit 6091f2ba33
2 changed files with 58 additions and 6 deletions

View File

@ -225,6 +225,15 @@ class POReceive(generics.CreateAPIView):
serializer_class = POReceiveSerializer
def get_serializer_context(self):
context = super().get_serializer_context()
# Pass the purchase order through to the serializer for validation
context['order'] = self.get_order()
return context
def get_order(self):
"""
Returns the PurchaseOrder associated with this API endpoint
@ -235,13 +244,51 @@ class POReceive(generics.CreateAPIView):
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)
# Check that the received line items are indeed correct
self.validate(serializer.validated_data)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def validate(self, data):
"""
Validate the deserialized data.
At this point, much of the heavy lifting has been done for us by DRF serializers
"""
location = data['location']
# Keep track of validated data "on the fly"
self.items = []
for item in data['items']:
supplier_part = item['supplier_part']
# Location specified for this part
item_location = item['location']
if not item_location:
# Both item_location and location are not specified
if not location:
raise ValidationError({
'location': _("Destination location must be specified"),
})
item['location'] = location
quantity = item['quantity']
class POLineItemList(generics.ListCreateAPIView):
""" API endpoint for accessing a list of POLineItem objects

View File

@ -172,12 +172,19 @@ class POLineItemReceiveSerializer(serializers.Serializer):
A serializer for receiving a single purchase order line item against a purchase order
"""
supplier_part = serializers.PrimaryKeyRelatedField(
queryset=company.models.SupplierPart.objects.all(),
line_item = serializers.PrimaryKeyRelatedField(
queryset=PurchaseOrderLineItem.objects.all(),
many=False,
label=_('Supplier Part'),
allow_null=False,
required=True,
label=_('Line Item'),
)
def validate_line_item(self, item):
if item.order != self.context['order']:
raise ValidationError(_('Line item does not match purchase order'))
location = serializers.PrimaryKeyRelatedField(
queryset=stock.models.StockLocation.objects.all(),
many=False,
@ -205,9 +212,7 @@ class POReceiveSerializer(serializers.Serializer):
Serializer for receiving items against a purchase order
"""
items = POLineItemReceiveSerializer(
many=True,
)
items = POLineItemReceiveSerializer(many=True)
location = serializers.PrimaryKeyRelatedField(
queryset=stock.models.StockLocation.objects.all(),