diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 70af651686..2abcecdc5f 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -273,6 +273,55 @@ class StockItem(MPTTModel): self.serial_int = serial_int + def get_next_serial_number(self, include_variants=True, reverse=False): + """ + Get the "next" serial number for the part this stock item references. + + e.g. if this stock item has a serial number 100, we may return the stock item with serial number 101 + + Note that this only works for "serialized" stock items with integer values + + Args: + include_variants: True if we wish to include stock for variant parts + reverse: True if we want to return the "previous" (lower) serial number + + Returns: + A StockItem object matching the requirements, or None + + """ + + if not self.serialized: + return None + + # Find only serialized stock items + items = StockItem.objects.exclude(serial=None).exclude(serial='') + + if include_variants: + # Match against any part within the variant tree + items = items.filter(part__tree_id=self.part.tree_id) + else: + # Match only against the specific part + items = items.filter(part=self.part) + + serial = self.serial_int + + if reverse: + # Select only stock items with lower serial numbers, in decreasing order + items = items.filter(serial_int__lt=serial) + items = items.order_by('-serial_int') + else: + # Select only stock items with higher serial numbers, in increasing order + items = items.filter(serial_int__gt=serial) + items = items.order_by('serial_int') + + if items.count() > 0: + item = items.first() + + if item.serialized: + return item + + return None + def save(self, *args, **kwargs): """ Save this StockItem to the database. Performs a number of checks: diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 95cb498739..71dc592080 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -101,43 +101,16 @@ class StockItemDetail(InvenTreeRoleMixin, DetailView): model = StockItem def get_context_data(self, **kwargs): - """ add previous and next item """ + """ + Add information on the "next" and "previous" StockItem objects, + based on the serial numbers. + """ + data = super().get_context_data(**kwargs) if self.object.serialized: - - serial_elem = {} - - try: - current = int(self.object.serial) - - for item in self.object.part.stock_items.all(): - - if item.serialized: - try: - sn = int(item.serial) - serial_elem[sn] = item - except ValueError: - # We only support integer serial number progression - pass - - serials = serial_elem.keys() - - # previous - for nbr in range(current - 1, min(serials), -1): - if nbr in serials: - data['previous'] = serial_elem.get(nbr, None) - break - - # next - for nbr in range(current + 1, max(serials) + 1): - if nbr in serials: - data['next'] = serial_elem.get(nbr, None) - break - - except ValueError: - # We only support integer serial number progression - pass + data['previous'] = self.object.get_next_serial_number(reverse=True) + data['next'] = self.object.get_next_serial_number() data['ownership_enabled'] = common.models.InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL') data['item_owner'] = self.object.get_item_owner()