mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Improve uniqueness checking for Part
This commit is contained in:
parent
b71d5b474a
commit
8328e7e13c
19
InvenTree/part/migrations/0010_auto_20190620_2135.py
Normal file
19
InvenTree/part/migrations/0010_auto_20190620_2135.py
Normal file
@ -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]),
|
||||||
|
),
|
||||||
|
]
|
@ -203,6 +203,7 @@ class Part(models.Model):
|
|||||||
description: Longer form description of the part
|
description: Longer form description of the part
|
||||||
keywords: Optional keywords for improving part search results
|
keywords: Optional keywords for improving part search results
|
||||||
IPN: Internal part number (optional)
|
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
|
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)
|
URL: Link to an external page with more information about this part (e.g. internal Wiki)
|
||||||
image: Image of this part
|
image: Image of this part
|
||||||
@ -260,13 +261,30 @@ class Part(models.Model):
|
|||||||
return static('/img/blank_image.png')
|
return static('/img/blank_image.png')
|
||||||
|
|
||||||
def validate_unique(self, exclude=None):
|
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)
|
super().validate_unique(exclude)
|
||||||
|
|
||||||
# Part name uniqueness should be case insensitive
|
# Part name uniqueness should be case insensitive
|
||||||
try:
|
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({
|
raise ValidationError({
|
||||||
"name": _("A part with this name already exists")
|
"name": msg,
|
||||||
|
"IPN": msg,
|
||||||
})
|
})
|
||||||
except Part.DoesNotExist:
|
except Part.DoesNotExist:
|
||||||
pass
|
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"),
|
'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,
|
name = models.CharField(max_length=100, blank=False,
|
||||||
help_text='Part name (must be unique)',
|
help_text='Part name',
|
||||||
validators=[validators.validate_part_name]
|
validators=[validators.validate_part_name]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user