From 8328e7e13c6bd4c1b1624f58385186b21f56b4a4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 20 Jun 2019 21:37:25 +1000 Subject: [PATCH] Improve uniqueness checking for Part --- .../migrations/0010_auto_20190620_2135.py | 19 ++++++++++++++ InvenTree/part/models.py | 26 ++++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 InvenTree/part/migrations/0010_auto_20190620_2135.py diff --git a/InvenTree/part/migrations/0010_auto_20190620_2135.py b/InvenTree/part/migrations/0010_auto_20190620_2135.py new file mode 100644 index 0000000000..2033e2870f --- /dev/null +++ b/InvenTree/part/migrations/0010_auto_20190620_2135.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.2 on 2019-06-20 11:35 + +import InvenTree.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0009_part_virtual'), + ] + + operations = [ + migrations.AlterField( + model_name='part', + name='name', + field=models.CharField(help_text='Part name', max_length=100, validators=[InvenTree.validators.validate_part_name]), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 92acce5026..f77e2d94f4 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -203,6 +203,7 @@ class Part(models.Model): description: Longer form description of the part keywords: Optional keywords for improving part search results IPN: Internal part number (optional) + revision: Part revision is_template: If True, this part is a 'template' part and cannot be instantiated as a StockItem URL: Link to an external page with more information about this part (e.g. internal Wiki) image: Image of this part @@ -260,13 +261,30 @@ class Part(models.Model): return static('/img/blank_image.png') def validate_unique(self, exclude=None): + """ Validate that a part is 'unique'. + Uniqueness is checked across the following (case insensitive) fields: + + * Name + * IPN + * Revision + + e.g. there can exist multiple parts with the same name, but only if + they have a different revision or internal part number. + + """ super().validate_unique(exclude) # Part name uniqueness should be case insensitive try: - if Part.objects.filter(name__iexact=self.name).exclude(id=self.id).exists(): + parts = Part.objects.exclude(id=self.id).filter( + name__iexact=self.name, + IPN__iexact=self.IPN) + + if parts.exists(): + msg = _("Part must be unique for name, IPN and revision") raise ValidationError({ - "name": _("A part with this name already exists") + "name": msg, + "IPN": msg, }) except Part.DoesNotExist: pass @@ -280,8 +298,8 @@ class Part(models.Model): 'variant_of': _("Part cannot be a variant of another part if it is already a template"), }) - name = models.CharField(max_length=100, blank=False, unique=True, - help_text='Part name (must be unique)', + name = models.CharField(max_length=100, blank=False, + help_text='Part name', validators=[validators.validate_part_name] )