mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-18 13:05:42 +00:00
Merge branch 'inventree:master' into matmair/issue2279
This commit is contained in:
@ -34,7 +34,12 @@ function buildFormFields() {
|
||||
reference: {
|
||||
prefix: global_settings.BUILDORDER_REFERENCE_PREFIX,
|
||||
},
|
||||
part: {},
|
||||
part: {
|
||||
filters: {
|
||||
assembly: true,
|
||||
virtual: false,
|
||||
}
|
||||
},
|
||||
title: {},
|
||||
quantity: {},
|
||||
parent: {
|
||||
@ -1226,7 +1231,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
||||
*
|
||||
* options:
|
||||
* - output: ID / PK of the associated build output (or null for untracked items)
|
||||
* - source_location: ID / PK of the top-level StockLocation to take parts from (or null)
|
||||
* - source_location: ID / PK of the top-level StockLocation to source stock from (or null)
|
||||
*/
|
||||
function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
|
||||
@ -1339,7 +1344,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
|
||||
var html = ``;
|
||||
|
||||
// Render a "take from" input
|
||||
// Render a "source location" input
|
||||
html += constructField(
|
||||
'take_from',
|
||||
{
|
||||
@ -1397,6 +1402,13 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
options,
|
||||
);
|
||||
|
||||
// Add callback to "clear" button for take_from field
|
||||
addClearCallback(
|
||||
'take_from',
|
||||
take_from_field,
|
||||
options,
|
||||
);
|
||||
|
||||
// Initialize stock item fields
|
||||
bom_items.forEach(function(bom_item) {
|
||||
initializeRelatedField(
|
||||
@ -1406,6 +1418,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
filters: {
|
||||
bom_item: bom_item.pk,
|
||||
in_stock: true,
|
||||
available: true,
|
||||
part_detail: true,
|
||||
location_detail: true,
|
||||
},
|
||||
@ -1456,14 +1469,7 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
);
|
||||
});
|
||||
|
||||
// Add callback to "clear" button for take_from field
|
||||
addClearCallback(
|
||||
'take_from',
|
||||
take_from_field,
|
||||
options,
|
||||
);
|
||||
|
||||
// Add button callbacks
|
||||
// Add remove-row button callbacks
|
||||
$(options.modal).find('.button-row-remove').click(function() {
|
||||
var pk = $(this).attr('pk');
|
||||
|
||||
|
@ -730,6 +730,9 @@ function submitFormData(fields, options) {
|
||||
data = options.processBeforeUpload(data);
|
||||
}
|
||||
|
||||
// Show the progress spinner
|
||||
$(options.modal).find('#modal-progress-spinner').show();
|
||||
|
||||
// Submit data
|
||||
upload_func(
|
||||
options.url,
|
||||
@ -737,10 +740,13 @@ function submitFormData(fields, options) {
|
||||
{
|
||||
method: options.method,
|
||||
success: function(response) {
|
||||
$(options.modal).find('#modal-progress-spinner').hide();
|
||||
handleFormSuccess(response, options);
|
||||
},
|
||||
error: function(xhr) {
|
||||
|
||||
$(options.modal).find('#modal-progress-spinner').hide();
|
||||
|
||||
switch (xhr.status) {
|
||||
case 400:
|
||||
handleFormErrors(xhr.responseJSON, fields, options);
|
||||
@ -1713,6 +1719,9 @@ function renderModelData(name, model, data, parameters, options) {
|
||||
case 'salesorder':
|
||||
renderer = renderSalesOrder;
|
||||
break;
|
||||
case 'salesordershipment':
|
||||
renderer = renderSalesOrderShipment;
|
||||
break;
|
||||
case 'manufacturerpart':
|
||||
renderer = renderManufacturerPart;
|
||||
break;
|
||||
|
@ -72,6 +72,7 @@ function createNewModal(options={}) {
|
||||
<!-- Extra buttons can be inserted here -->
|
||||
</div>
|
||||
<span class='flex-item' style='flex-grow: 1;'></span>
|
||||
<h4><span id='modal-progress-spinner' class='fas fa-circle-notch fa-spin' style='display: none;'></span></h4>
|
||||
<button type='button' class='btn btn-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% trans "Cancel" %}</button>
|
||||
<button type='button' class='btn btn-primary' id='modal-form-submit'>{% trans "Submit" %}</button>
|
||||
</div>
|
||||
|
@ -241,6 +241,23 @@ function renderSalesOrder(name, data, parameters, options) {
|
||||
}
|
||||
|
||||
|
||||
// Renderer for "SalesOrderShipment" model
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function renderSalesOrderShipment(name, data, parameters, options) {
|
||||
|
||||
var so_prefix = global_settings.SALESORDER_REFERENCE_PREFIX;
|
||||
|
||||
var html = `
|
||||
<span>${so_prefix}${data.order_detail.reference} - {% trans "Shipment" %} ${data.reference}</span>
|
||||
<span class='float-right'>
|
||||
<small>{% trans "Shipment ID" %}: ${data.pk}</small>
|
||||
</span>
|
||||
`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
// Renderer for "PartCategory" model
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function renderPartCategory(name, data, parameters, options) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,7 @@
|
||||
loadParametricPartTable,
|
||||
loadPartCategoryTable,
|
||||
loadPartParameterTable,
|
||||
loadPartPurchaseOrderTable,
|
||||
loadPartTable,
|
||||
loadPartTestTemplateTable,
|
||||
loadPartVariantTable,
|
||||
@ -712,6 +713,180 @@ function loadPartParameterTable(table, url, options) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct a table showing a list of purchase orders for a given part.
|
||||
*
|
||||
* This requests API data from the PurchaseOrderLineItem endpoint
|
||||
*/
|
||||
function loadPartPurchaseOrderTable(table, part_id, options={}) {
|
||||
|
||||
options.params = options.params || {};
|
||||
|
||||
// Construct API filterset
|
||||
options.params.base_part = part_id;
|
||||
options.params.part_detail = true;
|
||||
options.params.order_detail = true;
|
||||
|
||||
var filters = loadTableFilters('partpurchaseorders');
|
||||
|
||||
for (var key in options.params) {
|
||||
filters[key] = options.params[key];
|
||||
}
|
||||
|
||||
setupFilterList('purchaseorderlineitem', $(table), '#filter-list-partpurchaseorders');
|
||||
|
||||
$(table).inventreeTable({
|
||||
url: '{% url "api-po-line-list" %}',
|
||||
queryParams: filters,
|
||||
name: 'partpurchaseorders',
|
||||
original: options.params,
|
||||
showColumns: true,
|
||||
uniqueId: 'pk',
|
||||
formatNoMatches: function() {
|
||||
return '{% trans "No purchase orders found" %}';
|
||||
},
|
||||
onPostBody: function() {
|
||||
$(table).find('.button-line-receive').click(function() {
|
||||
var pk = $(this).attr('pk');
|
||||
|
||||
var line_item = $(table).bootstrapTable('getRowByUniqueId', pk);
|
||||
|
||||
if (!line_item) {
|
||||
console.log('WARNING: getRowByUniqueId returned null');
|
||||
return;
|
||||
}
|
||||
|
||||
receivePurchaseOrderItems(
|
||||
line_item.order,
|
||||
[
|
||||
line_item,
|
||||
],
|
||||
{
|
||||
success: function() {
|
||||
$(table).bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'order',
|
||||
title: '{% trans "Purchase Order" %}',
|
||||
switchable: false,
|
||||
formatter: function(value, row) {
|
||||
var order = row.order_detail;
|
||||
|
||||
if (!order) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
var ref = global_settings.PURCHASEORDER_REFERENCE_PREFIX + order.reference;
|
||||
|
||||
var html = renderLink(ref, `/order/purchase-order/${order.pk}/`);
|
||||
|
||||
html += purchaseOrderStatusDisplay(
|
||||
order.status,
|
||||
{
|
||||
classes: 'float-right',
|
||||
}
|
||||
);
|
||||
|
||||
return html;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'supplier',
|
||||
title: '{% trans "Supplier" %}',
|
||||
switchable: true,
|
||||
formatter: function(value, row) {
|
||||
|
||||
if (row.supplier_part_detail && row.supplier_part_detail.supplier_detail) {
|
||||
var supp = row.supplier_part_detail.supplier_detail;
|
||||
var html = imageHoverIcon(supp.thumbnail || supp.image);
|
||||
|
||||
html += ' ' + renderLink(supp.name, `/company/${supp.pk}/`);
|
||||
|
||||
return html;
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'sku',
|
||||
title: '{% trans "SKU" %}',
|
||||
switchable: true,
|
||||
formatter: function(value, row) {
|
||||
if (row.supplier_part_detail) {
|
||||
var supp = row.supplier_part_detail;
|
||||
|
||||
return renderLink(supp.SKU, `/supplier-part/${supp.pk}/`);
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'mpn',
|
||||
title: '{% trans "MPN" %}',
|
||||
switchable: true,
|
||||
formatter: function(value, row) {
|
||||
if (row.supplier_part_detail && row.supplier_part_detail.manufacturer_part_detail) {
|
||||
var manu = row.supplier_part_detail.manufacturer_part_detail;
|
||||
return renderLink(manu.MPN, `/manufacturer-part/${manu.pk}/`);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'quantity',
|
||||
title: '{% trans "Quantity" %}',
|
||||
},
|
||||
{
|
||||
field: 'received',
|
||||
title: '{% trans "Received" %}',
|
||||
switchable: true,
|
||||
},
|
||||
{
|
||||
field: 'purchase_price',
|
||||
title: '{% trans "Price" %}',
|
||||
switchable: true,
|
||||
formatter: function(value, row) {
|
||||
var formatter = new Intl.NumberFormat(
|
||||
'en-US',
|
||||
{
|
||||
style: 'currency',
|
||||
currency: row.purchase_price_currency,
|
||||
}
|
||||
);
|
||||
|
||||
return formatter.format(row.purchase_price);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'actions',
|
||||
title: '',
|
||||
formatter: function(value, row) {
|
||||
|
||||
if (row.received >= row.quantity) {
|
||||
// Already recevied
|
||||
return `<span class='badge bg-success rounded-pill'>{% trans "Received" %}</span>`;
|
||||
} else {
|
||||
var html = `<div class='btn-group' role='group'>`;
|
||||
var pk = row.pk;
|
||||
|
||||
html += makeIconButton('fa-sign-in-alt', 'button-line-receive', pk, '{% trans "Receive line item" %}');
|
||||
|
||||
html += `</div>`;
|
||||
return html;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function loadRelatedPartsTable(table, part_id, options={}) {
|
||||
/*
|
||||
* Load table of "related" parts
|
||||
|
@ -95,6 +95,9 @@ function serializeStockItem(pk, options={}) {
|
||||
});
|
||||
}
|
||||
|
||||
options.confirm = true;
|
||||
options.confirmMessage = '{% trans "Confirm Stock Serialization" %}';
|
||||
|
||||
constructForm(url, options);
|
||||
}
|
||||
|
||||
@ -1275,7 +1278,14 @@ function loadStockTable(table, options) {
|
||||
}
|
||||
|
||||
if (row.allocated) {
|
||||
html += makeIconBadge('fa-bookmark', '{% trans "Stock item has been allocated" %}');
|
||||
|
||||
if (row.serial != null && row.quantity == 1) {
|
||||
html += makeIconBadge('fa-bookmark icon-yellow', '{% trans "Serialized stock item has been allocated" %}');
|
||||
} else if (row.allocated >= row.quantity) {
|
||||
html += makeIconBadge('fa-bookmark icon-yellow', '{% trans "Stock item has been fully allocated" %}');
|
||||
} else {
|
||||
html += makeIconBadge('fa-bookmark', '{% trans "Stock item has been partially allocated" %}');
|
||||
}
|
||||
}
|
||||
|
||||
if (row.belongs_to) {
|
||||
|
@ -173,6 +173,11 @@ function getAvailableTableFilters(tableKey) {
|
||||
title: '{% trans "Is allocated" %}',
|
||||
description: '{% trans "Item has been allocated" %}',
|
||||
},
|
||||
available: {
|
||||
type: 'bool',
|
||||
title: '{% trans "Available" %}',
|
||||
description: '{% trans "Stock is available for use" %}',
|
||||
},
|
||||
cascade: {
|
||||
type: 'bool',
|
||||
title: '{% trans "Include sublocations" %}',
|
||||
@ -293,6 +298,10 @@ function getAvailableTableFilters(tableKey) {
|
||||
type: 'bool',
|
||||
title: '{% trans "Overdue" %}',
|
||||
},
|
||||
assigned_to_me: {
|
||||
type: 'bool',
|
||||
title: '{% trans "Assigned to me" %}',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -305,6 +314,7 @@ function getAvailableTableFilters(tableKey) {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Filters for the PurchaseOrder table
|
||||
if (tableKey == 'purchaseorder') {
|
||||
|
||||
@ -321,6 +331,10 @@ function getAvailableTableFilters(tableKey) {
|
||||
type: 'bool',
|
||||
title: '{% trans "Overdue" %}',
|
||||
},
|
||||
assigned_to_me: {
|
||||
type: 'bool',
|
||||
title: '{% trans "Assigned to me" %}',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -341,6 +355,15 @@ function getAvailableTableFilters(tableKey) {
|
||||
};
|
||||
}
|
||||
|
||||
if (tableKey == 'salesorderlineitem') {
|
||||
return {
|
||||
completed: {
|
||||
type: 'bool',
|
||||
title: '{% trans "Completed" %}',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (tableKey == 'supplier-part') {
|
||||
return {
|
||||
active: {
|
||||
|
Reference in New Issue
Block a user