mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge branch 'master' into scheduling
This commit is contained in:
commit
954f0afb85
@ -383,9 +383,7 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
Returns the BOM items for the part referenced by this BuildOrder
|
||||
"""
|
||||
|
||||
return self.part.bom_items.all().prefetch_related(
|
||||
'sub_part'
|
||||
)
|
||||
return self.part.get_bom_items()
|
||||
|
||||
@property
|
||||
def tracked_bom_items(self):
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1453,7 +1453,9 @@ class Part(MPTTModel):
|
||||
By default, will include inherited BOM items
|
||||
"""
|
||||
|
||||
return BomItem.objects.filter(self.get_bom_item_filter(include_inherited=include_inherited))
|
||||
queryset = BomItem.objects.filter(self.get_bom_item_filter(include_inherited=include_inherited))
|
||||
|
||||
return queryset.prefetch_related('sub_part')
|
||||
|
||||
def get_installed_part_options(self, include_inherited=True, include_variants=True):
|
||||
"""
|
||||
@ -1906,6 +1908,9 @@ class Part(MPTTModel):
|
||||
|
||||
include_inherited = kwargs.get('include_inherited', False)
|
||||
|
||||
# Should substitute parts be duplicated?
|
||||
copy_substitutes = kwargs.get('copy_substitutes', True)
|
||||
|
||||
# Copy existing BOM items from another part
|
||||
# Note: Inherited BOM Items will *not* be duplicated!!
|
||||
for bom_item in other.get_bom_items(include_inherited=include_inherited).all():
|
||||
@ -1928,11 +1933,22 @@ class Part(MPTTModel):
|
||||
if not bom_item.sub_part.check_add_to_bom(self, raise_error=raise_error):
|
||||
continue
|
||||
|
||||
# Obtain a list of direct substitute parts against this BomItem
|
||||
substitutes = BomItemSubstitute.objects.filter(bom_item=bom_item)
|
||||
|
||||
# Construct a new BOM item
|
||||
bom_item.part = self
|
||||
bom_item.pk = None
|
||||
|
||||
bom_item.save()
|
||||
bom_item.refresh_from_db()
|
||||
|
||||
if copy_substitutes:
|
||||
for sub in substitutes:
|
||||
# Duplicate the substitute (and point to the *new* BomItem object)
|
||||
sub.pk = None
|
||||
sub.bom_item = bom_item
|
||||
sub.save()
|
||||
|
||||
@transaction.atomic
|
||||
def copy_parameters_from(self, other, **kwargs):
|
||||
|
@ -656,6 +656,9 @@ class PartCopyBOMSerializer(serializers.Serializer):
|
||||
fields = [
|
||||
'part',
|
||||
'remove_existing',
|
||||
'copy_substitutes',
|
||||
'include_inherited',
|
||||
'skip_invalid',
|
||||
]
|
||||
|
||||
part = serializers.PrimaryKeyRelatedField(
|
||||
@ -692,6 +695,12 @@ class PartCopyBOMSerializer(serializers.Serializer):
|
||||
default=False,
|
||||
)
|
||||
|
||||
copy_substitutes = serializers.BooleanField(
|
||||
label=_('Copy Substitute Parts'),
|
||||
help_text=_('Copy substitute parts when duplicate BOM items'),
|
||||
default=True,
|
||||
)
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Actually duplicate the BOM
|
||||
@ -706,6 +715,7 @@ class PartCopyBOMSerializer(serializers.Serializer):
|
||||
clear=data.get('remove_existing', True),
|
||||
skip_invalid=data.get('skip_invalid', False),
|
||||
include_inherited=data.get('include_inherited', False),
|
||||
copy_substitutes=data.get('copy_substitutes', True),
|
||||
)
|
||||
|
||||
|
||||
|
@ -137,7 +137,13 @@
|
||||
<h4>{% trans "Sales Order Allocations" %}</h4>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<table class='table table-striped table-condensed' id='sales-order-allocation-table'></table>
|
||||
|
||||
<div id='sales-order-allocation-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="salesorderallocation" %}
|
||||
</div>
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='sales-order-allocation-table' data-toolbar='#sales-order-allocation-button-toolbar'></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -357,7 +363,12 @@
|
||||
<h4>{% trans "Build Order Allocations" %}</h4>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<table class='table table-striped table-condensed' id='build-order-allocation-table'></table>
|
||||
<div id='build-allocation-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="buildorderallocation" %}
|
||||
</div>
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='build-order-allocation-table' data-toolbar='#build-allocation-button-toolbar'></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -742,6 +753,7 @@
|
||||
});
|
||||
|
||||
// Load the BOM table data in the pricing view
|
||||
{% if part.has_bom and roles.sales_order.view %}
|
||||
loadBomTable($("#bom-pricing-table"), {
|
||||
editable: false,
|
||||
bom_url: "{% url 'api-bom-list' %}",
|
||||
@ -749,6 +761,7 @@
|
||||
parent_id: {{ part.id }} ,
|
||||
sub_part_detail: true,
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
onPanelLoad("purchase-orders", function() {
|
||||
loadPartPurchaseOrderTable(
|
||||
|
@ -59,13 +59,13 @@
|
||||
<ul class='dropdown-menu'>
|
||||
<li>
|
||||
<a class='dropdown-item' href='#' id='part-count'>
|
||||
<span class='fas fa-clipboard-list'></span>
|
||||
<span class='fas fa-check-circle icon-green'></span>
|
||||
{% trans "Count part stock" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class='dropdown-item' href='#' id='part-move'>
|
||||
<span class='fas fa-exchange-alt'></span>
|
||||
<span class='fas fa-exchange-alt icon-blue'></span>
|
||||
{% trans "Transfer part stock" %}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -909,7 +909,6 @@ class StockItem(MPTTModel):
|
||||
""" Can this stock item be deleted? It can NOT be deleted under the following circumstances:
|
||||
|
||||
- Has installed stock items
|
||||
- Has a serial number and is tracked
|
||||
- Is installed inside another StockItem
|
||||
- It has been assigned to a SalesOrder
|
||||
- It has been assigned to a BuildOrder
|
||||
@ -918,9 +917,6 @@ class StockItem(MPTTModel):
|
||||
if self.installed_item_count() > 0:
|
||||
return False
|
||||
|
||||
if self.part.trackable and self.serial is not None:
|
||||
return False
|
||||
|
||||
if self.sales_order is not None:
|
||||
return False
|
||||
|
||||
|
@ -66,7 +66,7 @@
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
{% if not item.serialized %}
|
||||
{% if item.in_stock %}
|
||||
<li><a class='dropdown-item' href='#' id='stock-count' title='{% trans "Count stock" %}'><span class='fas fa-clipboard-list'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='stock-count' title='{% trans "Count stock" %}'><span class='fas fa-check-circle icon-green'></span> {% trans "Count stock" %}</a></li>
|
||||
{% endif %}
|
||||
{% if not item.customer %}
|
||||
<li><a class='dropdown-item' href='#' id='stock-add' title='{% trans "Add stock" %}'><span class='fas fa-plus-circle icon-green'></span> {% trans "Add stock" %}</a></li>
|
||||
|
@ -671,9 +671,7 @@ function loadBomTable(table, options={}) {
|
||||
// Do we show part pricing in the BOM table?
|
||||
var show_pricing = global_settings.PART_SHOW_PRICE_IN_BOM;
|
||||
|
||||
if (!show_pricing) {
|
||||
params.include_pricing = false;
|
||||
}
|
||||
params.include_pricing = show_pricing == true;
|
||||
|
||||
if (options.part_detail) {
|
||||
params.part_detail = true;
|
||||
@ -989,32 +987,40 @@ function loadBomTable(table, options={}) {
|
||||
|
||||
// Function to request BOM data for sub-items
|
||||
// This function may be called recursively for multi-level BOMs
|
||||
function requestSubItems(bom_pk, part_pk) {
|
||||
function requestSubItems(bom_pk, part_pk, depth=0) {
|
||||
|
||||
// TODO: 2022-02-03 Currently, multi-level BOMs are not actually displayed.
|
||||
// Prevent multi-level recursion
|
||||
const MAX_BOM_DEPTH = 25;
|
||||
|
||||
// Re-enable this function once multi-level display has been re-deployed
|
||||
return;
|
||||
if (depth >= MAX_BOM_DEPTH) {
|
||||
console.log(`Maximum BOM depth (${MAX_BOM_DEPTH}) reached!`);
|
||||
return;
|
||||
}
|
||||
|
||||
inventreeGet(
|
||||
options.bom_url,
|
||||
{
|
||||
part: part_pk,
|
||||
sub_part_detail: true,
|
||||
include_pricing: show_pricing == true,
|
||||
},
|
||||
{
|
||||
success: function(response) {
|
||||
|
||||
// Add the returned sub-items to the table
|
||||
for (var idx = 0; idx < response.length; idx++) {
|
||||
|
||||
response[idx].parentId = bom_pk;
|
||||
|
||||
if (response[idx].sub_part_detail.assembly) {
|
||||
requestSubItems(response[idx].pk, response[idx].sub_part);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
table.bootstrapTable('append', response);
|
||||
|
||||
// Next, re-iterate and check if the new items also have sub items
|
||||
response.forEach(function(bom_item) {
|
||||
if (bom_item.sub_part_detail.assembly) {
|
||||
requestSubItems(bom_item.pk, bom_item.sub_part, depth + 1);
|
||||
}
|
||||
});
|
||||
|
||||
table.treegrid('collapseAll');
|
||||
},
|
||||
error: function(xhr) {
|
||||
@ -1026,7 +1032,7 @@ function loadBomTable(table, options={}) {
|
||||
}
|
||||
|
||||
table.inventreeTable({
|
||||
treeEnable: !options.editable,
|
||||
treeEnable: true,
|
||||
rootParentId: parent_id,
|
||||
idField: 'pk',
|
||||
uniqueId: 'pk',
|
||||
@ -1066,38 +1072,37 @@ function loadBomTable(table, options={}) {
|
||||
url: options.bom_url,
|
||||
onPostBody: function() {
|
||||
|
||||
if (!options.editable) {
|
||||
table.treegrid({
|
||||
treeColumn: 0,
|
||||
onExpand: function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
table.treegrid({
|
||||
treeColumn: 1,
|
||||
onExpand: function() {
|
||||
}
|
||||
});
|
||||
|
||||
table.treegrid('collapseAll');
|
||||
},
|
||||
onLoadSuccess: function() {
|
||||
|
||||
if (options.editable) {
|
||||
table.bootstrapTable('uncheckAll');
|
||||
} else {
|
||||
}
|
||||
|
||||
var data = table.bootstrapTable('getData');
|
||||
var data = table.bootstrapTable('getData');
|
||||
|
||||
for (var idx = 0; idx < data.length; idx++) {
|
||||
var row = data[idx];
|
||||
for (var idx = 0; idx < data.length; idx++) {
|
||||
var row = data[idx];
|
||||
|
||||
// If a row already has a parent ID set, it's already been updated!
|
||||
if (row.parentId) {
|
||||
continue;
|
||||
}
|
||||
// If a row already has a parent ID set, it's already been updated!
|
||||
if (row.parentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set the parent ID of the top-level rows
|
||||
row.parentId = parent_id;
|
||||
// Set the parent ID of the top-level rows
|
||||
row.parentId = parent_id;
|
||||
|
||||
table.bootstrapTable('updateRow', idx, row, true);
|
||||
table.bootstrapTable('updateRow', idx, row, true);
|
||||
|
||||
if (row.sub_part_detail.assembly) {
|
||||
requestSubItems(row.pk, row.sub_part);
|
||||
}
|
||||
if (row.sub_part_detail.assembly) {
|
||||
requestSubItems(row.pk, row.sub_part);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -475,6 +475,7 @@ function duplicateBom(part_id, options={}) {
|
||||
}
|
||||
},
|
||||
include_inherited: {},
|
||||
copy_substitutes: {},
|
||||
remove_existing: {},
|
||||
skip_invalid: {},
|
||||
},
|
||||
|
@ -278,7 +278,7 @@ $.fn.inventreeTable = function(options) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(`Could not get list of visible columns for column '${tableName}'`);
|
||||
console.log(`Could not get list of visible columns for table '${tableName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,16 +46,16 @@
|
||||
<ul class="dropdown-menu">
|
||||
{% if roles.stock.change %}
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-add' title='{% trans "Add to selected stock items" %}'><span class='fas fa-plus-circle icon-green'></span> {% trans "Add stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'><span class='fas fa-minus-circle'></span> {% trans "Remove stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'><span class='fas fa-check-circle'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'><span class='fas fa-exchange-alt'></span> {% trans "Move stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'><span class='fas fa-minus-circle icon-red'></span> {% trans "Remove stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'><span class='fas fa-check-circle icon-green'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'><span class='fas fa-exchange-alt icon-blue'></span> {% trans "Transfer stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-merge' title='{% trans "Merge selected stock items" %}'><span class='fas fa-object-group'></span> {% trans "Merge stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-order' title='{% trans "Order selected items" %}'><span class='fas fa-shopping-cart'></span> {% trans "Order stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-assign' title='{% trans "Assign to customer" %}'><span class='fas fa-user-tie'></span> {% trans "Assign to customer" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-set-status' title='{% trans "Change status" %}'><span class='fas fa-exclamation-circle'></span> {% trans "Change stock status" %}</a></li>
|
||||
{% endif %}
|
||||
{% if roles.stock.delete %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete stock" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user