diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index b4509446f6..ad4b810e32 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -34,6 +34,10 @@ class HelperForm(forms.ModelForm): Simply create a 'blank' layout for each available field. """ + self.rebuild_layout() + + def rebuild_layout(self): + layouts = [] for field in self.fields: diff --git a/InvenTree/build/forms.py b/InvenTree/build/forms.py index d9f497da4a..f7a91464d5 100644 --- a/InvenTree/build/forms.py +++ b/InvenTree/build/forms.py @@ -46,6 +46,13 @@ class ConfirmBuildForm(HelperForm): class CompleteBuildForm(HelperForm): """ Form for marking a Build as complete """ + field_prefix = { + 'serial_numbers': 'fa-hashtag', + } + + field_placeholder = { + } + location = forms.ModelChoiceField( queryset=StockLocation.objects.all(), help_text='Location of completed parts', diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 54094632c1..e75fc88946 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -53,6 +53,19 @@ class Build(MPTTModel): def get_absolute_url(self): return reverse('build-detail', kwargs={'pk': self.id}) + def clean(self): + """ + Validation for Build object. + """ + + super().clean() + + if self.part.trackable: + if not self.quantity == int(self.quantity): + raise ValidationError({ + 'quantity': _("Build quantity must be integer value for trackable parts") + }) + title = models.CharField( verbose_name=_('Build Title'), blank=False, diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 96eb602f2b..6ef455aa70 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -196,6 +196,20 @@ class BuildComplete(AjaxUpdateView): if not build.part.trackable: form.fields.pop('serial_numbers') + else: + sn = build.part.getNextSerialNumber() + + if build.quantity > 1: + sn = "{n}-{m}".format( + n=str(sn), + m=str(sn+build.quantity-1) + ) + else: + sn = str(sn) + + form.field_placeholder['serial_numbers'] = sn + + form.rebuild_layout() return form @@ -208,6 +222,7 @@ class BuildComplete(AjaxUpdateView): initials = super(BuildComplete, self).get_initial().copy() build = self.get_object() + if build.part.default_location is not None: try: location = StockLocation.objects.get(pk=build.part.default_location.id) diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 6493a9d381..b096f2a24f 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -876,6 +876,8 @@ class StockItemCreate(AjaxCreateView): sn = part.getNextSerialNumber() form.field_placeholder['serial_numbers'] = _('Next available serial number is') + ' ' + str(sn) + form.rebuild_layout() + # Hide the 'part' field (as a valid part is selected) form.fields['part'].widget = HiddenInput() @@ -998,6 +1000,8 @@ class StockItemCreate(AjaxCreateView): sn = part.getNextSerialNumber() form.field_placeholder['serial_numbers'] = _("Next available serial number is") + " " + str(sn) + form.rebuild_layout() + except (Part.DoesNotExist, ValueError, InvalidOperation): part = None quantity = 1