diff --git a/InvenTree/build/forms.py b/InvenTree/build/forms.py index d46138cd09..57c31ff1db 100644 --- a/InvenTree/build/forms.py +++ b/InvenTree/build/forms.py @@ -27,10 +27,10 @@ class EditBuildForm(HelperForm): ] -class AutoAllocateBuildForm(HelperForm): +class ConfirmBuildForm(HelperForm): """ Form for auto-allocation of stock to a build """ - confirm = forms.BooleanField(required=False, help_text='Confirm stock allocation') + confirm = forms.BooleanField(required=False, help_text='Confirm') class Meta: model = Build diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 2c9077f3d7..0b658dee1a 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -165,6 +165,12 @@ class Build(models.Model): return allocations + @transaction.atomic + def unallocateStock(self): + """ Deletes all stock allocations for this build. """ + + BuildItem.objects.filter(build=self.id).delete() + @transaction.atomic def autoAllocate(self): """ Run auto-allocation routine to allocate StockItems to this Build. diff --git a/InvenTree/build/templates/build/allocate.html b/InvenTree/build/templates/build/allocate.html index b3d7dd1009..c58bc39b49 100644 --- a/InvenTree/build/templates/build/allocate.html +++ b/InvenTree/build/templates/build/allocate.html @@ -19,7 +19,8 @@ InvenTree | Allocate Parts
- + +
@@ -74,4 +75,13 @@ InvenTree | Allocate Parts ); }); + $('#unallocate-build').on('click', function() { + launchModalForm( + "{% url 'build-unallocate' build.id %}", + { + reload: true, + } + ); + }); + {% endblock %} diff --git a/InvenTree/build/templates/build/unallocate.html b/InvenTree/build/templates/build/unallocate.html new file mode 100644 index 0000000000..503bc354f6 --- /dev/null +++ b/InvenTree/build/templates/build/unallocate.html @@ -0,0 +1,9 @@ +{% extends "modal_form.html" %} + +{% block pre_form_content %} + +{{ block.super }} + +Are you sure you wish to unallocate all stock for this build? + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/build/urls.py b/InvenTree/build/urls.py index ed0ee63289..3118bd6042 100644 --- a/InvenTree/build/urls.py +++ b/InvenTree/build/urls.py @@ -22,6 +22,7 @@ build_detail_urls = [ url(r'^cancel/?', views.BuildCancel.as_view(), name='build-cancel'), url(r'^complete/?', views.BuildComplete.as_view(), name='build-complete'), url(r'^auto-allocate/?', views.BuildAutoAllocate.as_view(), name='build-auto-allocate'), + url(r'^unallocate/', views.BuildUnallocate.as_view(), name='build-unallocate'), url(r'^.*$', views.BuildDetail.as_view(), name='build-detail'), ] diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 6575854704..79e3819df5 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -12,7 +12,7 @@ from django.forms import HiddenInput from part.models import Part from .models import Build, BuildItem -from .forms import EditBuildForm, EditBuildItemForm, CompleteBuildForm, AutoAllocateBuildForm +from . import forms from stock.models import StockLocation, StockItem from InvenTree.views import AjaxView, AjaxUpdateView, AjaxCreateView, AjaxDeleteView @@ -75,7 +75,7 @@ class BuildAutoAllocate(AjaxUpdateView): """ model = Build - form_class = AutoAllocateBuildForm + form_class = forms.ConfirmBuildForm context_object_name = 'build' ajax_form_title = 'Allocate Stock' ajax_template_name = 'build/auto_allocate.html' @@ -122,6 +122,40 @@ class BuildAutoAllocate(AjaxUpdateView): return self.renderJsonResponse(request, form, data, context=self.get_context_data()) +class BuildUnallocate(AjaxUpdateView): + """ View to un-allocate all parts from a build. + + Provides a simple confirmation dialog with a BooleanField checkbox. + """ + + model = Build + form_class = forms.ConfirmBuildForm + ajax_form_title = "Unallocate Stock" + ajax_template_name = "build/unallocate.html" + + def post(self, request, *args, **kwargs): + + build = self.get_object() + form = self.get_form() + + confirm = request.POST.get('confirm', False) + + 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() + valid = True + + data = { + 'form_valid': valid, + } + + return self.renderJsonResponse(request, form, data) + + class BuildComplete(AjaxUpdateView): """ View to mark a build as Complete. @@ -131,7 +165,7 @@ class BuildComplete(AjaxUpdateView): """ model = Build - form_class = CompleteBuildForm + form_class = forms.CompleteBuildForm context_object_name = "build" ajax_form_title = "Complete Build" ajax_template_name = "build/complete.html" @@ -248,7 +282,7 @@ class BuildCreate(AjaxCreateView): """ View to create a new Build object """ model = Build context_object_name = 'build' - form_class = EditBuildForm + form_class = forms.EditBuildForm ajax_form_title = 'Start new Build' ajax_template_name = 'modal_form.html' @@ -280,7 +314,7 @@ class BuildUpdate(AjaxUpdateView): """ View for editing a Build object """ model = Build - form_class = EditBuildForm + form_class = forms.EditBuildForm context_object_name = 'build' ajax_form_title = 'Edit Build Details' ajax_template_name = 'modal_form.html' @@ -311,7 +345,7 @@ class BuildItemCreate(AjaxCreateView): """ View for allocating a new part to a build """ model = BuildItem - form_class = EditBuildItemForm + form_class = forms.EditBuildItemForm ajax_template_name = 'modal_form.html' ajax_form_title = 'Allocate new Part' @@ -397,7 +431,7 @@ class BuildItemEdit(AjaxUpdateView): model = BuildItem ajax_template_name = 'modal_form.html' - form_class = EditBuildItemForm + form_class = forms.EditBuildItemForm ajax_form_title = 'Edit Stock Allocation' def get_data(self):