2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 13:05:42 +00:00

Merge branch 'master' of https://github.com/inventree/InvenTree into price-history

This commit is contained in:
2021-04-21 11:12:48 +02:00
89 changed files with 47808 additions and 2850 deletions

View File

@ -2,12 +2,13 @@
{% load i18n %}
{% load static %}
{% load inventree_extras %}
{% block page_title %}
InvenTree | {% trans "Index" %}
{% inventree_title %} | {% trans "Index" %}
{% endblock %}
{% block content %}
<h3>InvenTree</h3>
<h3>{% inventree_title %} </h3>
<hr>
<div class='col-sm-3' id='item-panel'>

View File

@ -5,7 +5,7 @@
{% load inventree_extras %}
{% block page_title %}
InvenTree | {% trans "Search Results" %}
{% inventree_title %} | {% trans "Search Results" %}
{% endblock %}
{% block content %}

View File

@ -16,6 +16,7 @@
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="INVENTREE_INSTANCE" icon="fa-info-circle" %}
{% include "InvenTree/settings/setting.html" with key="INVENTREE_INSTANCE_TITLE" icon="fa-info-circle" %}
{% include "InvenTree/settings/setting.html" with key="INVENTREE_BASE_URL" icon="fa-globe" %}
{% include "InvenTree/settings/setting.html" with key="INVENTREE_COMPANY_NAME" icon="fa-building" %}
{% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %}

View File

@ -2,9 +2,10 @@
{% load i18n %}
{% load static %}
{% load inventree_extras %}
{% block page_title %}
InvenTree | {% trans "Settings" %}
{% inventree_title %} | {% trans "Settings" %}
{% endblock %}
{% block content %}

View File

@ -60,7 +60,7 @@
<title>
{% block page_title %}
InvenTree
{% inventree_title %}
{% endblock %}
</title>
</head>
@ -144,20 +144,21 @@ InvenTree
<script type='text/javascript' src="{% static 'script/inventree/notification.js' %}"></script>
<script type='text/javascript' src="{% static 'script/inventree/sidenav.js' %}"></script>
<script type='text/javascript' src="{% url 'barcode.js' %}"></script>
<script type='text/javascript' src="{% url 'bom.js' %}"></script>
<script type='text/javascript' src="{% url 'company.js' %}"></script>
<script type='text/javascript' src="{% url 'part.js' %}"></script>
<script type='text/javascript' src="{% url 'modals.js' %}"></script>
<script type='text/javascript' src="{% url 'label.js' %}"></script>
<script type='text/javascript' src="{% url 'report.js' %}"></script>
<script type='text/javascript' src="{% url 'stock.js' %}"></script>
<script type='text/javascript' src="{% url 'build.js' %}"></script>
<script type='text/javascript' src="{% url 'order.js' %}"></script>
<script type='text/javascript' src="{% url 'calendar.js' %}"></script>
<script type='text/javascript' src="{% url 'tables.js' %}"></script>
<script type='text/javascript' src="{% url 'table_filters.js' %}"></script>
<script type='text/javascript' src="{% url 'filters.js' %}"></script>
<!-- translated -->
<script type='text/javascript' src="{% i18n_static 'barcode.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'bom.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'company.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'part.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'modals.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'label.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'report.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'stock.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'build.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'order.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'calendar.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'tables.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'table_filters.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'filters.js' %}"></script>
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>

View File

@ -32,12 +32,17 @@ function newBuildOrder(options={}) {
}
function makeBuildOutputActionButtons(output, buildInfo) {
function makeBuildOutputActionButtons(output, buildInfo, lines) {
/* Generate action buttons for a build output.
*/
var buildId = buildInfo.pk;
var outputId = output.pk;
if (output) {
outputId = output.pk;
} else {
outputId = 'untracked';
}
var panel = `#allocation-panel-${outputId}`;
@ -50,35 +55,42 @@ function makeBuildOutputActionButtons(output, buildInfo) {
var html = `<div class='btn-group float-right' role='group'>`;
// Add a button to "auto allocate" against the build
html += makeIconButton(
'fa-magic icon-blue', 'button-output-auto', outputId,
'{% trans "Auto-allocate stock items to this output" %}',
);
// "Auto" allocation only works for untracked stock items
if (!output && lines > 0) {
html += makeIconButton(
'fa-magic icon-blue', 'button-output-auto', outputId,
'{% trans "Auto-allocate stock items to this output" %}',
);
}
// Add a button to "complete" the particular build output
html += makeIconButton(
'fa-check icon-green', 'button-output-complete', outputId,
'{% trans "Complete build output" %}',
{
//disabled: true
}
);
if (lines > 0) {
// Add a button to "cancel" the particular build output (unallocate)
html += makeIconButton(
'fa-minus-circle icon-red', 'button-output-unallocate', outputId,
'{% trans "Unallocate stock from build output" %}',
);
}
// Add a button to "cancel" the particular build output (unallocate)
html += makeIconButton(
'fa-minus-circle icon-red', 'button-output-unallocate', outputId,
'{% trans "Unallocate stock from build output" %}',
);
// Add a button to "delete" the particular build output
html += makeIconButton(
'fa-trash-alt icon-red', 'button-output-delete', outputId,
'{% trans "Delete build output" %}',
);
if (output) {
// Add a button to "destroy" the particular build output (mark as damaged, scrap)
// TODO
// Add a button to "complete" the particular build output
html += makeIconButton(
'fa-check icon-green', 'button-output-complete', outputId,
'{% trans "Complete build output" %}',
{
//disabled: true
}
);
// Add a button to "delete" the particular build output
html += makeIconButton(
'fa-trash-alt icon-red', 'button-output-delete', outputId,
'{% trans "Delete build output" %}',
);
// TODO - Add a button to "destroy" the particular build output (mark as damaged, scrap)
}
html += '</div>';
@ -90,7 +102,6 @@ function makeBuildOutputActionButtons(output, buildInfo) {
launchModalForm(`/build/${buildId}/auto-allocate/`,
{
data: {
output: outputId,
},
success: reloadTable,
}
@ -98,11 +109,14 @@ function makeBuildOutputActionButtons(output, buildInfo) {
});
$(panel).find(`#button-output-complete-${outputId}`).click(function() {
var pk = $(this).attr('pk');
launchModalForm(
`/build/${buildId}/complete-output/`,
{
data: {
output: outputId,
output: pk,
},
reload: true,
}
@ -110,24 +124,30 @@ function makeBuildOutputActionButtons(output, buildInfo) {
});
$(panel).find(`#button-output-unallocate-${outputId}`).click(function() {
var pk = $(this).attr('pk');
launchModalForm(
`/build/${buildId}/unallocate/`,
{
success: reloadTable,
data: {
output: outputId,
output: pk,
}
}
);
});
$(panel).find(`#button-output-delete-${outputId}`).click(function() {
var pk = $(this).attr('pk');
launchModalForm(
`/build/${buildId}/delete-output/`,
{
reload: true,
data: {
output: outputId
output: pk
}
}
);
@ -152,13 +172,21 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
var outputId = null;
outputId = output.pk;
if (output) {
outputId = output.pk;
} else {
outputId = 'untracked';
}
var table = options.table;
if (options.table == null) {
table = `#allocation-table-${outputId}`;
}
// If an "output" is specified, then only "trackable" parts are allocated
// Otherwise, only "untrackable" parts are allowed
var trackable = ! !output;
function reloadTable() {
// Reload the entire build allocation table
@ -168,7 +196,13 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
function requiredQuantity(row) {
// Return the requied quantity for a given row
return row.quantity * output.quantity;
if (output) {
// "Tracked" parts are calculated against individual build outputs
return row.quantity * output.quantity;
} else {
// "Untracked" parts are specified against the build itself
return row.quantity * buildInfo.quantity;
}
}
function sumAllocations(row) {
@ -300,6 +334,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
queryParams: {
part: partId,
sub_part_detail: true,
sub_part_trackable: trackable,
},
formatNoMatches: function() {
return '{% trans "No BOM items found" %}';
@ -310,11 +345,19 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
onLoadSuccess: function(tableData) {
// Once the BOM data are loaded, request allocation data for this build output
var params = {
build: buildId,
}
if (output) {
params.sub_part_trackable = true;
params.output = outputId;
} else {
params.sub_part_trackable = false;
}
inventreeGet('/api/build/item/',
{
build: buildId,
output: outputId,
},
params,
{
success: function(data) {
// Iterate through the returned data, and group by the part they point to
@ -355,8 +398,16 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
// Calculate the total allocated quantity
var allocatedQuantity = sumAllocations(tableRow);
var requiredQuantity = 0;
if (output) {
requiredQuantity = tableRow.quantity * output.quantity;
} else {
requiredQuantity = tableRow.quantity * buildInfo.quantity;
}
// Is this line item fully allocated?
if (allocatedQuantity >= (tableRow.quantity * output.quantity)) {
if (allocatedQuantity >= requiredQuantity) {
allocatedLines += 1;
}
@ -367,16 +418,21 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
// Update the total progress for this build output
var buildProgress = $(`#allocation-panel-${outputId}`).find($(`#output-progress-${outputId}`));
var progress = makeProgressBar(
allocatedLines,
totalLines
);
if (totalLines > 0) {
buildProgress.html(progress);
var progress = makeProgressBar(
allocatedLines,
totalLines
);
buildProgress.html(progress);
} else {
buildProgress.html('');
}
// Update the available actions for this build output
makeBuildOutputActionButtons(output, buildInfo);
makeBuildOutputActionButtons(output, buildInfo, totalLines);
}
}
);
@ -600,6 +656,9 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
},
]
});
// Initialize the action buttons
makeBuildOutputActionButtons(output, buildInfo, 0);
}
@ -654,7 +713,7 @@ function loadBuildTable(table, options) {
field: 'reference',
title: '{% trans "Build" %}',
sortable: true,
switchable: false,
switchable: true,
formatter: function(value, row, index, field) {
var prefix = "{% settings_value 'BUILDORDER_REFERENCE_PREFIX' %}";
@ -675,6 +734,7 @@ function loadBuildTable(table, options) {
{
field: 'title',
title: '{% trans "Description" %}',
switchable: true,
},
{
field: 'part',
@ -725,7 +785,7 @@ function loadBuildTable(table, options) {
},
{
field: 'completion_date',
title: '{% trans "Completed" %}',
title: '{% trans "Completion Date" %}',
sortable: true,
},
],

View File

@ -1,4 +1,5 @@
{% load i18n %}
{% load inventree_extras %}
/* Part API functions
* Requires api.js to be loaded first
@ -506,6 +507,82 @@ function loadPartTable(table, url, options={}) {
});
}
function loadPartCategoryTable(table, options) {
/* Display a table of part categories */
var params = options.params || {};
var filterListElement = options.filterList || '#filter-list-category';
var filters = {};
var filterKey = options.filterKey || options.name || 'category';
if (!options.disableFilters) {
filters = loadTableFilters(filterKey);
}
var original = {};
for (var key in params) {
original[key] = params[key];
filters[key] = params[key];
}
setupFilterList(filterKey, table, filterListElement);
table.inventreeTable({
method: 'get',
url: options.url || '{% url "api-part-category-list" %}',
queryParams: filters,
sidePagination: 'server',
name: 'category',
original: original,
showColumns: true,
columns: [
{
checkbox: true,
title: '{% trans "Select" %}',
searchable: false,
switchable: false,
visible: false,
},
{
field: 'name',
title: '{% trans "Name" %}',
switchable: true,
sortable: true,
formatter: function(value, row) {
return renderLink(
value,
`/part/category/${row.pk}/`
);
}
},
{
field: 'description',
title: '{% trans "Description" %}',
switchable: true,
sortable: false,
},
{
field: 'pathstring',
title: '{% trans "Path" %}',
switchable: true,
sortable: false,
},
{
field: 'parts',
title: '{% trans "Parts" %}',
switchable: true,
sortable: false,
}
]
});
}
function yesNoLabel(value) {
if (value) {
return `<span class='label label-green'>{% trans "YES" %}</span>`;

View File

@ -897,6 +897,83 @@ function loadStockTable(table, options) {
});
}
function loadStockLocationTable(table, options) {
/* Display a table of stock locations */
var params = options.params || {};
var filterListElement = options.filterList || '#filter-list-location';
var filters = {};
var filterKey = options.filterKey || options.name || 'location';
if (!options.disableFilters) {
filters = loadTableFilters(filterKey);
}
var original = {};
for (var key in params) {
original[key] = params[key];
}
setupFilterList(filterKey, table, filterListElement);
for (var key in params) {
filters[key] = params[key];
}
table.inventreeTable({
method: 'get',
url: options.url || '{% url "api-location-list" %}',
queryParams: filters,
sidePagination: 'server',
name: 'location',
original: original,
showColumns: true,
columns: [
{
checkbox: true,
title: '{% trans "Select" %}',
searchable: false,
switchable: false,
},
{
field: 'name',
title: '{% trans "Name" %}',
switchable: true,
sortable: true,
formatter: function(value, row) {
return renderLink(
value,
`/stock/location/${row.pk}/`
);
},
},
{
field: 'description',
title: '{% trans "Description" %}',
switchable: true,
sortable: false,
},
{
field: 'pathstring',
title: '{% trans "Path" %}',
switchable: true,
sortable: false,
},
{
field: 'items',
title: '{% trans "Stock Items" %}',
switchable: true,
sortable: false,
sortName: 'item_count',
}
]
});
}
function loadStockTrackingTable(table, options) {
var cols = [

View File

@ -62,6 +62,28 @@ function getAvailableTableFilters(tableKey) {
};
}
// Filters for "stock location" table
if (tableKey == "location") {
return {
cascade: {
type: 'bool',
title: '{% trans "Include sublocations" %}',
description: '{% trans "Include locations" %}',
}
};
}
// Filters for "part category" table
if (tableKey == "category") {
return {
cascade: {
type: 'bool',
title: '{% trans "Include subcategories" %}',
description: '{% trans "Include subcategories" %}',
}
};
}
// Filters for the "customer stock" table (really a subset of "stock")
if (tableKey == "customerstock") {
return {

View File

@ -1,6 +1,7 @@
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load crispy_forms_tags %}
{% load inventree_extras %}
<!DOCTYPE html>
<html lang="en">
@ -29,7 +30,7 @@
</style>
<title>
InvenTree
{% inventree_title %}
</title>
</head>
@ -42,7 +43,7 @@
<div class='container-fluid'>
<div class='clearfix content-heading login-header'>
<img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
<span><h3>InvenTree</h3></span>
<span><h3>{% inventree_title %} </h3></span>
</div>
<hr>

View File

@ -1,5 +1,6 @@
{% load static %}
{% load i18n %}
{% load inventree_extras %}
<!DOCTYPE html>
<html lang="en">
@ -28,7 +29,7 @@
</style>
<title>
InvenTree
{% inventree_title %}
</title>
</head>
@ -44,7 +45,7 @@
<div class='container-fluid'>
<div class='clearfix content-heading login-header'>
<img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
<span><h3>InvenTree</h3></span>
<span><h3>{% inventree_title %} </h3></span>
</div>
<hr>

View File

@ -1,6 +1,7 @@
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load crispy_forms_tags %}
{% load inventree_extras %}
<!DOCTYPE html>
<html lang="en">
@ -29,7 +30,7 @@
</style>
<title>
InvenTree
{% inventree_title %}
</title>
</head>
@ -42,7 +43,7 @@
<div class='container-fluid'>
<div class='clearfix content-heading login-header'>
<img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
<span><h3>InvenTree</h3></span>
<span><h3>{% inventree_title %} </h3></span>
</div>
<hr>

View File

@ -1,6 +1,7 @@
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load crispy_forms_tags %}
{% load inventree_extras %}
<!DOCTYPE html>
<html lang="en">
@ -29,7 +30,7 @@
</style>
<title>
InvenTree
{% inventree_title %}
</title>
</head>
@ -42,7 +43,7 @@
<div class='container-fluid'>
<div class='clearfix content-heading login-header'>
<img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
<span><h3>InvenTree</h3></span>
<span><h3>{% inventree_title %} </h3></span>
</div>
<hr>

View File

@ -1,6 +1,7 @@
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load crispy_forms_tags %}
{% load inventree_extras %}
<!DOCTYPE html>
<html lang="en">
@ -29,7 +30,7 @@
</style>
<title>
InvenTree
{% inventree_title %}
</title>
</head>
@ -42,7 +43,7 @@
<div class='container-fluid'>
<div class='clearfix content-heading login-header'>
<img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
<span><h3>InvenTree</h3></span>
<span><h3>{% inventree_title %} </h3></span>
</div>
<hr>
<div class='container-fluid'>

View File

@ -1,6 +1,7 @@
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load crispy_forms_tags %}
{% load inventree_extras %}
<!DOCTYPE html>
<html lang="en">
@ -29,7 +30,7 @@
</style>
<title>
InvenTree
{% inventree_title %}
</title>
</head>
@ -42,7 +43,7 @@
<div class='container-fluid'>
<div class='clearfix content-heading login-header'>
<img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
<span><h3>InvenTree</h3></span>
<span><h3>{% inventree_title %} </h3></span>
</div>
<hr>

View File

@ -32,6 +32,7 @@
</ul>
</div>
{% endif %}
<!-- Printing actions menu -->
<div class='btn-group'>
<button id='stock-print-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown" title='{% trans "Printing Actions" %}'>
<span class='fas fa-print'></span> <span class='caret'></span>

View File

@ -9,8 +9,12 @@
{% block content %}
{% block header_panel %}
<div class='panel panel-default panel-inventree'>
{% block header_pre_content %}
{% endblock %}
<div class='row'>
<div class='col-sm-6'>
<div class='media-left'>
@ -30,8 +34,14 @@
{% endblock %}
</div>
</div>
</div>
{% block header_post_content %}
{% endblock %}
</div>
{% endblock %}
{% block content_panels %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>
@ -41,12 +51,15 @@
</h4>
</div>
{% block details_panel %}
<div class='panel-content'>
{% block details %}
<!-- Particular page detail views go here -->
{% endblock %}
</div>
{% endblock %}
</div>
{% endblock %}
{% endblock %}