diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index c86027118c..986749f7b3 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -7,6 +7,7 @@ from __future__ import unicode_literals from InvenTree.forms import HelperForm from InvenTree.helpers import GetExportFormats +from InvenTree.fields import RoundingDecimalFormField from mptt.fields import TreeNodeChoiceField from django import forms @@ -194,6 +195,8 @@ class EditCategoryForm(HelperForm): class EditBomItemForm(HelperForm): """ Form for editing a BomItem object """ + quantity = RoundingDecimalFormField(max_digits=10, decimal_places=5) + class Meta: model = BomItem fields = [ diff --git a/InvenTree/part/migrations/0043_auto_20200527_0005.py b/InvenTree/part/migrations/0043_auto_20200527_0005.py new file mode 100644 index 0000000000..72d1c1ddc4 --- /dev/null +++ b/InvenTree/part/migrations/0043_auto_20200527_0005.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.5 on 2020-05-27 00:05 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0042_auto_20200518_0900'), + ] + + operations = [ + migrations.AlterField( + model_name='bomitem', + name='part', + field=models.ForeignKey(help_text='Select parent part', limit_choices_to={'assembly': True}, on_delete=django.db.models.deletion.CASCADE, related_name='bom_items', to='part.Part'), + ), + migrations.AlterField( + model_name='bomitem', + name='sub_part', + field=models.ForeignKey(help_text='Select part to be used in BOM', limit_choices_to={'component': True}, on_delete=django.db.models.deletion.CASCADE, related_name='used_in', to='part.Part'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 1a8048a985..0e086032b4 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -262,6 +262,9 @@ class Part(MPTTModel): if n_refs == 0: previous.image.delete(save=False) + self.clean() + self.validate_unique() + super().save(*args, **kwargs) def __str__(self): @@ -433,11 +436,7 @@ class Part(MPTTModel): def clean(self): """ Perform cleaning operations for the Part model """ - if self.is_template and self.variant_of is not None: - raise ValidationError({ - 'is_template': _("Part cannot be a template part if it is a variant of another part"), - 'variant_of': _("Part cannot be a variant of another part if it is already a template"), - }) + super().clean() name = models.CharField(max_length=100, blank=False, help_text=_('Part name'), @@ -1364,7 +1363,6 @@ class BomItem(models.Model): help_text=_('Select parent part'), limit_choices_to={ 'assembly': True, - 'is_template': False, }) # A link to the child item (sub-part) @@ -1373,7 +1371,6 @@ class BomItem(models.Model): help_text=_('Select part to be used in BOM'), limit_choices_to={ 'component': True, - 'is_template': False, }) # Quantity required diff --git a/InvenTree/stock/migrations/0044_auto_20200528_1036.py b/InvenTree/stock/migrations/0044_auto_20200528_1036.py new file mode 100644 index 0000000000..2d026fe597 --- /dev/null +++ b/InvenTree/stock/migrations/0044_auto_20200528_1036.py @@ -0,0 +1,17 @@ +# Generated by Django 3.0.5 on 2020-05-28 10:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0043_auto_20200525_0420'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='stockitem', + unique_together=set(), + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 3d9394979c..7bebdefaba 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -292,11 +292,6 @@ class StockItem(MPTTModel): def get_part_name(self): return self.part.full_name - class Meta: - unique_together = [ - ('part', 'serial'), - ] - def format_barcode(self): """ Return a JSON string for formatting a barcode for this StockItem. Can be used to perform lookup of a stockitem using barcode diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 91d9e03016..bde9b2b25b 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -104,12 +104,14 @@ class StockItemSerializer(InvenTreeModelSerializer): location_detail = LocationBriefSerializer(source='location', many=False, read_only=True) supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True) - tracking_items = serializers.IntegerField(source='tracking_info_count') + tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False) quantity = serializers.FloatField() - allocated = serializers.FloatField(source='allocation_count') + allocated = serializers.FloatField(source='allocation_count', required=False) - required_tests = serializers.IntegerField(source='required_test_count', read_only=True) + serial = serializers.IntegerField(required=False) + + required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False) def __init__(self, *args, **kwargs):