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