mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	ad UI components
This commit is contained in:
		| @@ -35,6 +35,29 @@ | |||||||
|         <table class='table table-striped table-condensed' id='so-lines-table' data-toolbar='#order-toolbar-buttons'> |         <table class='table table-striped table-condensed' id='so-lines-table' data-toolbar='#order-toolbar-buttons'> | ||||||
|         </table> |         </table> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|  |     <div class='panel-heading'> | ||||||
|  |         <div class='d-flex flex-wrap'> | ||||||
|  |             <h4>{% trans "Sales Order Lines" %}</h4> | ||||||
|  |             {% include "spacer.html" %} | ||||||
|  |             <div class='btn-group' role='group'> | ||||||
|  |                 {% if roles.sales_order.change and order.is_pending %} | ||||||
|  |                 <button type='button' class='btn btn-success' id='new-so-additional-line'> | ||||||
|  |                     <span class='fas fa-plus-circle'></span> {% trans "Add Order Line" %} | ||||||
|  |                 </button> | ||||||
|  |                 {% endif %} | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |     <div class='panel-content'> | ||||||
|  |         <div id='order-additional-toolbar-buttons' class='btn-group' style='float: right;'> | ||||||
|  |             <div class='btn-group'> | ||||||
|  |                 {% include "filter_list.html" with id="sales-order-additional-lines" %} | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |         <table class='table table-striped table-condensed' id='so-additional-lines-table' data-toolbar='#order-additional-toolbar-buttons'> | ||||||
|  |         </table> | ||||||
|  |     </div> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| {% if order.is_pending %} | {% if order.is_pending %} | ||||||
| @@ -245,6 +268,30 @@ | |||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  |     $("#new-so-additional-line").click(function() { | ||||||
|  |  | ||||||
|  |         var fields = soAdditionalLineItemFields({ | ||||||
|  |             order: {{ order.pk }}, | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         constructForm('{% url "api-so-additional-line-list" %}', { | ||||||
|  |             fields: fields, | ||||||
|  |             method: 'POST', | ||||||
|  |             title: '{% trans "Add Order Line" %}', | ||||||
|  |             onSuccess: function() { | ||||||
|  |                 $("#so-additional-lines-table").bootstrapTable("refresh"); | ||||||
|  |             }, | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     loadSalesOrderAdditionalLineItemTable( | ||||||
|  |         '#so-additional-lines-table', | ||||||
|  |         { | ||||||
|  |             order: {{ order.pk }}, | ||||||
|  |             status: {{ order.status }}, | ||||||
|  |         } | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     enableSidebar('salesorder'); |     enableSidebar('salesorder'); | ||||||
|      |      | ||||||
| {% endblock %} | {% endblock %} | ||||||
| @@ -30,6 +30,7 @@ | |||||||
|     loadSalesOrderAllocationTable, |     loadSalesOrderAllocationTable, | ||||||
|     loadSalesOrderLineItemTable, |     loadSalesOrderLineItemTable, | ||||||
|     loadSalesOrderShipmentTable, |     loadSalesOrderShipmentTable, | ||||||
|  |     loadSalesOrderAdditionalLineItemTable | ||||||
|     loadSalesOrderTable, |     loadSalesOrderTable, | ||||||
|     newPurchaseOrderFromOrderWizard, |     newPurchaseOrderFromOrderWizard, | ||||||
|     newSupplierPartFromOrderWizard, |     newSupplierPartFromOrderWizard, | ||||||
| @@ -305,6 +306,28 @@ function soLineItemFields(options={}) { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Construct a set of fields for the SalesOrderAdditionalLineItem form */ | ||||||
|  | function SOAdditionalLineItemFields(options={}) { | ||||||
|  |  | ||||||
|  |     var fields = { | ||||||
|  |         order: { | ||||||
|  |             hidden: true, | ||||||
|  |         }, | ||||||
|  |         quantity: {}, | ||||||
|  |         reference: {}, | ||||||
|  |         sale_price: {}, | ||||||
|  |         sale_price_currency: {}, | ||||||
|  |         notes: {}, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     if (options.order) { | ||||||
|  |         fields.order.value = options.order; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return fields; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Construct a set of fields for the PurchaseOrderLineItem form */ | /* Construct a set of fields for the PurchaseOrderLineItem form */ | ||||||
| function poLineItemFields(options={}) { | function poLineItemFields(options={}) { | ||||||
|  |  | ||||||
| @@ -2773,3 +2796,241 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|         columns: columns, |         columns: columns, | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Load a table displaying line items for a particular SalesOrder | ||||||
|  |  *  | ||||||
|  |  * @param {String} table : HTML ID tag e.g. '#table' | ||||||
|  |  * @param {Object} options : object which contains: | ||||||
|  |  *      - order {integer} : pk of the SalesOrder | ||||||
|  |  *      - status: {integer} : status code for the order | ||||||
|  |  */ | ||||||
|  |  function loadSalesOrderAdditionalLineItemTable(table, options={}) { | ||||||
|  |  | ||||||
|  |     options.table = table; | ||||||
|  |  | ||||||
|  |     options.params = options.params || {}; | ||||||
|  |  | ||||||
|  |     if (!options.order) { | ||||||
|  |         console.log('ERROR: function called without order ID'); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!options.status) { | ||||||
|  |         console.log('ERROR: function called without order status'); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     options.params.order = options.order; | ||||||
|  |     options.params.part_detail = true; | ||||||
|  |     options.params.allocations = true; | ||||||
|  |      | ||||||
|  |     var filters = loadTableFilters('salesorderadditionallineitem'); | ||||||
|  |  | ||||||
|  |     for (var key in options.params) { | ||||||
|  |         filters[key] = options.params[key]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     options.url = options.url || '{% url "api-so-additional-line-list" %}'; | ||||||
|  |  | ||||||
|  |     var filter_target = options.filter_target || '#filter-list-sales-order-additional-lines'; | ||||||
|  |  | ||||||
|  |     setupFilterList('salesorderadditionallineitem', $(table), filter_target); | ||||||
|  |  | ||||||
|  |     // Is the order pending? | ||||||
|  |     var pending = options.status == {{ SalesOrderStatus.PENDING }}; | ||||||
|  |  | ||||||
|  |     // Has the order shipped? | ||||||
|  |     var shipped = options.status == {{ SalesOrderStatus.SHIPPED }}; | ||||||
|  |  | ||||||
|  |     // Show detail view if the PurchaseOrder is PENDING or SHIPPED | ||||||
|  |     var show_detail = pending || shipped; | ||||||
|  |  | ||||||
|  |     // Table columns to display | ||||||
|  |     var columns = [ | ||||||
|  |         /* | ||||||
|  |         { | ||||||
|  |             checkbox: true, | ||||||
|  |             visible: true, | ||||||
|  |             switchable: false, | ||||||
|  |         }, | ||||||
|  |         */ | ||||||
|  |         { | ||||||
|  |             sortable: true, | ||||||
|  |             field: 'reference', | ||||||
|  |             title: '{% trans "Reference" %}', | ||||||
|  |             switchable: true, | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             sortable: true, | ||||||
|  |             field: 'quantity', | ||||||
|  |             title: '{% trans "Quantity" %}', | ||||||
|  |             footerFormatter: function(data) { | ||||||
|  |                 return data.map(function(row) { | ||||||
|  |                     return +row['quantity']; | ||||||
|  |                 }).reduce(function(sum, i) { | ||||||
|  |                     return sum + i; | ||||||
|  |                 }, 0); | ||||||
|  |             }, | ||||||
|  |             switchable: false, | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             sortable: true, | ||||||
|  |             field: 'sale_price', | ||||||
|  |             title: '{% trans "Unit Price" %}', | ||||||
|  |             formatter: function(value, row) { | ||||||
|  |                 var formatter = new Intl.NumberFormat( | ||||||
|  |                     'en-US', | ||||||
|  |                     { | ||||||
|  |                         style: 'currency', | ||||||
|  |                         currency: row.sale_price_currency | ||||||
|  |                     } | ||||||
|  |                 ); | ||||||
|  |  | ||||||
|  |                 return formatter.format(row.sale_price); | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             field: 'total_price', | ||||||
|  |             sortable: true, | ||||||
|  |             title: '{% trans "Total Price" %}', | ||||||
|  |             formatter: function(value, row) { | ||||||
|  |                 var formatter = new Intl.NumberFormat( | ||||||
|  |                     'en-US', | ||||||
|  |                     { | ||||||
|  |                         style: 'currency', | ||||||
|  |                         currency: row.sale_price_currency | ||||||
|  |                     } | ||||||
|  |                 ); | ||||||
|  |  | ||||||
|  |                 return formatter.format(row.sale_price * row.quantity); | ||||||
|  |             }, | ||||||
|  |             footerFormatter: function(data) { | ||||||
|  |                 var total = data.map(function(row) { | ||||||
|  |                     return +row['sale_price'] * row['quantity']; | ||||||
|  |                 }).reduce(function(sum, i) { | ||||||
|  |                     return sum + i; | ||||||
|  |                 }, 0); | ||||||
|  |  | ||||||
|  |                 var currency = (data.slice(-1)[0] && data.slice(-1)[0].sale_price_currency) || 'USD'; | ||||||
|  |                  | ||||||
|  |                 var formatter = new Intl.NumberFormat( | ||||||
|  |                     'en-US', | ||||||
|  |                     { | ||||||
|  |                         style: 'currency',  | ||||||
|  |                         currency: currency | ||||||
|  |                     } | ||||||
|  |                 ); | ||||||
|  |                  | ||||||
|  |                 return formatter.format(total); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     columns.push({ | ||||||
|  |         field: 'notes', | ||||||
|  |         title: '{% trans "Notes" %}', | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     if (pending) { | ||||||
|  |         columns.push({ | ||||||
|  |             field: 'buttons', | ||||||
|  |             switchable: false, | ||||||
|  |             formatter: function(value, row, index, field) { | ||||||
|  |  | ||||||
|  |                 var html = `<div class='btn-group float-right' role='group'>`; | ||||||
|  |  | ||||||
|  |                 var pk = row.pk; | ||||||
|  |  | ||||||
|  |                 html += makeIconButton('fa-clone', 'button-duplicate', pk, '{% trans "Duplicate line item" %}'); | ||||||
|  |                 html += makeIconButton('fa-edit icon-blue', 'button-edit', pk, '{% trans "Edit line item" %}'); | ||||||
|  |  | ||||||
|  |                 var title = '{% trans "Delete line item" %}'; | ||||||
|  |  | ||||||
|  |                 // Prevent deletion of the line item if items have been allocated or shipped! | ||||||
|  |                 html += makeIconButton('fa-trash-alt icon-red', 'button-delete', pk, title, ); | ||||||
|  |  | ||||||
|  |                 html += `</div>`; | ||||||
|  |  | ||||||
|  |                 return html; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function reloadTable() { | ||||||
|  |         $(table).bootstrapTable('refresh'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Configure callback functions once the table is loaded | ||||||
|  |     function setupCallbacks() { | ||||||
|  |  | ||||||
|  |         // Callback for duplicating line items | ||||||
|  |         $(table).find('.button-duplicate').click(function() { | ||||||
|  |             var pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|  |             inventreeGet(`/api/order/so-additional-line/${pk}/`, {}, { | ||||||
|  |                 success: function(data) { | ||||||
|  |  | ||||||
|  |                     var fields = soLineItemFields(); | ||||||
|  |  | ||||||
|  |                     constructForm('{% url "api-so-additional-line-list" %}', { | ||||||
|  |                         method: 'POST', | ||||||
|  |                         fields: fields, | ||||||
|  |                         data: data, | ||||||
|  |                         title: '{% trans "Duplicate Line Item" %}', | ||||||
|  |                         onSuccess: function(response) { | ||||||
|  |                             $(table).bootstrapTable('refresh'); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // Callback for editing line items | ||||||
|  |         $(table).find('.button-edit').click(function() { | ||||||
|  |             var pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|  |             constructForm(`/api/order/so-additional-line/${pk}/`, { | ||||||
|  |                 fields: { | ||||||
|  |                     quantity: {}, | ||||||
|  |                     reference: {}, | ||||||
|  |                     sale_price: {}, | ||||||
|  |                     sale_price_currency: {}, | ||||||
|  |                     target_date: {}, | ||||||
|  |                     notes: {}, | ||||||
|  |                 }, | ||||||
|  |                 title: '{% trans "Edit Line Item" %}', | ||||||
|  |                 onSuccess: reloadTable, | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // Callback for deleting line items | ||||||
|  |         $(table).find('.button-delete').click(function() { | ||||||
|  |             var pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|  |             constructForm(`/api/order/so-additional-line/${pk}/`, { | ||||||
|  |                 method: 'DELETE', | ||||||
|  |                 title: '{% trans "Delete Line Item" %}', | ||||||
|  |                 onSuccess: reloadTable, | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $(table).inventreeTable({ | ||||||
|  |         onPostBody: setupCallbacks, | ||||||
|  |         name: 'salesorderadditionallineitems', | ||||||
|  |         sidePagination: 'client', | ||||||
|  |         formatNoMatches: function() { | ||||||
|  |             return '{% trans "No matching line items" %}'; | ||||||
|  |         }, | ||||||
|  |         queryParams: filters, | ||||||
|  |         original: options.params, | ||||||
|  |         url: options.url, | ||||||
|  |         showFooter: true, | ||||||
|  |         uniqueId: 'pk', | ||||||
|  |         detailView: show_detail, | ||||||
|  |         detailViewByClick: false, | ||||||
|  |         columns: columns, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user