diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 2124207c7d..88dc66085f 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -197,12 +197,8 @@ class BuildComplete(AjaxUpdateView): if not build.part.trackable: form.fields.pop('serial_numbers') else: - if build.quantity == 1: - text = _('Next available serial number is') - else: - text = _('Next available serial numbers are') - form.field_placeholder['serial_numbers'] = text + " " + build.part.getSerialNumberString(build.quantity) + form.field_placeholder['serial_numbers'] = build.part.getSerialNumberString(build.quantity) form.rebuild_layout() diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 0d19a0afb9..6190c9b4f0 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -319,9 +319,12 @@ class Part(MPTTModel): return stock.exists() - def getHighestSerialNumber(self): + def getLatestSerialNumber(self): """ - Return the highest serial number for this Part. + Return the "latest" serial number for this Part. + + If *all* the serial numbers are integers, then this will return the highest one. + Otherwise, it will simply return the serial number most recently added. Note: Serial numbers must be unique across an entire Part "tree", so we filter by the entire tree. @@ -330,51 +333,61 @@ class Part(MPTTModel): parts = Part.objects.filter(tree_id=self.tree_id) stock = StockModels.StockItem.objects.filter(part__in=parts).exclude(serial=None) + # There are no matchin StockItem objects (skip further tests) + if not stock.exists(): + return None + + # Attempt to coerce the returned serial numbers to integers + # If *any* are not integers, fail! try: ordered = sorted(stock.all(), reverse=True, key=lambda n: int(n.serial)) if len(ordered) > 0: return ordered[0].serial - # Non-numeric serials, so don't suggest one. + # One or more of the serial numbers was non-numeric + # In this case, the "best" we can do is return the most recent except ValueError: - return None + return stock.last().serial # No serial numbers found - return 0 + return None - def getNextSerialNumber(self): - """ - Return the next-available serial number for this Part. - """ - - n = self.getHighestSerialNumber() - - if n is None: - return None - else: - return int(n) + 1 - - def getSerialNumberString(self, quantity): + def getSerialNumberString(self, quantity=1): """ Return a formatted string representing the next available serial numbers, given a certain quantity of items. """ - sn = self.getNextSerialNumber() + latest = self.getLatestSerialNumber() - if sn is None: - return None + quantity = int(quantity) + + # No serial numbers can be found, assume 1 as the first serial + if latest is None: + latest = 0 + + # Attempt to turn into an integer + try: + latest = int(latest) + except: + pass + + if type(latest) is int: + + if quantity >= 2: + text = '{n} - {m}'.format(n=latest+1, m=latest+1+quantity) + + return _('Next available serial numbers are') + ' ' + text + else: + text = str(latest) + + return _('Next available serial number is') + ' ' + text - if quantity >= 2: - sn = "{n}-{m}".format( - n=sn, - m=int(sn + quantity - 1) - ) else: - sn = str(sn) + # Non-integer values, no option but to return latest - return sn + return _('Most recent serial number is') + ' ' + str(latest) @property def full_name(self): diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 18970fe373..eee68c6d6d 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -36,8 +36,14 @@ {% if part.trackable %}