mirror of
https://github.com/inventree/InvenTree.git
synced 2025-08-07 20:32:12 +00:00
* Adds "consumed_by" field to the StockItem model. - Points to a BuildOrder instance which "consumed" this stock - Marks item as unavailable - Allows filtering against build order * Allow API filtering * Adds table of "consumed stock items" to build order page * Update stock table to show "consumed by" stock status * Add "consumed_by" link to stock item detail * Optionally add 'buildorder' details to installStockItem method * Update methodology for completing a build item - Instead of deleting stock, mark as "consumed by" * Fix history entry for splitting stock * Bug fix * track "consumed_by" field for tracked items also * Update build docs * Update allocation documentation * Update terminology.md * Unit test updates * Fix conflicting migrations * revert change
448 lines
14 KiB
HTML
448 lines
14 KiB
HTML
{% extends "stock/stock_app_base.html" %}
|
|
{% load static %}
|
|
{% load inventree_extras %}
|
|
{% load plugin_extras %}
|
|
{% load i18n %}
|
|
|
|
{% block sidebar %}
|
|
{% include "stock/location_sidebar.html" %}
|
|
{% endblock sidebar %}
|
|
|
|
{% block breadcrumb_tree %}
|
|
<div id="breadcrumb-tree"></div>
|
|
{% endblock breadcrumb_tree %}
|
|
|
|
{% block heading %}
|
|
{% if location %}
|
|
{% trans "Stock Location" %}:
|
|
{% settings_value "STOCK_LOCATION_DEFAULT_ICON" as default_icon %}
|
|
{% if location.icon or default_icon %}
|
|
<span class="{{ location.icon|default:default_icon }}"></span>
|
|
{% endif %}
|
|
{{ location.name }}
|
|
{% else %}
|
|
{% trans "Stock" %}
|
|
{% endif %}
|
|
{% endblock heading %}
|
|
|
|
{% block actions %}
|
|
|
|
<!-- Admin view -->
|
|
{% if location and user.is_staff and roles.stock_location.change %}
|
|
{% url 'admin:stock_stocklocation_change' location.pk as url %}
|
|
{% include "admin_button.html" with url=url %}
|
|
{% endif %}
|
|
{% settings_value "STOCKTAKE_ENABLE" as stocktake_enable %}
|
|
{% if stocktake_enable and roles.stocktake.add %}
|
|
<button type='button' class='btn btn-outline-secondary' id='location-stocktake' title='{% trans "Perform stocktake for this stock location" %}'>
|
|
<span class='fas fa-clipboard-check'></span>
|
|
</button>
|
|
{% endif %}
|
|
|
|
{% mixin_available "locate" as locate_available %}
|
|
{% if location and plugins_enabled and locate_available %}
|
|
<button id='locate-location-button' title='{% trans "Locate stock location" %}' class='btn btn-outline-secondary' typy='button'>
|
|
<span class='fas fa-search-location'></span>
|
|
</button>
|
|
|
|
{% endif %}
|
|
|
|
{% if barcodes %}
|
|
<!-- Barcode actions menu -->
|
|
{% if location %}
|
|
<div class='btn-group' role='group'>
|
|
<button id='barcode-options' title='{% trans "Barcode actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'><span class='fas fa-qrcode'></span> <span class='caret'></span></button>
|
|
<ul class='dropdown-menu'>
|
|
<li><a class='dropdown-item' href='#' id='show-qr-code'><span class='fas fa-qrcode'></span> {% trans "Show QR Code" %}</a></li>
|
|
{% if location.barcode_hash %}
|
|
<li><a class='dropdown-item' href='#' id='barcode-unlink'><span class='fas fa-unlink'></span> {% trans "Unlink Barcode" %}</a></li>
|
|
{% else %}
|
|
<li><a class='dropdown-item' href='#' id='barcode-link'><span class='fas fa-link'></span> {% trans "Link Barcode" %}</a></li>
|
|
{% endif %}
|
|
<li><a class='dropdown-item' href='#' id='barcode-scan-in-items' title='{% trans "Scan stock items into this location" %}'><span class='fas fa-boxes'></span> {% trans "Scan In Stock Items" %}</a></li>
|
|
<li><a class='dropdown-item' href='#' id='barcode-scan-in-containers' title='{% trans "Scan stock container into this location" %}'><span class='fas fa-sitemap'></span> {% trans "Scan In Container" %}</a></li>
|
|
</ul>
|
|
</div>
|
|
<!-- Printing action -->
|
|
{% if labels_enabled %}
|
|
<div class='btn-group' role='group'>
|
|
<button id='printing-options' title='{% trans "Printing actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
|
<span class='fas fa-print'></span> <span class='caret'></span>
|
|
</button>
|
|
<ul class='dropdown-menu'>
|
|
<li><a class='dropdown-item' href='#' id='print-label'><span class='fas fa-tag'></span> {% trans "Print Label" %}</a>
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
<!-- Check permissions and owner -->
|
|
{% if user_owns_location %}
|
|
{% if roles.stock.change %}
|
|
<div class='btn-group' role='group'>
|
|
<button id='stock-actions' title='{% trans "Stock actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
|
<span class='fas fa-boxes'></span> <span class='caret'></span>
|
|
</button>
|
|
<ul class='dropdown-menu' role='menu'>
|
|
<li>
|
|
<a class='dropdown-item' href='#' id='location-count'>
|
|
<span class='fas fa-clipboard-list'></span>
|
|
{% trans "Count stock" %}
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class='dropdown-item' href='#' id='location-move'>
|
|
<span class='fas fa-exchange-alt'></span>
|
|
{% trans "Transfer stock" %}
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
{% if roles.stock_location.change %}
|
|
<div class='btn-group' role='group'>
|
|
<button id='location-actions' title='{% trans "Location actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle="dropdown"><span class='fas fa-sitemap'></span> <span class='caret'></span></button>
|
|
<ul class='dropdown-menu' role='menu'>
|
|
<li><a class='dropdown-item' href='#' id='location-edit'><span class='fas fa-edit icon-green'></span> {% trans "Edit location" %}</a></li>
|
|
{% if roles.stock.delete %}
|
|
<li><a class='dropdown-item' href='#' id='location-delete'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete location" %}</a></li>
|
|
{% endif %}
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endblock actions %}
|
|
|
|
{% block details_left %}
|
|
<table class='table table-striped table-condensed'>
|
|
<col width='25'>
|
|
{% if location %}
|
|
{% if location.description %}
|
|
<tr>
|
|
<td><span class='fas fa-info-circle'></span></td>
|
|
<td>{% trans "Description" %}</td>
|
|
<td>{{ location.description }}</td>
|
|
</tr>
|
|
{% endif %}
|
|
<tr>
|
|
<td><span class='fas fa-sitemap'></span></td>
|
|
<td>{% trans "Location Path" %}</td>
|
|
<td>{{ location.pathstring }}</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td><span class='fas fa-sitemap'></span></td>
|
|
<td>{% trans "Location Path" %}</td>
|
|
<td><em>{% trans "Top level stock location" %}</em></td>
|
|
</tr>
|
|
{% endif %}
|
|
{% if ownership_enabled and location_owner %}
|
|
<tr>
|
|
<td><span class='fas fa-users'></span></td>
|
|
<td>{% trans "Location Owner" %}</td>
|
|
<td>
|
|
{{ location_owner }}
|
|
{% if not user_owns_location %}
|
|
<span class='badge rounded-pill bg-warning badge-right' title='{% trans "You are not in the list of owners of this location. This stock location cannot be edited." %}'>
|
|
{% trans "Read only" %}
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
{% include "barcode_data.html" with instance=location %}
|
|
</table>
|
|
{% endblock details_left %}
|
|
|
|
{% block details_right %}
|
|
{% if location %}
|
|
<table class='table table-striped table-condensed'>
|
|
<col width='25'>
|
|
<tr>
|
|
<td><span class='fas fa-map-marker-alt'></span></td>
|
|
<td>{% trans "Sublocations" %}</td>
|
|
<td>{{ location.children.count }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class='fas fa-boxes'></span></td>
|
|
<td>{% trans "Stock Items" %}</td>
|
|
<td>{{ location.item_count }}</td>
|
|
</tr>
|
|
</table>
|
|
{% else %}
|
|
<table class='table table-striped table-condensed'>
|
|
<col width='25'>
|
|
<tr>
|
|
<td><span class='fas fa-map-marker-alt'></span></td>
|
|
<td>{% trans "Stock Locations" %}</td>
|
|
<td>{{ loc_count }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class='fas fa-boxes'></span></td>
|
|
<td>{% trans "Stock Items" %}</td>
|
|
<td>{{ stock_count }}</td>
|
|
</tr>
|
|
</table>
|
|
{% endif %}
|
|
{% endblock details_right %}
|
|
|
|
{% block page_content %}
|
|
|
|
<div class='panel panel-hidden' id='panel-stock'>
|
|
<div class='panel-heading'>
|
|
<div class='d-flex flex-wrap'>
|
|
<h4>{% trans "Stock Items" %}</h4>
|
|
{% include "spacer.html" %}
|
|
<div class='btn-group' role='group'>
|
|
<button type='button' class='btn btn-success' id='item-create' title='{% trans "Create new stock item" %}'>
|
|
<span class='fas fa-plus-circle'></span> {% trans "New Stock Item" %}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class='panel-content'>
|
|
{% include "stock_table.html" %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='panel panel-hidden' id='panel-sublocations'>
|
|
<div class='panel-heading'>
|
|
<div class='d-flex flex-wrap'>
|
|
<h4>{% trans "Sublocations" %}</h4>
|
|
{% include "spacer.html" %}
|
|
<div class='btn-group' role='group'>
|
|
{% if user_owns_location and roles.stock_location.add %}
|
|
<button class='btn btn-success' id='location-create' type='button' title='{% trans "Create new stock location" %}'>
|
|
<span class='fas fa-plus-circle'></span> {% trans "New Location" %}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class='panel-content'>
|
|
<div id='sublocation-button-toolbar'>
|
|
<div class='btn-group' role='group'>
|
|
{% include "filter_list.html" with id="location" %}
|
|
</div>
|
|
</div>
|
|
|
|
<table class='table table-striped table-condensed' data-toolbar='#sublocation-button-toolbar' id='sublocation-table'></table>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock page_content %}
|
|
|
|
{% block js_ready %}
|
|
{{ block.super }}
|
|
|
|
{% settings_value "STOCKTAKE_ENABLE" as stocktake_enable %}
|
|
{% if stocktake_enable and roles.stocktake.add %}
|
|
$('#location-stocktake').click(function() {
|
|
generateStocktakeReport({
|
|
category: {},
|
|
location: {
|
|
{% if location %}value: {{ location.pk }},{% endif %}
|
|
},
|
|
generate_report: {},
|
|
update_parts: {},
|
|
});
|
|
});
|
|
{% endif %}
|
|
|
|
{% if plugins_enabled and location %}
|
|
$('#locate-location-button').click(function() {
|
|
locateItemOrLocation({
|
|
location: {{ location.pk }},
|
|
});
|
|
});
|
|
{% endif %}
|
|
|
|
onPanelLoad('sublocations', function() {
|
|
loadStockLocationTable($('#sublocation-table'), {
|
|
params: {
|
|
{% if location %}
|
|
parent: {{ location.pk }},
|
|
{% else %}
|
|
parent: 'null',
|
|
{% endif %}
|
|
},
|
|
allowTreeView: true,
|
|
});
|
|
});
|
|
|
|
linkButtonsToSelection(
|
|
$('#sublocation-table'),
|
|
[
|
|
'#location-print-options',
|
|
]
|
|
);
|
|
|
|
{% if labels_enabled %}
|
|
$('#print-label').click(function() {
|
|
|
|
var locs = [{{ location.pk }}];
|
|
|
|
printLabels({
|
|
items: locs,
|
|
singular_name: '{% trans "stock location" %}',
|
|
key: 'location',
|
|
url: '{% url "api-stocklocation-label-list" %}',
|
|
});
|
|
});
|
|
{% endif %}
|
|
|
|
{% if location %}
|
|
$("#barcode-scan-in-items").click(function() {
|
|
barcodeCheckInStockItems({{ location.id }});
|
|
});
|
|
|
|
$('#barcode-scan-in-containers').click(function() {
|
|
barcodeCheckInStockLocations({{ location.id }},
|
|
{
|
|
onSuccess: function() {
|
|
showMessage(
|
|
'{% trans "Scanned stock container into this location" %}',
|
|
{
|
|
style: 'success',
|
|
}
|
|
);
|
|
|
|
$('#sublocation-table').bootstrapTable('refresh');
|
|
}
|
|
}
|
|
);
|
|
});
|
|
{% endif %}
|
|
|
|
$('#location-create').click(function () {
|
|
createStockLocation({
|
|
{% if location %}
|
|
parent: {{ location.pk }},
|
|
{% endif %}
|
|
follow: true,
|
|
});
|
|
});
|
|
|
|
{% if location %}
|
|
|
|
$('#location-edit').click(function() {
|
|
editStockLocation({{ location.id }}, {
|
|
reload: true,
|
|
});
|
|
});
|
|
|
|
$('#location-delete').click(function() {
|
|
|
|
deleteStockLocation({{ location.pk }}, {
|
|
{% if location.parent %}
|
|
redirect: '{% url "stock-location-detail" location.parent.pk %}',
|
|
{% else %}
|
|
redirect: '{% url "stock-index" %}',
|
|
{% endif %}
|
|
});
|
|
});
|
|
|
|
function adjustLocationStock(action) {
|
|
inventreeGet(
|
|
'{% url "api-stock-list" %}',
|
|
{
|
|
location: {{ location.id }},
|
|
in_stock: true,
|
|
part_detail: true,
|
|
location_detail: true,
|
|
},
|
|
{
|
|
success: function(items) {
|
|
adjustStock(action, items, {
|
|
success: function() {
|
|
location.reload();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
$("#location-count").click(function() {
|
|
adjustLocationStock('count');
|
|
});
|
|
|
|
$("#location-move").click(function() {
|
|
adjustLocationStock('move');
|
|
});
|
|
|
|
{% if barcodes %}
|
|
$('#show-qr-code').click(function() {
|
|
showQRDialog(
|
|
'{% trans "Stock Location QR Code" %}',
|
|
'{"stocklocation": {{ location.pk }} }'
|
|
);
|
|
});
|
|
|
|
$("#barcode-link").click(function() {
|
|
linkBarcodeDialog(
|
|
{
|
|
stocklocation: {{ location.pk }},
|
|
},
|
|
{
|
|
title: '{% trans "Link Barcode to Stock Location" %}',
|
|
}
|
|
);
|
|
});
|
|
|
|
$("#barcode-unlink").click(function() {
|
|
unlinkBarcode({
|
|
stocklocation: {{ location.pk }},
|
|
});
|
|
});
|
|
|
|
{% endif %}
|
|
|
|
{% endif %}
|
|
|
|
$('#item-create').click(function () {
|
|
createNewStockItem({
|
|
data: {
|
|
{% if location %}
|
|
location: {{ location.id }}
|
|
{% endif %}
|
|
},
|
|
});
|
|
});
|
|
|
|
onPanelLoad('stock', function() {
|
|
loadStockTable($("#stock-table"), {
|
|
buttons: [
|
|
'#stock-options',
|
|
],
|
|
params: {
|
|
{% if location %}
|
|
location: {{ location.pk }},
|
|
{% endif %}
|
|
part_detail: true,
|
|
location_detail: true,
|
|
supplier_part_detail: true,
|
|
},
|
|
});
|
|
});
|
|
|
|
enableSidebar('stocklocation');
|
|
|
|
// Enable breadcrumb tree view
|
|
enableBreadcrumbTree({
|
|
label: 'location',
|
|
url: '{% url "api-location-tree" %}',
|
|
{% if location %}
|
|
selected: {{ location.pk }},
|
|
{% endif %}
|
|
processNode: function(node) {
|
|
node.text = node.name;
|
|
node.href = `/stock/location/${node.pk}/`;
|
|
|
|
return node;
|
|
},
|
|
defaultIcon: global_settings.STOCK_LOCATION_DEFAULT_ICON,
|
|
});
|
|
|
|
{% endblock js_ready %}
|