2
0
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:
Matthias Mair
2021-12-04 17:52:58 +01:00
committed by GitHub
82 changed files with 23406 additions and 16264 deletions

View File

@ -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');

View File

@ -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;

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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: {