mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-26 16:50:56 +00:00
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:
19
InvenTree/stock/migrations/0003_auto_20190525_2303.py
Normal file
19
InvenTree/stock/migrations/0003_auto_20190525_2303.py
Normal 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'),
|
||||||
|
),
|
||||||
|
]
|
@ -115,6 +115,23 @@ class StockItem(models.Model):
|
|||||||
system=True
|
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):
|
def clean(self):
|
||||||
""" Validate the StockItem object (separate to field validation)
|
""" 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,
|
part = models.ForeignKey('part.Part', on_delete=models.CASCADE,
|
||||||
related_name='stock_items', help_text='Base part',
|
related_name='stock_items', help_text='Base part',
|
||||||
limit_choices_to={
|
limit_choices_to={
|
||||||
'has_variants': True,
|
'has_variants': False,
|
||||||
'active': True,
|
'active': True,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -208,13 +208,19 @@ class StockItemCreate(AjaxCreateView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
part = Part.objects.get(id=part_id)
|
part = Part.objects.get(id=part_id)
|
||||||
parts = form.fields['supplier_part'].queryset
|
# Hide the 'part' field (as a valid part is selected)
|
||||||
parts = parts.filter(part=part.id)
|
form.fields['part'].widget = HiddenInput()
|
||||||
|
|
||||||
|
|
||||||
# If the part is NOT purchaseable, hide the supplier_part field
|
# If the part is NOT purchaseable, hide the supplier_part field
|
||||||
if not part.purchaseable:
|
if not part.purchaseable:
|
||||||
form.fields['supplier_part'].widget = HiddenInput()
|
form.fields['supplier_part'].widget = HiddenInput()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Pre-select the allowable SupplierPart options
|
||||||
|
parts = form.fields['supplier_part'].queryset
|
||||||
|
parts = parts.filter(part=part.id)
|
||||||
|
|
||||||
form.fields['supplier_part'].queryset = parts
|
form.fields['supplier_part'].queryset = parts
|
||||||
|
|
||||||
# If there is one (and only one) supplier part available, pre-select it
|
# If there is one (and only one) supplier part available, pre-select it
|
||||||
@ -227,9 +233,6 @@ class StockItemCreate(AjaxCreateView):
|
|||||||
except Part.DoesNotExist:
|
except Part.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Hide the 'part' field
|
|
||||||
form.fields['part'].widget = HiddenInput()
|
|
||||||
|
|
||||||
# Otherwise if the user has selected a SupplierPart, we know what Part they meant!
|
# Otherwise if the user has selected a SupplierPart, we know what Part they meant!
|
||||||
elif form['supplier_part'].value() is not None:
|
elif form['supplier_part'].value() is not None:
|
||||||
pass
|
pass
|
||||||
|
Reference in New Issue
Block a user