Merge branch 'feature-non-int-serial' of git://github.com/bcc/InvenTree into bcc-feature-non-int-serial

This commit is contained in:
Oliver Walters 2020-09-01 19:41:48 +10:00
commit e6c0a04131
7 changed files with 54 additions and 28 deletions

View File

@ -371,14 +371,10 @@ def ExtractSerialNumbers(serials, expected_quantity):
continue continue
else: else:
try: if group in numbers:
n = int(group) errors.append(_("Duplicate serial: {g}".format(g=group)))
if n in numbers:
errors.append(_("Duplicate serial: {n}".format(n=n)))
else: else:
numbers.append(n) numbers.append(group)
except ValueError:
errors.append(_("Invalid group: {g}".format(g=group)))
if len(errors) > 0: if len(errors) > 0:
raise ValidationError(errors) raise ValidationError(errors)

View File

@ -220,5 +220,5 @@ class BuildTest(TestCase):
# And a new stock item created for the build output # And a new stock item created for the build output
self.assertEqual(StockItem.objects.get(pk=7).quantity, 1) self.assertEqual(StockItem.objects.get(pk=7).quantity, 1)
self.assertEqual(StockItem.objects.get(pk=7).serial, 1) self.assertEqual(StockItem.objects.get(pk=7).serial, "1")
self.assertEqual(StockItem.objects.get(pk=7).build, self.build) self.assertEqual(StockItem.objects.get(pk=7).build, self.build)

View File

@ -328,13 +328,20 @@ class Part(MPTTModel):
""" """
parts = Part.objects.filter(tree_id=self.tree_id) parts = Part.objects.filter(tree_id=self.tree_id)
stock = StockModels.StockItem.objects.filter(part__in=parts).exclude(serial=None).order_by('-serial') stock = StockModels.StockItem.objects.filter(part__in=parts).exclude(serial=None)
if stock.count() > 0: try:
return stock.first().serial 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.
except ValueError:
return None
# No serial numbers found # No serial numbers found
return None return 0
def getNextSerialNumber(self): def getNextSerialNumber(self):
""" """
@ -344,9 +351,9 @@ class Part(MPTTModel):
n = self.getHighestSerialNumber() n = self.getHighestSerialNumber()
if n is None: if n is None:
return 1 return None
else: else:
return n + 1 return int(n) + 1
def getSerialNumberString(self, quantity): def getSerialNumberString(self, quantity):
""" """
@ -356,6 +363,9 @@ class Part(MPTTModel):
sn = self.getNextSerialNumber() sn = self.getNextSerialNumber()
if sn is None:
return None
if quantity >= 2: if quantity >= 2:
sn = "{n}-{m}".format( sn = "{n}-{m}".format(
n=sn, n=sn,

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.7 on 2020-08-21 14:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('stock', '0049_auto_20200820_0454'),
]
operations = [
migrations.AlterField(
model_name='stockitem',
name='serial',
field=models.CharField(blank=True, help_text='Serial number for this item', max_length=100, null=True, verbose_name='Serial Number'),
),
]

View File

@ -355,9 +355,9 @@ class StockItem(MPTTModel):
verbose_name=_("Customer"), verbose_name=_("Customer"),
) )
serial = models.PositiveIntegerField( serial = models.CharField(
verbose_name=_('Serial Number'), verbose_name=_('Serial Number'),
blank=True, null=True, max_length=100, blank=True, null=True,
help_text=_('Serial number for this item') help_text=_('Serial number for this item')
) )
@ -687,9 +687,6 @@ class StockItem(MPTTModel):
if not type(serials) in [list, tuple]: if not type(serials) in [list, tuple]:
raise ValidationError({"serial_numbers": _("Serial numbers must be a list of integers")}) raise ValidationError({"serial_numbers": _("Serial numbers must be a list of integers")})
if any([type(i) is not int for i in serials]):
raise ValidationError({"serial_numbers": _("Serial numbers must be a list of integers")})
if not quantity == len(serials): if not quantity == len(serials):
raise ValidationError({"quantity": _("Quantity does not match serial numbers")}) raise ValidationError({"quantity": _("Quantity does not match serial numbers")})

View File

@ -113,7 +113,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
allocated = serializers.FloatField(source='allocation_count', required=False) allocated = serializers.FloatField(source='allocation_count', required=False)
serial = serializers.IntegerField(required=False) serial = serializers.CharField(required=False)
required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False) required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False)

View File

@ -295,10 +295,7 @@ class StockTest(TestCase):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
item.serializeStock(-1, [], self.user) item.serializeStock(-1, [], self.user)
# Try invalid serial numbers # Not enough serial numbers for all stock items.
with self.assertRaises(ValidationError):
item.serializeStock(3, [1, 2, 'k'], self.user)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
item.serializeStock(3, "hello", self.user) item.serializeStock(3, "hello", self.user)
@ -394,8 +391,16 @@ class VariantTest(StockTest):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
item.save() item.save()
# This should pass # Verify items with a non-numeric serial don't offer a next serial.
item.serial = n + 1 item.serial = "string"
item.save()
self.assertEqual(variant.getNextSerialNumber(), None)
# And the same for the range when serializing.
self.assertEqual(variant.getSerialNumberString(5), None)
# This should pass, although not strictly an int field now.
item.serial = int(n) + 1
item.save() item.save()
# Attempt to create the same serial number but for a variant (should fail!) # Attempt to create the same serial number but for a variant (should fail!)