Validate uniqueness for StockItems

- If the Part is a variant of a template, ensure that the serial numbers are unique across all instances of the template
- Prevent instantiation of a StockItem for a part which has variants
This commit is contained in:
Oliver Walters 2019-05-25 23:09:04 +10:00
parent bc778c1451
commit d70110690b
3 changed files with 51 additions and 12 deletions

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2 on 2019-05-25 13:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('stock', '0002_auto_20190525_2226'),
]
operations = [
migrations.AlterField(
model_name='stockitem',
name='part',
field=models.ForeignKey(help_text='Base part', limit_choices_to={'active': True, 'has_variants': False}, on_delete=django.db.models.deletion.CASCADE, related_name='stock_items', to='part.Part'),
),
]

View File

@ -115,6 +115,23 @@ class StockItem(models.Model):
system=True
)
def validate_unique(self, exclude=None):
super(StockItem, self).validate_unique(exclude)
# If the Part object is a variant (of a template part),
# ensure that the serial number is unique
# across all variants of the same template part
try:
if self.serial is not None and self.part.variant_of is not None:
if StockItem.objects.filter(part__variant_of=self.part.variant_of, serial=self.serial).exclude(id=self.id).exists():
raise ValidationError({
'serial': _('A part with this serial number already exists for template part {part}'.format(part=self.part.variant_of))
})
except Part.DoesNotExist:
pass
def clean(self):
""" Validate the StockItem object (separate to field validation)
@ -196,7 +213,7 @@ class StockItem(models.Model):
part = models.ForeignKey('part.Part', on_delete=models.CASCADE,
related_name='stock_items', help_text='Base part',
limit_choices_to={
'has_variants': True,
'has_variants': False,
'active': True,
})

View File

@ -208,28 +208,31 @@ class StockItemCreate(AjaxCreateView):
try:
part = Part.objects.get(id=part_id)
parts = form.fields['supplier_part'].queryset
parts = parts.filter(part=part.id)
# Hide the 'part' field (as a valid part is selected)
form.fields['part'].widget = HiddenInput()
# If the part is NOT purchaseable, hide the supplier_part field
if not part.purchaseable:
form.fields['supplier_part'].widget = HiddenInput()
form.fields['supplier_part'].queryset = parts
else:
# Pre-select the allowable SupplierPart options
parts = form.fields['supplier_part'].queryset
parts = parts.filter(part=part.id)
# If there is one (and only one) supplier part available, pre-select it
all_parts = parts.all()
if len(all_parts) == 1:
form.fields['supplier_part'].queryset = parts
# TODO - This does NOT work for some reason? Ref build.views.BuildItemCreate
form.fields['supplier_part'].initial = all_parts[0].id
# If there is one (and only one) supplier part available, pre-select it
all_parts = parts.all()
if len(all_parts) == 1:
# TODO - This does NOT work for some reason? Ref build.views.BuildItemCreate
form.fields['supplier_part'].initial = all_parts[0].id
except Part.DoesNotExist:
pass
# Hide the 'part' field
form.fields['part'].widget = HiddenInput()
# Otherwise if the user has selected a SupplierPart, we know what Part they meant!
elif form['supplier_part'].value() is not None:
pass