diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index 12ceb600fc..9a76f1b451 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -311,11 +311,21 @@ class PurchaseOrderCancel(PurchaseOrderContextMixin, generics.CreateAPIView): The purchase order must be in a state which can be cancelled """ - queryset = models.PurchaseOrderLineItem.objects.all() + queryset = models.PurchaseOrder.objects.all() serializer_class = serializers.PurchaseOrderCancelSerializer +class PurchaseOrderComplete(PurchaseOrderContextMixin, generics.CreateAPIView): + """ + API endpoint to 'complete' a purchase order + """ + + queryset = models.PurchaseOrder.objects.all() + + serializer_class = serializers.PurchaseOrderCompleteSerializer + + class PurchaseOrderReceive(PurchaseOrderContextMixin, generics.CreateAPIView): """ API endpoint to receive stock items against a purchase order. @@ -1124,6 +1134,7 @@ order_api_urls = [ re_path(r'^(?P\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'^complete/', PurchaseOrderComplete.as_view(), name='api-po-complete'), re_path(r'.*$', PurchaseOrderDetail.as_view(), name='api-po-detail'), ])), diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 0ac55a2f22..f9ece96bda 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -30,17 +30,6 @@ class IssuePurchaseOrderForm(HelperForm): ] -class CompletePurchaseOrderForm(HelperForm): - - confirm = forms.BooleanField(required=True, label=_('Confirm'), help_text=_("Mark order as complete")) - - class Meta: - model = PurchaseOrder - fields = [ - 'confirm', - ] - - class CancelSalesOrderForm(HelperForm): confirm = forms.BooleanField(required=True, label=_('Confirm'), help_text=_('Cancel order')) diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index a151da77b9..47ec14377d 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -208,6 +208,32 @@ class PurchaseOrderCancelSerializer(serializers.Serializer): order.cancel_order() +class PurchaseOrderCompleteSerializer(serializers.Serializer): + """ + Serializer for completing a purchase order + """ + + class Meta: + fields = [] + + def get_context_data(self): + """ + Custom context information for this serializer + """ + + order = self.context['order'] + + return { + 'is_complete': order.is_complete, + } + + def save(self): + + order = self.context['order'] + + + + class PurchaseOrderLineItemSerializer(InvenTreeModelSerializer): @staticmethod diff --git a/InvenTree/order/templates/order/order_base.html b/InvenTree/order/templates/order/order_base.html index 70d791081b..dc0c4344b1 100644 --- a/InvenTree/order/templates/order/order_base.html +++ b/InvenTree/order/templates/order/order_base.html @@ -252,9 +252,15 @@ $("#receive-order").click(function() { }); $("#complete-order").click(function() { - launchModalForm("{% url 'po-complete' order.id %}", { - reload: true, - }); + + completePurchaseOrder( + {{ order.pk }}, + { + onSuccess: function() { + window.location.reload(); + } + } + ); }); $("#cancel-order").click(function() { diff --git a/InvenTree/order/templates/order/order_complete.html b/InvenTree/order/templates/order/order_complete.html deleted file mode 100644 index ef35841f9d..0000000000 --- a/InvenTree/order/templates/order/order_complete.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "modal_form.html" %} - -{% load i18n %} - -{% block pre_form_content %} - -{% trans 'Mark this order as complete?' %} -{% if not order.is_complete %} -
- {% trans 'This order has line items which have not been marked as received.' %}
- {% trans 'Completing this order means that the order and line items will no longer be editable.' %} -
-{% endif %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/urls.py b/InvenTree/order/urls.py index 79bd897a4d..74c7976379 100644 --- a/InvenTree/order/urls.py +++ b/InvenTree/order/urls.py @@ -12,8 +12,6 @@ from . import views purchase_order_detail_urls = [ re_path(r'^issue/', views.PurchaseOrderIssue.as_view(), name='po-issue'), - re_path(r'^complete/', views.PurchaseOrderComplete.as_view(), name='po-complete'), - re_path(r'^upload/', views.PurchaseOrderUpload.as_view(), name='po-upload'), re_path(r'^export/', views.PurchaseOrderExport.as_view(), name='po-export'), diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index a3f4fc68e6..b36f64c937 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -140,44 +140,6 @@ class PurchaseOrderIssue(AjaxUpdateView): } -class PurchaseOrderComplete(AjaxUpdateView): - """ View for marking a PurchaseOrder as complete. - """ - - form_class = order_forms.CompletePurchaseOrderForm - model = PurchaseOrder - ajax_template_name = "order/order_complete.html" - ajax_form_title = _("Complete Order") - context_object_name = 'order' - - def get_context_data(self): - - ctx = { - 'order': self.get_object(), - } - - return ctx - - def validate(self, order, form, **kwargs): - - confirm = str2bool(form.cleaned_data.get('confirm', False)) - - if not confirm: - form.add_error('confirm', _('Confirm order completion')) - - def save(self, order, form, **kwargs): - """ - Complete the PurchaseOrder - """ - - order.complete_order() - - def get_data(self): - return { - 'success': _('Purchase order completed') - } - - class PurchaseOrderUpload(FileManagementFormView): ''' PurchaseOrder: Upload file, match to fields and parts (using multi-Step form) ''' diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index c1abe2cafb..aedbb5a5bf 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -21,6 +21,7 @@ /* exported allocateStockToSalesOrder, cancelPurchaseOrder, + completePurchaseOrder, completeShipment, createSalesOrder, createSalesOrderShipment, @@ -142,6 +143,46 @@ function completeShipment(shipment_id) { } +function completePurchaseOrder(order_id, options={}) { + + constructForm( + `/api/order/po/${order_id}/complete/`, + { + method: 'POST', + title: '{% trans "Complete Purchase Order" %}', + confirm: true, + preFormContent: function(opts) { + + var html = ` +
+ {% trans "Mark this order as complete?" %} +
`; + + if (opts.context.is_complete) { + html += ` +
+ {% trans "All line items have been received" %} +
`; + } else { + html += ` +
+ {% trans 'This order has line items which have not been marked as received.' %}
+ {% trans 'Completing this order means that the order and line items will no longer be editable.' %} +
`; + } + + return html; + }, + onSuccess: function(response) { + if (options.onSuccess) { + options.onSuccess(response); + } + } + } + ); +} + + function cancelPurchaseOrder(order_id, options={}) { var html = `