{% extends "order/sales_order_base.html" %} {% load inventree_extras %} {% load status_codes %} {% load i18n %} {% load static %} {% block details %} {% include "order/so_tabs.html" with tab='details' %}

{% trans "Sales Order Items" %}

{% endblock %} {% block js_ready %} {{ block.super }} function reloadTable() { $("#so-lines-table").bootstrapTable("refresh"); } $("#new-so-line").click(function() { launchModalForm("{% url 'so-line-item-create' %}", { success: reloadTable, data: { order: {{ order.id }}, }, secondary: [ ] }); }); {% if order.status == SalesOrderStatus.PENDING %} function showAllocationSubTable(index, row, element) { // Construct a table showing stock items which have been allocated against this line item var html = `
`; element.html(html); var lineItem = row; var table = $(`#allocation-table-${row.pk}`); table.bootstrapTable({ data: row.allocations, showHeader: false, columns: [ { width: '50%', field: 'allocated', title: 'Quantity', formatter: function(value, row, index, field) { var text = ''; if (row.serial != null && row.quantity == 1) { text = `{% trans "Serial Number" %}: ${row.serial}`; } else { text = `{% trans "Quantity" %}: ${row.quantity}`; } return renderLink(text, `/stock/item/${row.item}/`); }, }, { field: 'location_id', title: 'Location', formatter: function(value, row, index, field) { return renderLink(row.location_path, `/stock/location/${row.location_id}/`); }, }, { field: 'buttons', title: 'Actions', formatter: function(value, row, index, field) { var html = "
"; var pk = row.pk; {% if order.status == SalesOrderStatus.PENDING %} html += makeIconButton('fa-edit', 'button-allocation-edit', pk, '{% trans "Edit stock allocation" %}'); html += makeIconButton('fa-trash-alt', 'button-allocation-delete', pk, '{% trans "Delete stock allocation" %}'); {% endif %} html += "
"; return html; }, }, ], }); table.find(".button-allocation-edit").click(function() { var pk = $(this).attr('pk'); launchModalForm(`/order/sales-order/allocation/${pk}/edit/`, { success: reloadTable, }); }); table.find(".button-allocation-delete").click(function() { var pk = $(this).attr('pk'); launchModalForm(`/order/sales-order/allocation/${pk}/delete/`, { success: reloadTable, }); }); } {% endif %} function showFulfilledSubTable(index, row, element) { // Construct a table showing stock items which have been fulfilled against this line item var id = `fulfilled-table-${row.pk}`; var html = `
`; element.html(html); var lineItem = row; $(`#${id}`).bootstrapTable({ url: "{% url 'api-stock-list' %}", queryParams: { part: row.part, sales_order: {{ order.id }}, }, showHeader: false, columns: [ { field: 'pk', visible: false, }, { field: 'stock', formatter: function(value, row) { var text = ''; if (row.serial && row.quantity == 1) { text = `{% trans "Serial Number" %}: ${row.serial}`; } else { text = `{% trans "Quantity" %}: ${row.quantity}`; } return renderLink(text, `/stock/item/${row.pk}/`); }, } ], }); } $("#so-lines-table").inventreeTable({ formatNoMatches: function() { return "No matching line items"; }, queryParams: { order: {{ order.id }}, part_detail: true, allocations: true, }, uniqueId: 'pk', url: "{% url 'api-so-line-list' %}", onPostBody: setupCallbacks, {% if order.status == SalesOrderStatus.PENDING or order.status == SalesOrderStatus.SHIPPED %} detailViewByClick: true, detailView: true, detailFilter: function(index, row) { {% if order.status == SalesOrderStatus.PENDING %} return row.allocated > 0; {% else %} return row.fulfilled > 0; {% endif %} }, {% if order.status == SalesOrderStatus.PENDING %} detailFormatter: showAllocationSubTable, {% else %} detailFormatter: showFulfilledSubTable, {% endif %} {% endif %} columns: [ { field: 'pk', title: 'ID', visible: false, }, { sortable: true, field: 'part', title: 'Part', formatter: function(value, row, index, field) { if (row.part) { return imageHoverIcon(row.part_detail.thumbnail) + renderLink(row.part_detail.full_name, `/part/${value}/`); } else { return '-'; } } }, { sortable: true, field: 'reference', title: 'Reference' }, { sortable: true, field: 'quantity', title: 'Quantity', }, { sortable: true, field: 'allocated', {% if order.status == SalesOrderStatus.PENDING %} title: '{% trans "Allocated" %}', {% else %} title: '{% trans "Fulfilled" %}', {% endif %} formatter: function(value, row, index, field) { {% if order.status == SalesOrderStatus.PENDING %} var quantity = row.allocated; {% else %} var quantity = row.fulfilled; {% endif %} return makeProgressBar(quantity, row.quantity, { id: `order-line-progress-${row.pk}`, }); }, sorter: function(valA, valB, rowA, rowB) { {% if order.status == SalesOrderStatus.PENDING %} var A = rowA.allocated; var B = rowB.allocated; {% else %} var A = rowA.fulfilled; var B = rowB.fulfilled; {% endif %} if (A == 0 && B == 0) { return (rowA.quantity > rowB.quantity) ? 1 : -1; } var progressA = parseFloat(A) / rowA.quantity; var progressB = parseFloat(B) / rowB.quantity; return (progressA < progressB) ? 1 : -1; } }, { field: 'notes', title: 'Notes', }, {% if order.status == SalesOrderStatus.PENDING %} { field: 'buttons', formatter: function(value, row, index, field) { var html = `
`; var pk = row.pk; if (row.part) { var part = row.part_detail; if (part.purchaseable) { html += makeIconButton('fa-shopping-cart', 'button-buy', row.part, '{% trans "Buy parts" %}'); } if (part.assembly) { html += makeIconButton('fa-tools', 'button-build', row.part, '{% trans "Build parts" %}'); } html += makeIconButton('fa-plus', 'button-add', pk, '{% trans "Allocate parts" %}'); } html += makeIconButton('fa-edit', 'button-edit', pk, '{% trans "Edit line item" %}'); html += makeIconButton('fa-trash-alt', 'button-delete', pk, '{% trans "Delete line item " %}'); html += `
`; return html; } }, {% endif %} ], }); function setupCallbacks() { var table = $("#so-lines-table"); // Set up callbacks for the row buttons table.find(".button-edit").click(function() { var pk = $(this).attr('pk'); launchModalForm(`/order/sales-order/line/${pk}/edit/`, { success: reloadTable, }); }); table.find(".button-delete").click(function() { var pk = $(this).attr('pk'); launchModalForm(`/order/sales-order/line/${pk}/delete/`, { reload: true, }); }); table.find(".button-add").click(function() { var pk = $(this).attr('pk'); launchModalForm(`/order/sales-order/allocation/new/`, { success: reloadTable, data: { line: pk, }, }); }); table.find(".button-build").click(function() { var pk = $(this).attr('pk'); // Extract the row data from the table! var idx = $(this).closest('tr').attr('data-index'); var row = table.bootstrapTable('getData')[idx]; var quantity = 1; if (row.allocated < row.quantity) { quantity = row.quantity - row.allocated; } launchModalForm(`/build/new/`, { follow: true, data: { part: pk, sales_order: {{ order.id }}, quantity: quantity, }, }); }); table.find(".button-buy").click(function() { var pk = $(this).attr('pk'); launchModalForm("{% url 'order-parts' %}", { data: { parts: [pk], }, }); }); } {% endblock %}