2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-11 15:34:15 +00:00

Merge remote-tracking branch 'inventree/master' into receive-via-api

This commit is contained in:
Oliver
2021-08-24 15:07:55 +10:00
11 changed files with 293 additions and 244 deletions

@ -105,7 +105,7 @@
{% if roles.purchase_order.add %}
<div id='po-button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-primary' type='button' id='company-order2' title='{% trans "Create new purchase order" %}'>
<button class='btn btn-success' type='button' id='company-order2' title='{% trans "Create new purchase order" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Purchase Order" %}</button>
<div class='filter-list' id='filter-list-purchaseorder'>
<!-- Empty div -->
@ -127,7 +127,7 @@
{% if roles.sales_order.add %}
<div id='so-button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-primary' type='button' id='new-sales-order' title='{% trans "Create new sales order" %}'>
<button class='btn btn-success' type='button' id='new-sales-order' title='{% trans "Create new sales order" %}'>
<div class='fas fa-plus-circle'></div> {% trans "New Sales Order" %}
</button>
<div class='filter-list' id='filter-list-salesorder'>

@ -160,7 +160,7 @@ src="{% static 'img/blank_image.png' %}"
<div class='panel-content'>
{% if roles.purchase_order.add %}
<div id='price-break-toolbar' class='btn-group'>
<button class='btn btn-primary' id='new-price-break' type='button'>
<button class='btn btn-success' id='new-price-break' type='button'>
<span class='fas fa-plus-circle'></span> {% trans "Add Price Break" %}
</button>
</div>

@ -19,7 +19,7 @@
<div class='panel-content'>
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
{% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %}
<button type='button' class='btn btn-primary' id='new-po-line'>
<button type='button' class='btn btn-success' id='new-po-line'>
<span class='fas fa-plus-circle'></span> {% trans "Add Line Item" %}
</button>
<a class='btn btn-primary' href='{% url "po-upload" order.id %}' role='button'>

@ -17,7 +17,7 @@
<div class='button-toolbar container-fluid' style='float: right;'>
<div class='btn-group'>
{% if roles.purchase_order.add %}
<button class='btn btn-primary' type='button' id='po-create' title='{% trans "Create new purchase order" %}'>
<button class='btn btn-success' type='button' id='po-create' title='{% trans "Create new purchase order" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Purchase Order" %}
</button>
{% endif %}

@ -17,7 +17,7 @@
<div class='button-toolbar container-fluid' style='float: right;'>
<div class='btn-group'>
{% if roles.sales_order.add %}
<button class='btn btn-primary' type='button' id='so-create' title='{% trans "Create new sales order" %}'>
<button class='btn btn-success' type='button' id='so-create' title='{% trans "Create new sales order" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Sales Order" %}
</button>
{% endif %}

@ -74,7 +74,7 @@
<div id='so-button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
{% if 0 %}
<button class='btn btn-primary' type='button' id='part-order2' title='{% trans "New sales order" %}'>{% trans "New Order" %}</button>
<button class='btn btn-success' type='button' id='part-order2' title='{% trans "New sales order" %}'>{% trans "New Order" %}</button>
{% endif %}
<div class='filter-list' id='filter-list-salesorder'>
<!-- An empty div in which the filter list will be constructed -->
@ -185,7 +185,7 @@
<div id='related-button-bar'>
<div class='button-toolbar container-fluid' style='float: left;'>
{% if roles.part.change %}
<button class='btn btn-primary' type='button' id='add-related-part' title='{% trans "Add Related" %}'>{% trans "Add Related" %}</button>
<button class='btn btn-success' type='button' id='add-related-part' title='{% trans "Add Related" %}'>{% trans "Add Related" %}</button>
<div class='filter-list' id='filter-list-related'>
<!-- An empty div in which the filter list will be constructed -->
</div>

@ -87,7 +87,7 @@
</li>
{% endif %}
{% endif %}
{% if roles.sales_order.view and enable_sell and enable_so %}
{% if part.salable and roles.sales_order.view and enable_sell and enable_so %}
<li class='list-group-item' title='{% trans "Sales Orders" %}'>
<a href='#' id='select-sales-orders' class='nav-toggle'>
<span class='menu-tab-icon fas fa-truck sidebar-icon'></span>

@ -211,7 +211,7 @@
</div>
<div class="col col-md-4">
<div id='internal-price-break-toolbar' class='btn-group'>
<button class='btn btn-primary' id='new-internal-price-break' type='button'>
<button class='btn btn-success' id='new-internal-price-break' type='button'>
<span class='fas fa-plus-circle'></span> {% trans "Add Internal Price Break" %}
</button>
</div>
@ -267,7 +267,7 @@
</div>
<div class="col col-md-4">
<div id='price-break-toolbar' class='btn-group'>
<button class='btn btn-primary' id='new-price-break' type='button'>
<button class='btn btn-success' id='new-price-break' type='button'>
<span class='fas fa-plus-circle'></span> {% trans "Add Price Break" %}
</button>
</div>

@ -111,9 +111,17 @@ function inventreeDocReady() {
},
create: function () {
$(this).data('ui-autocomplete')._renderItem = function (ul, item) {
return $('<li>')
.append('<span>' + imageHoverIcon(item.thumbnail) + item.label + '</span>')
.appendTo(ul);
var html = `<a href='/part/${item.id}/'><span>`;
html += `<img class='hover-img-thumb' src='`;
html += item.thumbnail || `/static/img/blank_image.png`;
html += `'> `;
html += item.label;
html += '</span></a>';
return $('<li>').append(html).appendTo(ul);
};
},
select: function( event, ui ) {

@ -74,34 +74,34 @@ function partFields(options={}) {
icon: 'fa-boxes',
},
component: {
value: global_settings.PART_COMPONENT,
default: global_settings.PART_COMPONENT,
group: 'attributes',
},
assembly: {
value: global_settings.PART_ASSEMBLY,
default: global_settings.PART_ASSEMBLY,
group: 'attributes',
},
is_template: {
value: global_settings.PART_TEMPLATE,
default: global_settings.PART_TEMPLATE,
group: 'attributes',
},
trackable: {
value: global_settings.PART_TRACKABLE,
default: global_settings.PART_TRACKABLE,
group: 'attributes',
},
purchaseable: {
value: global_settings.PART_PURCHASEABLE,
default: global_settings.PART_PURCHASEABLE,
group: 'attributes',
onEdit: function(value, name, field, options) {
setFormGroupVisibility('supplier', value, options);
}
},
salable: {
value: global_settings.PART_SALABLE,
default: global_settings.PART_SALABLE,
group: 'attributes',
},
virtual: {
value: global_settings.PART_VIRTUAL,
default: global_settings.PART_VIRTUAL,
group: 'attributes',
},
};

@ -706,181 +706,7 @@ function loadStockTable(table, options) {
// Ref: https://github.com/wenzhixin/bootstrap-table/issues/3250
grouping = false;
table.inventreeTable({
method: 'get',
formatNoMatches: function() {
return '{% trans "No stock items matching query" %}';
},
url: options.url || "{% url 'api-stock-list' %}",
queryParams: filters,
sidePagination: 'server',
name: 'stock',
original: original,
showColumns: true,
{% if False %}
groupByField: options.groupByField || 'part',
groupBy: grouping,
groupByFormatter: function(field, id, data) {
var row = data[0];
if (field == 'part_detail.full_name') {
var html = imageHoverIcon(row.part_detail.thumbnail);
html += row.part_detail.full_name;
html += ` <i>(${data.length} {% trans "items" %})</i>`;
html += makePartIcons(row.part_detail);
return html;
}
else if (field == 'part_detail.IPN') {
var ipn = row.part_detail.IPN;
if (ipn) {
return ipn;
} else {
return '-';
}
}
else if (field == 'part_detail.description') {
return row.part_detail.description;
}
else if (field == 'packaging') {
var packaging = [];
data.forEach(function(item) {
var pkg = item.packaging;
if (!pkg) {
pkg = '-';
}
if (!packaging.includes(pkg)) {
packaging.push(pkg);
}
});
if (packaging.length > 1) {
return "...";
} else if (packaging.length == 1) {
return packaging[0];
} else {
return "-";
}
}
else if (field == 'quantity') {
var stock = 0;
var items = 0;
data.forEach(function(item) {
stock += parseFloat(item.quantity);
items += 1;
});
stock = +stock.toFixed(5);
return stock + " (" + items + " items)";
} else if (field == 'status') {
var statii = [];
data.forEach(function(item) {
var status = String(item.status);
if (!status || status == '') {
status = '-';
}
if (!statii.includes(status)) {
statii.push(status);
}
});
// Multiple status codes
if (statii.length > 1) {
return "...";
} else if (statii.length == 1) {
return stockStatusDisplay(statii[0]);
} else {
return "-";
}
} else if (field == 'batch') {
var batches = [];
data.forEach(function(item) {
var batch = item.batch;
if (!batch || batch == '') {
batch = '-';
}
if (!batches.includes(batch)) {
batches.push(batch);
}
});
if (batches.length > 1) {
return "" + batches.length + " {% trans 'batches' %}";
} else if (batches.length == 1) {
if (batches[0]) {
return batches[0];
} else {
return '-';
}
} else {
return '-';
}
} else if (field == 'location_detail.pathstring') {
/* Determine how many locations */
var locations = [];
data.forEach(function(item) {
var detail = locationDetail(item);
if (!locations.includes(detail)) {
locations.push(detail);
}
});
if (locations.length == 1) {
// Single location, easy!
return locations[0];
} else if (locations.length > 1) {
return "In " + locations.length + " {% trans 'locations' %}";
} else {
return "<i>{% trans 'Undefined location' %}</i>";
}
} else if (field == 'notes') {
var notes = [];
data.forEach(function(item) {
var note = item.notes;
if (!note || note == '') {
note = '-';
}
if (!notes.includes(note)) {
notes.push(note);
}
});
if (notes.length > 1) {
return '...';
} else if (notes.length == 1) {
return notes[0] || '-';
} else {
return '-';
}
}
else {
return '';
}
},
{% endif %}
columns: [
var columns = [
{
checkbox: true,
title: '{% trans "Select" %}',
@ -892,12 +718,13 @@ function loadStockTable(table, options) {
title: 'ID',
visible: false,
switchable: false,
},
{
}
];
col = {
field: 'part_detail.full_name',
title: '{% trans "Part" %}',
sortName: 'part__name',
sortable: true,
visible: params['part_detail'],
switchable: params['part_detail'],
formatter: function(value, row, index, field) {
@ -912,19 +739,28 @@ function loadStockTable(table, options) {
return html;
}
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
col = {
field: 'part_detail.IPN',
title: 'IPN',
sortName: 'part__IPN',
sortable: true,
visible: params['part_detail'],
switchable: params['part_detail'],
formatter: function(value, row, index, field) {
return row.part_detail.IPN;
},
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
columns.push({
field: 'part_detail.description',
title: '{% trans "Description" %}',
visible: params['part_detail'],
@ -932,11 +768,11 @@ function loadStockTable(table, options) {
formatter: function(value, row, index, field) {
return row.part_detail.description;
}
},
{
});
col = {
field: 'quantity',
title: '{% trans "Stock" %}',
sortable: true,
formatter: function(value, row, index, field) {
var val = parseFloat(value);
@ -982,6 +818,7 @@ function loadStockTable(table, options) {
if (row.status == {{ StockStatus.REJECTED }}) {
html += makeIconBadge('fa-times-circle icon-red', '{% trans "Stock item has been rejected" %}');
}
// LOST
else if (row.status == {{ StockStatus.LOST }}) {
html += makeIconBadge('fa-question-circle','{% trans "Stock item is lost" %}');
@ -996,46 +833,75 @@ function loadStockTable(table, options) {
return html;
}
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
col = {
field: 'status',
title: '{% trans "Status" %}',
sortable: 'true',
formatter: function(value, row, index, field) {
return stockStatusDisplay(value);
},
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
col = {
field: 'batch',
title: '{% trans "Batch" %}',
sortable: true,
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
col = {
field: 'location_detail.pathstring',
title: '{% trans "Location" %}',
sortable: true,
formatter: function(value, row, index, field) {
return locationDetail(row);
}
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
col = {
field: 'stocktake_date',
title: '{% trans "Stocktake" %}',
sortable: true,
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
col = {
field: 'expiry_date',
title: '{% trans "Expiry Date" %}',
sortable: true,
visible: global_settings.STOCK_ENABLE_EXPIRY,
switchable: global_settings.STOCK_ENABLE_EXPIRY,
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
col = {
field: 'updated',
title: '{% trans "Last Updated" %}',
sortable: true,
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
columns.push({
field: 'purchase_order',
title: '{% trans "Purchase Order" %}',
formatter: function(value, row) {
@ -1078,21 +944,196 @@ function loadStockTable(table, options) {
return renderLink(text, link);
}
},
{
});
col = {
field: 'purchase_price_string',
title: '{% trans "Purchase Price" %}',
sortable: true,
},
{
};
if (!options.params.ordering) {
col['sortable'] = true;
};
columns.push(col);
columns.push({
field: 'packaging',
title: '{% trans "Packaging" %}',
},
{
field: 'notes',
title: '{% trans "Notes" %}',
});
table.inventreeTable({
method: 'get',
formatNoMatches: function() {
return '{% trans "No stock items matching query" %}';
},
url: options.url || "{% url 'api-stock-list' %}",
queryParams: filters,
sidePagination: 'server',
name: 'stock',
original: original,
showColumns: true,
columns: columns,
{% if False %}
groupByField: options.groupByField || 'part',
groupBy: grouping,
groupByFormatter: function(field, id, data) {
var row = data[0];
if (field == 'part_detail.full_name') {
var html = imageHoverIcon(row.part_detail.thumbnail);
html += row.part_detail.full_name;
html += ` <i>(${data.length} {% trans "items" %})</i>`;
html += makePartIcons(row.part_detail);
return html;
} else if (field == 'part_detail.IPN') {
var ipn = row.part_detail.IPN;
if (ipn) {
return ipn;
} else {
return '-';
}
],
} else if (field == 'part_detail.description') {
return row.part_detail.description;
} else if (field == 'packaging') {
var packaging = [];
data.forEach(function(item) {
var pkg = item.packaging;
if (!pkg) {
pkg = '-';
}
if (!packaging.includes(pkg)) {
packaging.push(pkg);
}
});
if (packaging.length > 1) {
return "...";
} else if (packaging.length == 1) {
return packaging[0];
} else {
return "-";
}
} else if (field == 'quantity') {
var stock = 0;
var items = 0;
data.forEach(function(item) {
stock += parseFloat(item.quantity);
items += 1;
});
stock = +stock.toFixed(5);
return stock + " (" + items + " items)";
} else if (field == 'status') {
var statii = [];
data.forEach(function(item) {
var status = String(item.status);
if (!status || status == '') {
status = '-';
}
if (!statii.includes(status)) {
statii.push(status);
}
});
// Multiple status codes
if (statii.length > 1) {
return "...";
} else if (statii.length == 1) {
return stockStatusDisplay(statii[0]);
} else {
return "-";
}
} else if (field == 'batch') {
var batches = [];
data.forEach(function(item) {
var batch = item.batch;
if (!batch || batch == '') {
batch = '-';
}
if (!batches.includes(batch)) {
batches.push(batch);
}
});
if (batches.length > 1) {
return "" + batches.length + " {% trans 'batches' %}";
} else if (batches.length == 1) {
if (batches[0]) {
return batches[0];
} else {
return '-';
}
} else {
return '-';
}
} else if (field == 'location_detail.pathstring') {
/* Determine how many locations */
var locations = [];
data.forEach(function(item) {
var detail = locationDetail(item);
if (!locations.includes(detail)) {
locations.push(detail);
}
});
if (locations.length == 1) {
// Single location, easy!
return locations[0];
} else if (locations.length > 1) {
return "In " + locations.length + " {% trans 'locations' %}";
} else {
return "<i>{% trans 'Undefined location' %}</i>";
}
} else if (field == 'notes') {
var notes = [];
data.forEach(function(item) {
var note = item.notes;
if (!note || note == '') {
note = '-';
}
if (!notes.includes(note)) {
notes.push(note);
}
});
if (notes.length > 1) {
return '...';
} else if (notes.length == 1) {
return notes[0] || '-';
} else {
return '-';
}
} else {
return '';
}
},
{% endif %}
});
/*