Adds ability to add custom serializer context information to the OPTIONS endpoint

- Will be useful for constructing prettier forms with information about the endpoint
This commit is contained in:
Oliver Walters 2022-05-04 15:06:02 +10:00
parent dbc0023c57
commit c7980a347e
4 changed files with 83 additions and 15 deletions

View File

@ -37,6 +37,25 @@ class InvenTreeMetadata(SimpleMetadata):
metadata = super().determine_metadata(request, view)
"""
Custom context information to pass through to the OPTIONS endpoint,
if the "context=True" is supplied to the OPTIONS requst
Serializer class can supply either:
- get_context_data() (method)
- CONTEXT_DATA (dict)
"""
context = {}
if hasattr(self.serializer, 'get_context_data'):
context = self.serializer.get_context_data()
elif hasattr(self.erializer, 'CONTEXT_DATA'):
context = self.serializer.CONTEXT_DATA
metadata['context'] = context
user = request.user
if user is None:
@ -99,6 +118,8 @@ class InvenTreeMetadata(SimpleMetadata):
to any fields whose Meta.model specifies a default value
"""
self.serializer = serializer
serializer_info = super().get_serializer_info(serializer)
model_class = None

View File

@ -286,7 +286,37 @@ class PurchaseOrderDetail(generics.RetrieveUpdateDestroyAPIView):
return queryset
class PurchaseOrderReceive(generics.CreateAPIView):
class PurchaseOrderContextMixin:
def get_serializer_context(self):
""" Add the PurchaseOrder object to the serializer context """
context = super().get_serializer_context()
# Pass the purchase order through to the serializer for validation
try:
context['order'] = models.PurchaseOrder.objects.get(pk=self.kwargs.get('pk', None))
except:
pass
context['request'] = self.request
return context
class PurchaseOrderCancel(PurchaseOrderContextMixin, generics.CreateAPIView):
"""
API endpoint to 'cancel' a purchase order.
The purchase order must be in a state which can be cancelled
"""
queryset = models.PurchaseOrderLineItem.objects.all()
serializer_class = serializers.PurchaseOrderCancelSerializer
class PurchaseOrderReceive(PurchaseOrderContextMixin, generics.CreateAPIView):
"""
API endpoint to receive stock items against a purchase order.
@ -303,20 +333,6 @@ class PurchaseOrderReceive(generics.CreateAPIView):
serializer_class = serializers.PurchaseOrderReceiveSerializer
def get_serializer_context(self):
context = super().get_serializer_context()
# Pass the purchase order through to the serializer for validation
try:
context['order'] = models.PurchaseOrder.objects.get(pk=self.kwargs.get('pk', None))
except:
pass
context['request'] = self.request
return context
class PurchaseOrderLineItemFilter(rest_filters.FilterSet):
"""
@ -1107,6 +1123,7 @@ order_api_urls = [
# Individual purchase order detail URLs
re_path(r'^(?P<pk>\d+)/', include([
re_path(r'^receive/', PurchaseOrderReceive.as_view(), name='api-po-receive'),
re_path(r'^cancel/', PurchaseOrderCancel.as_view(), name='api-po-cancel'),
re_path(r'.*$', PurchaseOrderDetail.as_view(), name='api-po-detail'),
])),

View File

@ -380,6 +380,7 @@ class PurchaseOrder(Order):
PurchaseOrderStatus.PENDING
]
@transaction.atomic
def cancel_order(self):
""" Marks the PurchaseOrder as CANCELLED. """

View File

@ -179,6 +179,35 @@ class PurchaseOrderSerializer(AbstractOrderSerializer, ReferenceIndexingSerializ
]
class PurchaseOrderCancelSerializer(serializers.Serializer):
"""
Serializer for cancelling a PurchaseOrder
"""
class Meta:
fields = [],
def get_context_data(self):
"""
Return custom context information about the order
"""
self.order = self.context['order']
return {
'can_cancel': self.order.can_cancel(),
}
def save(self):
order = self.context['order']
if not order.can_cancel():
raise ValidationError(_("Order cannot be cancelled"))
order.cancel_order()
class PurchaseOrderLineItemSerializer(InvenTreeModelSerializer):
@staticmethod