mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Control build allocation of optional BOM items (#4090)
* Control build allocation of optional BOM items - User can specify in form whether optional items are allocated - Default = False * Updated unit test
This commit is contained in:
parent
d9e99e38d2
commit
0e8563ebee
@ -832,6 +832,7 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
exclude_location = kwargs.get('exclude_location', None)
|
||||
interchangeable = kwargs.get('interchangeable', False)
|
||||
substitutes = kwargs.get('substitutes', True)
|
||||
optional_items = kwargs.get('optional_items', False)
|
||||
|
||||
def stock_sort(item, bom_item, variant_parts):
|
||||
if item.part == bom_item.sub_part:
|
||||
@ -848,6 +849,10 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
# Do not auto-allocate stock to consumable BOM items
|
||||
continue
|
||||
|
||||
if bom_item.optional and not optional_items:
|
||||
# User has specified that optional_items are to be ignored
|
||||
continue
|
||||
|
||||
variant_parts = bom_item.sub_part.get_descendants(include_self=False)
|
||||
|
||||
unallocated_quantity = self.unallocated_quantity(bom_item)
|
||||
|
@ -812,6 +812,7 @@ class BuildAutoAllocationSerializer(serializers.Serializer):
|
||||
'exclude_location',
|
||||
'interchangeable',
|
||||
'substitutes',
|
||||
'optional_items',
|
||||
]
|
||||
|
||||
location = serializers.PrimaryKeyRelatedField(
|
||||
@ -844,6 +845,12 @@ class BuildAutoAllocationSerializer(serializers.Serializer):
|
||||
help_text=_('Allow allocation of substitute parts'),
|
||||
)
|
||||
|
||||
optional_items = serializers.BooleanField(
|
||||
default=False,
|
||||
label=_('Optional Items'),
|
||||
help_text=_('Allocate optional BOM items to build order'),
|
||||
)
|
||||
|
||||
def save(self):
|
||||
"""Perform the auto-allocation step"""
|
||||
data = self.validated_data
|
||||
@ -855,6 +862,7 @@ class BuildAutoAllocationSerializer(serializers.Serializer):
|
||||
exclude_location=data.get('exclude_location', None),
|
||||
interchangeable=data['interchangeable'],
|
||||
substitutes=data['substitutes'],
|
||||
optional_items=data['optional_items'],
|
||||
)
|
||||
|
||||
|
||||
|
@ -82,7 +82,8 @@ class BuildTestBase(TestCase):
|
||||
self.bom_item_2 = BomItem.objects.create(
|
||||
part=self.assembly,
|
||||
sub_part=self.sub_part_2,
|
||||
quantity=3
|
||||
quantity=3,
|
||||
optional=True
|
||||
)
|
||||
|
||||
# sub_part_3 is trackable!
|
||||
@ -626,6 +627,7 @@ class AutoAllocationTests(BuildTestBase):
|
||||
self.build.auto_allocate_stock(
|
||||
interchangeable=True,
|
||||
substitutes=False,
|
||||
optional_items=True,
|
||||
)
|
||||
|
||||
self.assertFalse(self.build.are_untracked_parts_allocated())
|
||||
@ -646,17 +648,18 @@ class AutoAllocationTests(BuildTestBase):
|
||||
|
||||
# self.assertEqual(self.build.allocated_stock.count(), 8)
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_1), 0)
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_2), 0)
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_2), 5.0)
|
||||
|
||||
self.assertTrue(self.build.is_bom_item_allocated(self.bom_item_1))
|
||||
self.assertTrue(self.build.is_bom_item_allocated(self.bom_item_2))
|
||||
self.assertFalse(self.build.is_bom_item_allocated(self.bom_item_2))
|
||||
|
||||
def test_fully_auto(self):
|
||||
"""We should be able to auto-allocate against a build in a single go"""
|
||||
|
||||
self.build.auto_allocate_stock(
|
||||
interchangeable=True,
|
||||
substitutes=True
|
||||
substitutes=True,
|
||||
optional_items=True,
|
||||
)
|
||||
|
||||
self.assertTrue(self.build.are_untracked_parts_allocated())
|
||||
|
@ -2422,6 +2422,9 @@ function autoAllocateStockToBuild(build_id, bom_items=[], options={}) {
|
||||
substitutes: {
|
||||
value: true,
|
||||
},
|
||||
optional_items: {
|
||||
value: false,
|
||||
},
|
||||
};
|
||||
|
||||
constructForm(`/api/build/${build_id}/auto-allocate/`, {
|
||||
|
Loading…
Reference in New Issue
Block a user