mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Add unit tests for the auto_allocate_stock method
This commit is contained in:
parent
71cd6c93d1
commit
0bb0047fcd
@ -826,7 +826,7 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
self.save()
|
||||
|
||||
@transaction.atomic
|
||||
def auto_allocate_stock(self, user, **kwargs):
|
||||
def auto_allocate_stock(self, **kwargs):
|
||||
"""
|
||||
Automatically allocate stock items against this build order,
|
||||
following a number of 'guidelines':
|
||||
@ -847,9 +847,8 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
|
||||
# Get a list of all 'untracked' BOM items
|
||||
for bom_item in self.untracked_bom_items:
|
||||
|
||||
|
||||
variant_parts = bom_item.sub_part.get_descendants(include_self=False)
|
||||
substitute_parts = [p for p in bom_item.substitutes.all()]
|
||||
|
||||
unallocated_quantity = self.unallocated_quantity(bom_item)
|
||||
|
||||
@ -891,7 +890,7 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
return 2
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
||||
available_stock = sorted(available_stock, key=stock_sort)
|
||||
|
||||
if len(available_stock) == 0:
|
||||
|
@ -746,11 +746,9 @@ class BuildAutoAllocationSerializer(serializers.Serializer):
|
||||
|
||||
data = self.validated_data
|
||||
|
||||
request = self.context['request']
|
||||
build = self.context['build']
|
||||
|
||||
build.auto_allocate_stock(
|
||||
request.user,
|
||||
location=data.get('location', None),
|
||||
interchangeable=data['interchangeable'],
|
||||
substitutes=data['substitutes'],
|
||||
|
@ -8,11 +8,11 @@ from django.db.utils import IntegrityError
|
||||
from InvenTree import status_codes as status
|
||||
|
||||
from build.models import Build, BuildItem, get_next_build_number
|
||||
from part.models import Part, BomItem
|
||||
from part.models import Part, BomItem, BomItemSubstitute
|
||||
from stock.models import StockItem
|
||||
|
||||
|
||||
class BuildTest(TestCase):
|
||||
class BuildTestBase(TestCase):
|
||||
"""
|
||||
Run some tests to ensure that the Build model is working properly.
|
||||
"""
|
||||
@ -107,13 +107,20 @@ class BuildTest(TestCase):
|
||||
)
|
||||
|
||||
# Create some stock items to assign to the build
|
||||
self.stock_1_1 = StockItem.objects.create(part=self.sub_part_1, quantity=1000)
|
||||
self.stock_1_1 = StockItem.objects.create(part=self.sub_part_1, quantity=3)
|
||||
self.stock_1_2 = StockItem.objects.create(part=self.sub_part_1, quantity=100)
|
||||
|
||||
self.stock_2_1 = StockItem.objects.create(part=self.sub_part_2, quantity=5000)
|
||||
self.stock_2_1 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_2 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_2 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_2 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_2 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
|
||||
self.stock_3_1 = StockItem.objects.create(part=self.sub_part_3, quantity=1000)
|
||||
|
||||
|
||||
class BuildTest(BuildTestBase):
|
||||
|
||||
def test_ref_int(self):
|
||||
"""
|
||||
Test the "integer reference" field used for natural sorting
|
||||
@ -369,3 +376,108 @@ class BuildTest(TestCase):
|
||||
|
||||
for output in outputs:
|
||||
self.assertFalse(output.is_building)
|
||||
|
||||
|
||||
class AutoAllocationTests(BuildTestBase):
|
||||
"""
|
||||
Tests for auto allocating stock against a build order
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
|
||||
super().setUp()
|
||||
|
||||
# Add a "substitute" part for bom_item_2
|
||||
alt_part = Part.objects.create(
|
||||
name="alt part",
|
||||
description="An alternative part!",
|
||||
component=True,
|
||||
)
|
||||
|
||||
BomItemSubstitute.objects.create(
|
||||
bom_item=self.bom_item_2,
|
||||
part=alt_part,
|
||||
)
|
||||
|
||||
StockItem.objects.create(
|
||||
part=alt_part,
|
||||
quantity=500,
|
||||
)
|
||||
|
||||
def test_auto_allocate(self):
|
||||
"""
|
||||
Run the 'auto-allocate' function. What do we expect to happen?
|
||||
|
||||
There are two "untracked" parts:
|
||||
- sub_part_1 (quantity 5 per BOM = 50 required total) / 103 in stock (2 items)
|
||||
- sub_part_2 (quantity 3 per BOM = 30 required total) / 25 in stock (5 items)
|
||||
|
||||
A "fully auto" allocation should allocate *all* of these stock items to the build
|
||||
"""
|
||||
|
||||
# No build item allocations have been made against the build
|
||||
self.assertEqual(self.build.allocated_stock.count(), 0)
|
||||
|
||||
self.assertFalse(self.build.are_untracked_parts_allocated())
|
||||
|
||||
# Stock is not interchangeable, nothing will happen
|
||||
self.build.auto_allocate_stock(
|
||||
interchangeable=False,
|
||||
substitutes=False,
|
||||
)
|
||||
|
||||
self.assertFalse(self.build.are_untracked_parts_allocated())
|
||||
|
||||
self.assertEqual(self.build.allocated_stock.count(), 0)
|
||||
|
||||
self.assertFalse(self.build.is_bom_item_allocated(self.bom_item_1))
|
||||
self.assertFalse(self.build.is_bom_item_allocated(self.bom_item_2))
|
||||
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_1), 50)
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_2), 30)
|
||||
|
||||
# This time we expect stock to be allocated!
|
||||
self.build.auto_allocate_stock(
|
||||
interchangeable=True,
|
||||
substitutes=False,
|
||||
)
|
||||
|
||||
self.assertFalse(self.build.are_untracked_parts_allocated())
|
||||
|
||||
self.assertEqual(self.build.allocated_stock.count(), 7)
|
||||
|
||||
self.assertTrue(self.build.is_bom_item_allocated(self.bom_item_1))
|
||||
self.assertFalse(self.build.is_bom_item_allocated(self.bom_item_2))
|
||||
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_1), 0)
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_2), 5)
|
||||
|
||||
# This time, allow substitue parts to be used!
|
||||
self.build.auto_allocate_stock(
|
||||
interchangeable=True,
|
||||
substitutes=True,
|
||||
)
|
||||
|
||||
# self.assertTrue(self.build.are_untracked_parts_allocated())
|
||||
|
||||
# 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.assertTrue(self.build.is_bom_item_allocated(self.bom_item_1))
|
||||
self.assertTrue(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
|
||||
)
|
||||
|
||||
self.assertTrue(self.build.are_untracked_parts_allocated())
|
||||
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_1), 0)
|
||||
self.assertEqual(self.build.unallocated_quantity(self.bom_item_2), 0)
|
||||
|
Loading…
Reference in New Issue
Block a user