mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	Merge branch 'feature-non-int-serial' of git://github.com/bcc/InvenTree into bcc-feature-non-int-serial
This commit is contained in:
		| @@ -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: |             else: | ||||||
|                     errors.append(_("Duplicate serial: {n}".format(n=n))) |                 numbers.append(group) | ||||||
|                 else: |  | ||||||
|                     numbers.append(n) |  | ||||||
|             except ValueError: |  | ||||||
|                 errors.append(_("Invalid group: {g}".format(g=group))) |  | ||||||
|  |  | ||||||
|     if len(errors) > 0: |     if len(errors) > 0: | ||||||
|         raise ValidationError(errors) |         raise ValidationError(errors) | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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: |  | ||||||
|             return stock.first().serial |  | ||||||
|          |          | ||||||
|  |         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. | ||||||
|  |         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, | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								InvenTree/stock/migrations/0050_auto_20200821_1403.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								InvenTree/stock/migrations/0050_auto_20200821_1403.py
									
									
									
									
									
										Normal 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'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -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")}) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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!) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user