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:
Oliver 2022-12-21 21:22:59 +11:00 committed by GitHub
parent d9e99e38d2
commit 0e8563ebee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 4 deletions

View File

@ -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)

View File

@ -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'],
)

View File

@ -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())

View File

@ -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/`, {