mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Build Order Updates (#4855)
* Add new BuildLine model - Represents an instance of a BOM item against a BuildOrder * Create BuildLine instances automatically When a new Build is created, automatically generate new BuildLine items * Improve logic for handling exchange rate backends * logic fixes * Adds API endpoints Add list and detail API endpoints for new BuildLine model * update users/models.py - Add new model to roles definition * bulk-create on auto_allocate Save database hits by performing a bulk-create * Add skeleton data migration * Create BuildLines for existing orders * Working on building out BuildLine table * Adds link for "BuildLine" to "BuildItem" - A "BuildItem" will now be tracked against a BuildLine - Not tracked directly against a build - Not tracked directly against a BomItem - Add schema migration - Add data migration to update links * Adjust migration 0045 - bom_item and build fields are about to be removed - Set them to "nullable" so the data doesn't get removed * Remove old fields from BuildItem model - build fk - bom_item fk - A lot of other required changes too * Update BuildLine.bom_item field - Delete the BuildLine if the BomItem is removed - This is closer to current behaviour * Cleanup for Build model - tracked_bom_items -> tracked_line_items - untracked_bom_items -> tracked_bom_items - remove build.can_complete - move bom_item specific methods to the BuildLine model - Cleanup / consolidation * front-end work - Update javascript - Cleanup HTML templates * Add serializer annotation and filtering - Annotate 'allocated' quantity - Filter by allocated / trackable / optional / consumable * Make table sortable * Add buttons * Add callback for building new stock * Fix Part annotation * Adds callback to order parts * Allocation works again * template cleanup * Fix allocate / unallocate actions - Also turns out "unallocate" is not a word.. * auto-allocate works again * Fix call to build.is_over_allocated * Refactoring updates * Bump API version * Cleaner implementation of allocation sub-table * Fix rendering in build output table * Improvements to StockItem list API - Refactor very old code - Add option to include test results to queryset * Add TODO for later me * Fix for serializers.py * Working on cleaner implementation of build output table * Add function to determine if a single output is fully allocated * Updates to build.js - Button callbacks - Table rendering * Revert previous changes to build.serializers.py * Fix for forms.js * Rearrange code in build.js * Rebuild "allocated lines" for output table * Fix allocation calculation * Show or hide column for tracked parts * Improve debug messages * Refactor "loadBuildLineTable" - Allow it to also be used as output sub-table * Refactor "completed tests" column * Remove old javascript - Cleans up a *lot* of crusty old code * Annotate the available stock quantity to BuildLine serializer - Similar pattern to BomItem serializer - Needs refactoring in the future * Update available column * Fix build allocation table - Bug fix - Make pretty * linting fixes * Allow sorting by available stock * Tweak for "required tests" column * Bug fix for completing a build output * Fix for consumable stock * Fix for trim_allocated_stock * Fix for creating new build * Migration fix - Ensure initial django_q migrations are applied - Why on earth is this failing now? * Catch exception * Update for exception handling * Update migrations - Ensure inventreesetting is added * Catch all exceptions when getting default currency code * Bug fix for currency exchange rates update * Working on unit tests * Unit test fixes * More work on unit tests * Use bulk_create in unit test * Update required quantity when a BuildOrder is saved * Tweak overage display in BOM table * Fix icon in BOM table * Fix spelling error * More unit test fixes * Build reports - Add line_items - Update docs - Cleanup * Reimplement is_partially_allocated method * Update docs about overage * Unit testing for data migration * Add "required_for_build_orders" annotation - Makes API query *much* faster now - remove old "required_parts_to_complete_build" method - Cleanup part API filter code * Adjust order of fixture loading * Fix unit test * Prevent "schedule_pricing_update" in unit tests - Should cut down on DB hits significantly * Unit test updates * Improvements for unit test - Don't hard-code pk values - postgresql no likey * Better unit test
This commit is contained in:
@ -582,6 +582,9 @@ class BuildAllocationTest(BuildAPITest):
|
||||
|
||||
self.build = Build.objects.get(pk=1)
|
||||
|
||||
# Regenerate BuildLine objects
|
||||
self.build.create_build_line_items()
|
||||
|
||||
# Record number of build items which exist at the start of each test
|
||||
self.n = BuildItem.objects.count()
|
||||
|
||||
@ -593,7 +596,7 @@ class BuildAllocationTest(BuildAPITest):
|
||||
self.assertEqual(self.build.part.bom_items.count(), 4)
|
||||
|
||||
# No items yet allocated to this build
|
||||
self.assertEqual(self.build.allocated_stock.count(), 0)
|
||||
self.assertEqual(BuildItem.objects.filter(build_line__build=self.build).count(), 0)
|
||||
|
||||
def test_get(self):
|
||||
"""A GET request to the endpoint should return an error."""
|
||||
@ -634,7 +637,7 @@ class BuildAllocationTest(BuildAPITest):
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"bom_item": 1, # M2x4 LPHS
|
||||
"build_line": 1, # M2x4 LPHS
|
||||
"stock_item": 2, # 5,000 screws available
|
||||
}
|
||||
]
|
||||
@ -658,7 +661,7 @@ class BuildAllocationTest(BuildAPITest):
|
||||
expected_code=400
|
||||
).data
|
||||
|
||||
self.assertIn("This field is required", str(data["items"][0]["bom_item"]))
|
||||
self.assertIn("This field is required", str(data["items"][0]["build_line"]))
|
||||
|
||||
# Missing stock_item
|
||||
data = self.post(
|
||||
@ -666,7 +669,7 @@ class BuildAllocationTest(BuildAPITest):
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"bom_item": 1,
|
||||
"build_line": 1,
|
||||
"quantity": 5000,
|
||||
}
|
||||
]
|
||||
@ -681,12 +684,25 @@ class BuildAllocationTest(BuildAPITest):
|
||||
|
||||
def test_invalid_bom_item(self):
|
||||
"""Test by passing an invalid BOM item."""
|
||||
|
||||
# Find the right (in this case, wrong) BuildLine instance
|
||||
|
||||
si = StockItem.objects.get(pk=11)
|
||||
lines = self.build.build_lines.all()
|
||||
|
||||
wrong_line = None
|
||||
|
||||
for line in lines:
|
||||
if line.bom_item.sub_part.pk != si.pk:
|
||||
wrong_line = line
|
||||
break
|
||||
|
||||
data = self.post(
|
||||
self.url,
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"bom_item": 5,
|
||||
"build_line": wrong_line.pk,
|
||||
"stock_item": 11,
|
||||
"quantity": 500,
|
||||
}
|
||||
@ -695,19 +711,31 @@ class BuildAllocationTest(BuildAPITest):
|
||||
expected_code=400
|
||||
).data
|
||||
|
||||
self.assertIn('must point to the same part', str(data))
|
||||
self.assertIn('Selected stock item does not match BOM line', str(data))
|
||||
|
||||
def test_valid_data(self):
|
||||
"""Test with valid data.
|
||||
|
||||
This should result in creation of a new BuildItem object
|
||||
"""
|
||||
|
||||
# Find the correct BuildLine
|
||||
si = StockItem.objects.get(pk=2)
|
||||
|
||||
right_line = None
|
||||
|
||||
for line in self.build.build_lines.all():
|
||||
|
||||
if line.bom_item.sub_part.pk == si.part.pk:
|
||||
right_line = line
|
||||
break
|
||||
|
||||
self.post(
|
||||
self.url,
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"bom_item": 1,
|
||||
"build_line": right_line.pk,
|
||||
"stock_item": 2,
|
||||
"quantity": 5000,
|
||||
}
|
||||
@ -749,16 +777,22 @@ class BuildOverallocationTest(BuildAPITest):
|
||||
cls.state = {}
|
||||
cls.allocation = {}
|
||||
|
||||
for i, bi in enumerate(cls.build.part.bom_items.all()):
|
||||
rq = cls.build.required_quantity(bi, None) + i + 1
|
||||
si = StockItem.objects.filter(part=bi.sub_part, quantity__gte=rq).first()
|
||||
items_to_create = []
|
||||
|
||||
cls.state[bi.sub_part] = (si, si.quantity, rq)
|
||||
BuildItem.objects.create(
|
||||
build=cls.build,
|
||||
for idx, build_line in enumerate(cls.build.build_lines.all()):
|
||||
required = build_line.quantity + idx + 1
|
||||
sub_part = build_line.bom_item.sub_part
|
||||
si = StockItem.objects.filter(part=sub_part, quantity__gte=required).first()
|
||||
|
||||
cls.state[sub_part] = (si, si.quantity, required)
|
||||
|
||||
items_to_create.append(BuildItem(
|
||||
build_line=build_line,
|
||||
stock_item=si,
|
||||
quantity=rq,
|
||||
)
|
||||
quantity=required,
|
||||
))
|
||||
|
||||
BuildItem.objects.bulk_create(items_to_create)
|
||||
|
||||
# create and complete outputs
|
||||
cls.build.create_build_output(cls.build.quantity)
|
||||
@ -822,9 +856,10 @@ class BuildOverallocationTest(BuildAPITest):
|
||||
self.assertTrue(self.build.is_complete)
|
||||
|
||||
# Check stock items have reduced only by bom requirement (overallocation trimmed)
|
||||
for bi in self.build.part.bom_items.all():
|
||||
si, oq, _ = self.state[bi.sub_part]
|
||||
rq = self.build.required_quantity(bi, None)
|
||||
for line in self.build.build_lines.all():
|
||||
|
||||
si, oq, _ = self.state[line.bom_item.sub_part]
|
||||
rq = line.quantity
|
||||
si.refresh_from_db()
|
||||
self.assertEqual(si.quantity, oq - rq)
|
||||
|
||||
|
Reference in New Issue
Block a user