Auto-generate build outputs when a build is created

This commit is contained in:
Oliver Walters 2020-10-27 23:09:17 +11:00
parent 170d55d64e
commit 22a5f921b8
4 changed files with 88 additions and 12 deletions

View File

@ -387,7 +387,7 @@ class AjaxCreateView(AjaxMixin, CreateView):
self.pre_save(self.form, request)
self.object = self.form.save()
self.post_save(new_object=self.object, request=request)
self.post_save(new_object=self.object, request=request, form=self.form, data=self.form.cleaned_data)
# Return the PK of the newly-created object
data['pk'] = self.object.pk

View File

@ -23,6 +23,7 @@ class EditBuildForm(HelperForm):
'reference': 'BO',
'link': 'fa-link',
'batch': 'fa-layer-group',
'serial-numbers': 'fa-hashtag',
'location': 'fa-map-marker-alt',
}
@ -30,6 +31,12 @@ class EditBuildForm(HelperForm):
'reference': _('Build Order reference')
}
serial_numbers = forms.CharField(
label=_('Serial Numbers'),
help_text=_('Serial numbers for build outputs'),
required=False,
)
class Meta:
model = Build
fields = [
@ -38,6 +45,7 @@ class EditBuildForm(HelperForm):
'part',
'quantity',
'batch',
'serial_numbers',
'take_from',
'destination',
'parent',

View File

@ -24,6 +24,7 @@ from mptt.models import MPTTModel, TreeForeignKey
from InvenTree.status_codes import BuildStatus
from InvenTree.helpers import increment, getSetting, normalize
from InvenTree.helpers import ExtractSerialNumbers
from InvenTree.validators import validate_build_order_reference
from InvenTree.models import InvenTreeAttachment
@ -269,21 +270,46 @@ class Build(MPTTModel):
return new_ref
def createInitialStockItem(self, user):
def createInitialStockItem(self, serial_numbers, user):
"""
Create an initial output StockItem to be completed by this build.
"""
output = StockModels.StockItem.objects.create(
part=self.part, # Link to the parent part
location=None, # No location (yet) until it is completed
quantity=self.quantity,
batch='', # The 'batch' code is not set until the item is completed
build=self, # Point back to this build
is_building=True, # Mark this StockItem as building
)
if self.part.trackable:
# Trackable part? Create individual build outputs?
output.save()
# Serial numbers specified for the build?
if serial_numbers:
serials = ExtractSerialNumbers(serial_numbers, self.quantity)
else:
serials = [None] * self.quantity
for serial in serials:
output = StockModels.StockItem.objects.create(
part=self.part,
location=self.destination,
quantity=1,
batch=self.batch,
serial=serial,
build=self,
is_building=True
)
output.save()
else:
# Create a single build output
output = StockModels.StockItem.objects.create(
part=self.part, # Link to the parent part
location=None, # No location (yet) until it is completed
quantity=self.quantity,
batch='', # The 'batch' code is not set until the item is completed
build=self, # Point back to this build
is_building=True, # Mark this StockItem as building
)
output.save()
# TODO - Add a transaction note to the new StockItem

View File

@ -512,6 +512,18 @@ class BuildCreate(AjaxCreateView):
ajax_template_name = 'modal_form.html'
role_required = 'build.add'
def get_form(self):
form = super().get_form()
if form['part'].value():
part = Part.objects.get(pk=form['part'].value())
# Part is not trackable - hide serial numbers
if not part.trackable:
form.fields['serial_numbers'].widget = HiddenInput()
return form
def get_initial(self):
""" Get initial parameters for Build creation.
@ -547,6 +559,33 @@ class BuildCreate(AjaxCreateView):
return {
'success': _('Created new build'),
}
def validate(self, cleaned_data, **kwargs):
"""
Perform extra form validation.
- If part is trackable, check that either batch or serial numbers are calculated
By this point form.is_valid() has been executed
"""
part = cleaned_data['part']
if part.trackable:
# For a trackable part, either batch or serial nubmber must be specified
if not cleaned_data['batch'] and not cleaned_data['serial_numbers']:
raise ValidationError({
'part': _('Trackable part must have either batch or serial number specified')
})
# If serial numbers are set...
serials = cleaned_data['serial_numbers']
quantity = cleaned_data['quantity']
extracted = ExtractSerialNumbers(serials, quantity)
# Ok, no errors...
return True
def post_save(self, **kwargs):
"""
@ -555,8 +594,11 @@ class BuildCreate(AjaxCreateView):
build = kwargs['new_object']
request = kwargs['request']
data = kwargs['data']
serials = data['serial_numbers']
build.createInitialStockItem(request.user)
build.createInitialStockItem(serials, request.user)
class BuildUpdate(AjaxUpdateView):