From 718ad037cf41e7d08fba8cee732b756be06dc0b6 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 14 Mar 2023 17:29:44 +1100 Subject: [PATCH] Adds basic "index" page for Return Order model --- .../order/templates/order/order_base.html | 2 +- .../order/templates/order/return_orders.html | 65 +++++++ .../templates/order/sales_order_base.html | 2 +- InvenTree/order/test_views.py | 2 +- InvenTree/order/urls.py | 13 +- InvenTree/order/views.py | 12 +- InvenTree/templates/js/translated/order.js | 166 +++++++++++++++++- InvenTree/templates/navbar.html | 11 +- 8 files changed, 260 insertions(+), 13 deletions(-) create mode 100644 InvenTree/order/templates/order/return_orders.html diff --git a/InvenTree/order/templates/order/order_base.html b/InvenTree/order/templates/order/order_base.html index d2a5bb9871..63d415afa2 100644 --- a/InvenTree/order/templates/order/order_base.html +++ b/InvenTree/order/templates/order/order_base.html @@ -10,7 +10,7 @@ {% endblock %} {% block breadcrumbs %} - + {% endblock %} diff --git a/InvenTree/order/templates/order/return_orders.html b/InvenTree/order/templates/order/return_orders.html new file mode 100644 index 0000000000..c2be127342 --- /dev/null +++ b/InvenTree/order/templates/order/return_orders.html @@ -0,0 +1,65 @@ +{% extends "page_base.html" %} + +{% load inventree_extras %} +{% load static %} +{% load i18n %} + +{% block page_title %} +{% inventree_title %} | {% trans "Return Orders" %} +{% endblock %} + +{% block breadcrumb_list %} +{% endblock %} + +{% block heading %} +{% trans "Return Orders" %} +{% endblock %} + + +{% block actions %} +{% if roles.returns.add %} + +{% endif %} +{% endblock actions %} + +{% block page_info %} + +
+
+
+
+ {% if report_enabled %} + + {% endif %} + {% include "filter_list.html" with id="returnorder" %} +
+
+
+ + +
+ +
+
+ +{% endblock page_info %} + +{% block js_ready %} +{{ block.super }} + +loadReturnOrderTable('#return-order-table', { +}); + +{% if report_enabled %} + +{% endif %} + +$('#return-order-create').click(function() { + createReturnOrder(); +}); + +{% endblock js_ready %} diff --git a/InvenTree/order/templates/order/sales_order_base.html b/InvenTree/order/templates/order/sales_order_base.html index 20acc35379..15278bfbb3 100644 --- a/InvenTree/order/templates/order/sales_order_base.html +++ b/InvenTree/order/templates/order/sales_order_base.html @@ -10,7 +10,7 @@ {% endblock %} {% block breadcrumbs %} - + {% endblock %} diff --git a/InvenTree/order/test_views.py b/InvenTree/order/test_views.py index cadd2914ad..cec085cf17 100644 --- a/InvenTree/order/test_views.py +++ b/InvenTree/order/test_views.py @@ -32,7 +32,7 @@ class OrderListTest(OrderViewTestCase): """Unit tests for the PurchaseOrder index page""" def test_order_list(self): """Tests for the PurchaseOrder index page""" - response = self.client.get(reverse('po-index')) + response = self.client.get(reverse('purchase-order-index')) self.assertEqual(response.status_code, 200) diff --git a/InvenTree/order/urls.py b/InvenTree/order/urls.py index 278914bd75..aca666702d 100644 --- a/InvenTree/order/urls.py +++ b/InvenTree/order/urls.py @@ -24,7 +24,7 @@ purchase_order_urls = [ re_path(r'^(?P\d+)/', include(purchase_order_detail_urls)), # Display complete list of purchase orders - re_path(r'^.*$', views.PurchaseOrderIndex.as_view(), name='po-index'), + re_path(r'^.*$', views.PurchaseOrderIndex.as_view(), name='purchase-order-index'), ] sales_order_detail_urls = [ @@ -38,10 +38,19 @@ sales_order_urls = [ re_path(r'^(?P\d+)/', include(sales_order_detail_urls)), # Display list of all sales orders - re_path(r'^.*$', views.SalesOrderIndex.as_view(), name='so-index'), + re_path(r'^.*$', views.SalesOrderIndex.as_view(), name='sales-order-index'), ] + +return_order_urls = [ + + # Display list of all return orders + re_path(r'^.*$', views.ReturnOrderIndex.as_view(), name='return-order-index'), +] + + order_urls = [ re_path(r'^purchase-order/', include(purchase_order_urls)), re_path(r'^sales-order/', include(sales_order_urls)), + re_path(r'^return-order/', include(return_order_urls)), ] diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index b3909971e0..7027f0a0f3 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -24,8 +24,8 @@ from plugin.views import InvenTreePluginViewMixin from . import forms as order_forms from .admin import PurchaseOrderLineItemResource, SalesOrderLineItemResource -from .models import (PurchaseOrder, PurchaseOrderLineItem, SalesOrder, - SalesOrderLineItem) +from .models import (PurchaseOrder, PurchaseOrderLineItem, ReturnOrder, + SalesOrder, SalesOrderLineItem) logger = logging.getLogger("inventree") @@ -51,6 +51,14 @@ class SalesOrderIndex(InvenTreeRoleMixin, ListView): context_object_name = 'orders' +class ReturnOrderIndex(InvenTreeRoleMixin, ListView): + """ReturnOrder index (list) view""" + + model = ReturnOrder + template_name = 'order/return_orders.html' + context_object_name = 'orders' + + class PurchaseOrderDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView): """Detail view for a PurchaseOrder object.""" diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index 1ec8b48702..3faf789afe 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -29,6 +29,7 @@ completePendingShipments, createPurchaseOrder, createPurchaseOrderLineItem, + createReturnOrder, createSalesOrder, createSalesOrderLineItem, createSalesOrderShipment, @@ -41,6 +42,7 @@ loadPurchaseOrderLineItemTable, loadPurchaseOrderExtraLineTable loadPurchaseOrderTable, + loadReturnOrderTable, loadSalesOrderAllocationTable, loadSalesOrderLineItemTable, loadSalesOrderExtraLineTable @@ -536,9 +538,7 @@ function salesOrderFields(options={}) { title: '{% trans "Add Customer" %}', fields: function() { var fields = companyFormFields(); - fields.is_customer.value = true; - return fields; } } @@ -573,10 +573,10 @@ function createSalesOrder(options={}) { constructForm('{% url "api-so-list" %}', { method: 'POST', fields: fields, + title: '{% trans "Create Sales Order" %}', onSuccess: function(data) { location.href = `/order/sales-order/${data.pk}/`; }, - title: '{% trans "Create Sales Order" %}', }); } @@ -4662,3 +4662,163 @@ function loadSalesOrderExtraLineTable(table, options={}) { columns: columns, }); } + + +/* + * Construct a set of fields for a ReturnOrder form + */ +function returnOrderFields(options={}) { + + let fields = { + reference: { + icon: 'fa-hashtag', + }, + description: {}, + customer: { + icon: 'fa-user-tie', + secondary: { + title: '{% trans "Add Customer" %}', + fields: function() { + var fields = companyFormFields(); + fields.is_customer.value = true; + return fields; + } + } + }, + customer_reference: {}, + link: { + icon: 'fa-link', + }, + responsible: { + icon: 'fa-user', + } + }; + + return fields; +} + + +/* + * Create a new Return Order + */ +function createReturnOrder(options={}) { + let fields = returnOrderFields(options); + + if (options.customer) { + fields.customer.value = options.customer; + } + + constructForm('{% url "api-return-order-list" %}', { + method: 'POST', + fields: fields, + title: '{% trans "Create Return Order" %}', + onSuccess: function(data) { + location.href = `/order/return-order/${data.pk}/`; + }, + }); +} + + +/* + * Load a table of return orders + */ +function loadReturnOrderTable(table, options={}) { + + // Ensure the table starts in a known state + $(table).bootstrapTable('destroy'); + + options.params = options.params || {}; + options.params['customer_detail'] = true; + + var filters = loadTableFilters('returnorder'); + + for (var key in options.params) { + filters[key] = options.params[key]; + } + + setupFilterList('returnorder', $(table), '#filter-list-returnorder', {download: true}); + + let display_mode = inventreeLoad('returnorder-table-display-mode', 'list'); + + let is_calendar = display_mode == 'calendar'; + + $(table).inventreeTable({ + url: '{% url "api-return-order-list" %}', + queryParams: filters, + name: 'returnorder', + sidePagination: 'server', + original: options.params, + showColumns: !is_calendar, + search: !is_calendar, + showCustomViewButton: false, + showCustomView: is_calendar, + disablePagination: is_calendar, + formatNoMatches: function() { + return '{% trans "No return orders found" %}'; + }, + onRefresh: function() { + loadReturnOrderTable(table, options); + }, + onLoadSuccess: function() { + // TODO + }, + columns: [ + { + title: '', + checkbox: true, + visible: true, + switchable: false, + }, + { + sortable: true, + field: 'reference', + title: '{% trans "Return Order" %}', + formatter: function(value, row) { + var html = renderLink(value, `/order/return-order/${row.pk}/`); + return html; + }, + }, + { + sortable: true, + sortName: 'customer__name', + field: 'customer_detail', + title: '{% trans "Customer" %}', + formatter: function(value, row) { + + if (!row.customer_detail) { + return '{% trans "Invalid Customer" %}'; + } + + return imageHoverIcon(row.customer_detail.image) + renderLink(row.customer_detail.name, `/company/${row.customer}/sales-orders/`); + } + }, + { + sortable: true, + field: 'customer_reference', + title: '{% trans "Customer Reference" %}', + }, + { + sortable: false, + field: 'description', + title: '{% trans "Description" %}', + }, + { + sortable: true, + field: 'status', + title: '{% trans "Status" %}', + formatter: function(value, row) { + return 'todo'; + return salesOrderStatusDisplay(row.status); + } + }, + { + sortable: true, + field: 'creation_date', + title: '{% trans "Creation Date" %}', + formatter: function(value) { + return renderDate(value); + } + }, + ] + }); +} diff --git a/InvenTree/templates/navbar.html b/InvenTree/templates/navbar.html index 620aaf3eff..cd660fa893 100644 --- a/InvenTree/templates/navbar.html +++ b/InvenTree/templates/navbar.html @@ -47,18 +47,23 @@ {% endif %} - {% if roles.sales_order.view %} + {% if roles.sales_order.view or roles.returns.view %} {% endif %}