Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2020-05-29 13:47:19 +10:00
commit b73044cd44
6 changed files with 53 additions and 15 deletions

View File

@ -7,6 +7,7 @@ from __future__ import unicode_literals
from InvenTree.forms import HelperForm from InvenTree.forms import HelperForm
from InvenTree.helpers import GetExportFormats from InvenTree.helpers import GetExportFormats
from InvenTree.fields import RoundingDecimalFormField
from mptt.fields import TreeNodeChoiceField from mptt.fields import TreeNodeChoiceField
from django import forms from django import forms
@ -194,6 +195,8 @@ class EditCategoryForm(HelperForm):
class EditBomItemForm(HelperForm): class EditBomItemForm(HelperForm):
""" Form for editing a BomItem object """ """ Form for editing a BomItem object """
quantity = RoundingDecimalFormField(max_digits=10, decimal_places=5)
class Meta: class Meta:
model = BomItem model = BomItem
fields = [ fields = [

View File

@ -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'),
),
]

View File

@ -262,6 +262,9 @@ class Part(MPTTModel):
if n_refs == 0: if n_refs == 0:
previous.image.delete(save=False) previous.image.delete(save=False)
self.clean()
self.validate_unique()
super().save(*args, **kwargs) super().save(*args, **kwargs)
def __str__(self): def __str__(self):
@ -433,11 +436,7 @@ class Part(MPTTModel):
def clean(self): def clean(self):
""" Perform cleaning operations for the Part model """ """ Perform cleaning operations for the Part model """
if self.is_template and self.variant_of is not None: super().clean()
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"),
})
name = models.CharField(max_length=100, blank=False, name = models.CharField(max_length=100, blank=False,
help_text=_('Part name'), help_text=_('Part name'),
@ -1364,7 +1363,6 @@ class BomItem(models.Model):
help_text=_('Select parent part'), help_text=_('Select parent part'),
limit_choices_to={ limit_choices_to={
'assembly': True, 'assembly': True,
'is_template': False,
}) })
# A link to the child item (sub-part) # 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'), help_text=_('Select part to be used in BOM'),
limit_choices_to={ limit_choices_to={
'component': True, 'component': True,
'is_template': False,
}) })
# Quantity required # Quantity required

View File

@ -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(),
),
]

View File

@ -292,11 +292,6 @@ class StockItem(MPTTModel):
def get_part_name(self): def get_part_name(self):
return self.part.full_name return self.part.full_name
class Meta:
unique_together = [
('part', 'serial'),
]
def format_barcode(self): def format_barcode(self):
""" Return a JSON string for formatting a barcode for this StockItem. """ Return a JSON string for formatting a barcode for this StockItem.
Can be used to perform lookup of a stockitem using barcode Can be used to perform lookup of a stockitem using barcode

View File

@ -104,12 +104,14 @@ class StockItemSerializer(InvenTreeModelSerializer):
location_detail = LocationBriefSerializer(source='location', many=False, read_only=True) location_detail = LocationBriefSerializer(source='location', many=False, read_only=True)
supplier_part_detail = SupplierPartSerializer(source='supplier_part', 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() 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): def __init__(self, *args, **kwargs):