diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index 9a76f1b451..e93c5b093f 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -326,6 +326,17 @@ class PurchaseOrderComplete(PurchaseOrderContextMixin, generics.CreateAPIView): serializer_class = serializers.PurchaseOrderCompleteSerializer +class PurchaseOrderIssue(PurchaseOrderContextMixin, generics.CreateAPIView): + """ + API endpoint to 'complete' a purchase order + """ + + queryset = models.PurchaseOrder.objects.all() + + serializer_class = serializers.PurchaseOrderIssueSerializer + + + class PurchaseOrderReceive(PurchaseOrderContextMixin, generics.CreateAPIView): """ API endpoint to receive stock items against a purchase order. @@ -1132,6 +1143,7 @@ order_api_urls = [ # Individual purchase order detail URLs re_path(r'^(?P\d+)/', include([ + re_path(r'^issue/', PurchaseOrderIssue.as_view(), name='api-po-issue'), 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'), diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index f9ece96bda..75b6cb94ec 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -19,16 +19,6 @@ from .models import PurchaseOrder from .models import SalesOrder -class IssuePurchaseOrderForm(HelperForm): - - confirm = forms.BooleanField(required=True, initial=False, label=_('Confirm'), help_text=_('Place order')) - - class Meta: - model = PurchaseOrder - fields = [ - 'confirm', - ] - class CancelSalesOrderForm(HelperForm): diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index 47ec14377d..5bd753f17f 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -230,8 +230,20 @@ class PurchaseOrderCompleteSerializer(serializers.Serializer): def save(self): order = self.context['order'] + order.complete_order() +class PurchaseOrderIssueSerializer(serializers.Serializer): + """ Serializer for issuing (sending) a purchase order """ + + class Meta: + fields = [] + + + def save(self): + + order = self.context['order'] + order.place_order() class PurchaseOrderLineItemSerializer(InvenTreeModelSerializer): diff --git a/InvenTree/order/templates/order/order_base.html b/InvenTree/order/templates/order/order_base.html index dc0c4344b1..ea1ab024ab 100644 --- a/InvenTree/order/templates/order/order_base.html +++ b/InvenTree/order/templates/order/order_base.html @@ -186,10 +186,14 @@ src="{% static 'img/blank_image.png' %}" {% if order.status == PurchaseOrderStatus.PENDING %} $("#place-order").click(function() { - launchModalForm("{% url 'po-issue' order.id %}", - { - reload: true, - }); + + issuePurchaseOrder( + {{ order.pk }}, + { + reload: true, + } + ); + }); {% endif %} diff --git a/InvenTree/order/templates/order/order_issue.html b/InvenTree/order/templates/order/order_issue.html deleted file mode 100644 index 058a7b529c..0000000000 --- a/InvenTree/order/templates/order/order_issue.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "modal_form.html" %} - -{% load i18n %} - -{% block pre_form_content %} - -
- {% trans 'After placing this purchase order, line items will no longer be editable.' %} -
- -{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/urls.py b/InvenTree/order/urls.py index 74c7976379..9536d96963 100644 --- a/InvenTree/order/urls.py +++ b/InvenTree/order/urls.py @@ -11,7 +11,6 @@ from . import views purchase_order_detail_urls = [ - re_path(r'^issue/', views.PurchaseOrderIssue.as_view(), name='po-issue'), 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 b36f64c937..4620c34210 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -113,33 +113,6 @@ class SalesOrderCancel(AjaxUpdateView): order.cancel_order() -class PurchaseOrderIssue(AjaxUpdateView): - """ View for changing a purchase order from 'PENDING' to 'ISSUED' """ - - model = PurchaseOrder - ajax_form_title = _('Issue Order') - ajax_template_name = "order/order_issue.html" - form_class = order_forms.IssuePurchaseOrderForm - - def validate(self, order, form, **kwargs): - - confirm = str2bool(self.request.POST.get('confirm', False)) - - if not confirm: - form.add_error('confirm', _('Confirm order placement')) - - def save(self, order, form, **kwargs): - """ - Once the form has been validated, place the order. - """ - order.place_order() - - def get_data(self): - return { - 'success': _('Purchase order issued') - } - - 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 aedbb5a5bf..9fe50e3548 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -27,6 +27,7 @@ createSalesOrderShipment, editPurchaseOrderLineItem, exportOrder, + issurPurchaseOrder, loadPurchaseOrderLineItemTable, loadPurchaseOrderExtraLineTable loadPurchaseOrderTable, @@ -142,7 +143,9 @@ function completeShipment(shipment_id) { }); } - +/* + * Launches a modal form to mark a PurchaseOrder as "complete" +*/ function completePurchaseOrder(order_id, options={}) { constructForm( @@ -174,39 +177,75 @@ function completePurchaseOrder(order_id, options={}) { return html; }, onSuccess: function(response) { - if (options.onSuccess) { - options.onSuccess(response); - } + handleFormSuccess(response, options); } } ); } +/* + * Launches a modal form to mark a PurchaseOrder as 'cancelled' + */ function cancelPurchaseOrder(order_id, options={}) { - var html = ` -
- {% trans "Are you sure you wish to cancel this purchase order?" %} -
`; - constructForm( `/api/order/po/${order_id}/cancel/`, { method: 'POST', title: '{% trans "Cancel Purchase Order" %}', confirm: true, - preFormContent: html, - onSuccess: function(response) { - if (options.onSuccess) { - options.onSuccess(response); + preFormContent: function(opts) { + var html = ` +
+ {% trans "Are you sure you wish to cancel this purchase order?" %} +
`; + + if (!opts.context.can_cancel) { + html += ` +
+ {% trans "This purchase order can not be cancelled" %} +
`; } + + return html; + }, + onSuccess: function(response) { + handleFormSuccess(response, options); } } ); } +/* + * Launches a modal form to mark a PurchaseOrder as "issued" + */ +function issuePurchaseOrder(order_id, options={}) { + + constructForm( + `/api/order/po/${order_id}/issue/`, + { + method: 'POST', + title: '{% trans "Issue Purchase Order" %}', + confirm: true, + preFormContent: function(opts) { + var html = ` +
+ {% trans 'After placing this purchase order, line items will no longer be editable.' %} +
`; + + return html; + }, + onSuccess: function(response) { + handleFormSuccess(response, options); + } + } + ) + +} + + // Open a dialog to create a new sales order shipment function createSalesOrderShipment(options={}) {