From a3265ef9fdec65adf15a08cd78df4b8cf1da31a9 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 24 Oct 2020 13:15:13 +1100 Subject: [PATCH] Unallocate stock against a particular line item --- InvenTree/build/forms.py | 5 ++++ InvenTree/build/models.py | 5 +++- InvenTree/build/views.py | 15 +++++++++- InvenTree/templates/js/build.js | 50 ++++++++++++++++++++++++++++++--- 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/InvenTree/build/forms.py b/InvenTree/build/forms.py index b1df528e08..6f02f2061f 100644 --- a/InvenTree/build/forms.py +++ b/InvenTree/build/forms.py @@ -81,6 +81,11 @@ class UnallocateBuildForm(HelperForm): widget=forms.HiddenInput() ) + part_id = forms.IntegerField( + required=False, + widget=forms.HiddenInput(), + ) + class Meta: model = Build fields = [ diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 7cead39cb8..d462513f9b 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -363,7 +363,7 @@ class Build(MPTTModel): return allocations @transaction.atomic - def unallocateStock(self, output=None): + def unallocateStock(self, output=None, part=None): """ Deletes all stock allocations for this build. @@ -377,6 +377,9 @@ class Build(MPTTModel): if output: allocations = allocations.filter(install_into=output.pk) + if part: + allocations = allocations.filter(stock_item__part=part) + # Remove all the allocations allocations.delete() diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 94d661ef8d..30ea31af58 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -218,6 +218,12 @@ class BuildUnallocate(AjaxUpdateView): if output: initials['output_id'] = output + # Pointing to a particular part? + part = self.get_param('part') + + if part: + initials['part_id'] = part + return initials def post(self, request, *args, **kwargs): @@ -234,13 +240,20 @@ class BuildUnallocate(AjaxUpdateView): except (ValueError, StockItem.DoesNotExist): output = None + part_id = request.POST.get('part_id', None) + + try: + part = Part.objects.get(pk=part_id) + except (ValueError, Part.DoesNotExist): + part = None + valid = False if confirm is False: form.errors['confirm'] = [_('Confirm unallocation of build stock')] form.non_field_errors = [_('Check the confirmation box')] else: - build.unallocateStock(output=output) + build.unallocateStock(output=output, part=part) valid = True data = { diff --git a/InvenTree/templates/js/build.js b/InvenTree/templates/js/build.js index d5ddf68bfa..1c68677768 100644 --- a/InvenTree/templates/js/build.js +++ b/InvenTree/templates/js/build.js @@ -160,6 +160,12 @@ function loadBuildOutputAllocationTable(buildId, partId, output, options={}) { $(table).bootstrapTable('refresh'); } + function requiredQuantity(row) { + // Return the requied quantity for a given row + + return row.quantity * output.quantity; + } + function sumAllocations(row) { // Calculat total allocations for a given row if (!row.allocations) { @@ -185,8 +191,8 @@ function loadBuildOutputAllocationTable(buildId, partId, output, options={}) { var pk = $(this).attr('pk'); // Extract row data from the table - var idx = $(this).closest('tr').attr('data-index'); - var row = $(table).bootstrapTable('getData')[idx]; + //var idx = $(this).closest('tr').attr('data-index'); + //var row = $(table).bootstrapTable('getData')[idx]; // Launch form to allocate new stock against this output launchModalForm("{% url 'build-item-create' %}", { @@ -209,6 +215,36 @@ function loadBuildOutputAllocationTable(buildId, partId, output, options={}) { ] }); }); + + // Callback for 'build' button + $(table).find('.button-build').click(function() { + var pk = $(this).attr('pk'); + + // Launch form to create a new build order + launchModalForm('{% url "build-create" %}', { + follow: true, + data: { + part: pk, + parent: buildId, + quantity: 123, // TODO - Fix this quantity! + } + }); + }); + + // Callback for 'unallocate' button + $(table).find('.button-unallocate').click(function() { + var pk = $(this).attr('pk'); + + launchModalForm(`/build/${buildId}/unallocate/`, + { + success: reloadTable, + data: { + output: outputId, + part: pk, + } + } + ); + }); } // Load table of BOM items @@ -423,6 +459,10 @@ function loadBuildOutputAllocationTable(buildId, partId, output, options={}) { title: '{% trans "Quantity Per" %}', sortable: true, }, + { + field: 'sub_part_detail.stock', + title: '{% trans "Available" %}', + }, { field: 'allocated', title: '{% trans "Allocated" %}', @@ -436,7 +476,7 @@ function loadBuildOutputAllocationTable(buildId, partId, output, options={}) { }); } - var required = row.quantity * output.quantity; + var required = requiredQuantity(row); return makeProgressBar(allocated, required); }, @@ -465,7 +505,7 @@ function loadBuildOutputAllocationTable(buildId, partId, output, options={}) { var html = `
`; if (row.sub_part_detail.assembly) { - html += makeIconButton('fa-tools icon-blue', 'button-build', row.sub_part, '{% trans "Build stock" %}', {disabled: true}); + html += makeIconButton('fa-tools icon-blue', 'button-build', row.sub_part, '{% trans "Build stock" %}'); } if (row.sub_part_detail.purchaseable) { @@ -474,6 +514,8 @@ function loadBuildOutputAllocationTable(buildId, partId, output, options={}) { html += makeIconButton('fa-sign-in-alt icon-green', 'button-add', row.sub_part, '{% trans "Allocate stock" %}'); + html += makeIconButton('fa-times-circle icon-red', 'button-unallocate', row.sub_part, '{% trans "Unallocate stock" %}'); + html += '
'; return html;