mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
332a419ab9
@ -1083,7 +1083,9 @@ class Part(MPTTModel):
|
|||||||
parts: Set of parts already found (to prevent recursion issues)
|
parts: Set of parts already found (to prevent recursion issues)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for bom_item in self.bom_items.all().select_related('sub_part'):
|
items = self.bom_items.all().prefetch_related('sub_part')
|
||||||
|
|
||||||
|
for bom_item in items:
|
||||||
|
|
||||||
sub_part = bom_item.sub_part
|
sub_part = bom_item.sub_part
|
||||||
|
|
||||||
@ -1885,25 +1887,27 @@ class BomItem(models.Model):
|
|||||||
- If the "sub_part" is trackable, then the "part" must be trackable too!
|
- If the "sub_part" is trackable, then the "part" must be trackable too!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# If the sub_part is 'trackable' then the 'quantity' field must be an integer
|
|
||||||
try:
|
try:
|
||||||
if self.sub_part.trackable:
|
# Check for circular BOM references
|
||||||
if not self.quantity == int(self.quantity):
|
if self.sub_part:
|
||||||
raise ValidationError({
|
self.sub_part.checkAddToBOM(self.part)
|
||||||
"quantity": _("Quantity must be integer value for trackable parts")
|
|
||||||
})
|
|
||||||
|
|
||||||
# Force the upstream part to be trackable if the sub_part is trackable
|
# If the sub_part is 'trackable' then the 'quantity' field must be an integer
|
||||||
if not self.part.trackable:
|
if self.sub_part.trackable:
|
||||||
self.part.trackable = True
|
if not self.quantity == int(self.quantity):
|
||||||
self.part.clean()
|
raise ValidationError({
|
||||||
self.part.save()
|
"quantity": _("Quantity must be integer value for trackable parts")
|
||||||
|
})
|
||||||
|
|
||||||
|
# Force the upstream part to be trackable if the sub_part is trackable
|
||||||
|
if not self.part.trackable:
|
||||||
|
self.part.trackable = True
|
||||||
|
self.part.clean()
|
||||||
|
self.part.save()
|
||||||
|
else:
|
||||||
|
raise ValidationError({'sub_part': _('Sub part must be specified')})
|
||||||
except Part.DoesNotExist:
|
except Part.DoesNotExist:
|
||||||
pass
|
raise ValidationError({'sub_part': _('Sub part must be specified')})
|
||||||
|
|
||||||
# Check for circular BOM references
|
|
||||||
self.sub_part.checkAddToBOM(self.part)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("BOM Item")
|
verbose_name = _("BOM Item")
|
||||||
|
@ -2428,30 +2428,34 @@ class BomItemCreate(AjaxCreateView):
|
|||||||
|
|
||||||
part_id = form['part'].value()
|
part_id = form['part'].value()
|
||||||
|
|
||||||
|
# Construct a queryset for the part field
|
||||||
|
part_query = Part.objects.filter(active=True)
|
||||||
|
|
||||||
|
# Construct a queryset for the sub_part field
|
||||||
|
sub_part_query = Part.objects.filter(
|
||||||
|
component=True,
|
||||||
|
active=True
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
part = Part.objects.get(id=part_id)
|
part = Part.objects.get(id=part_id)
|
||||||
|
|
||||||
# Only allow active parts to be selected
|
# Hide the 'part' field
|
||||||
query = form.fields['part'].queryset.filter(active=True)
|
form.fields['part'].widget = HiddenInput()
|
||||||
form.fields['part'].queryset = query
|
|
||||||
|
|
||||||
# Don't allow selection of sub_part objects which are already added to the Bom!
|
# Exclude the part from its own BOM
|
||||||
query = form.fields['sub_part'].queryset
|
sub_part_query = sub_part_query.exclude(id=part.id)
|
||||||
|
|
||||||
# Don't allow a part to be added to its own BOM
|
|
||||||
query = query.exclude(id=part.id)
|
|
||||||
query = query.filter(active=True)
|
|
||||||
|
|
||||||
# Eliminate any options that are already in the BOM!
|
# Eliminate any options that are already in the BOM!
|
||||||
query = query.exclude(id__in=[item.id for item in part.getRequiredParts()])
|
sub_part_query = sub_part_query.exclude(id__in=[item.id for item in part.getRequiredParts()])
|
||||||
|
|
||||||
form.fields['sub_part'].queryset = query
|
|
||||||
|
|
||||||
form.fields['part'].widget = HiddenInput()
|
|
||||||
|
|
||||||
except (ValueError, Part.DoesNotExist):
|
except (ValueError, Part.DoesNotExist):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Set the querysets for the fields
|
||||||
|
form.fields['part'].queryset = part_query
|
||||||
|
form.fields['sub_part'].queryset = sub_part_query
|
||||||
|
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
@ -2492,6 +2496,8 @@ class BomItemEdit(AjaxUpdateView):
|
|||||||
- Remove any part items that are already in the BOM
|
- Remove any part items that are already in the BOM
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
item = self.get_object()
|
||||||
|
|
||||||
form = super().get_form()
|
form = super().get_form()
|
||||||
|
|
||||||
part_id = form['part'].value()
|
part_id = form['part'].value()
|
||||||
@ -2499,9 +2505,14 @@ class BomItemEdit(AjaxUpdateView):
|
|||||||
try:
|
try:
|
||||||
part = Part.objects.get(pk=part_id)
|
part = Part.objects.get(pk=part_id)
|
||||||
|
|
||||||
query = form.fields['sub_part'].queryset
|
# Construct a queryset
|
||||||
|
query = Part.objects.filter(component=True)
|
||||||
|
|
||||||
# Reduce the available selection options
|
# Limit to "active" items, *unless* the currently selected item is not active
|
||||||
|
if item.sub_part.active:
|
||||||
|
query = query.filter(active=True)
|
||||||
|
|
||||||
|
# Prevent the parent part from being selected
|
||||||
query = query.exclude(pk=part_id)
|
query = query.exclude(pk=part_id)
|
||||||
|
|
||||||
# Eliminate any options that are already in the BOM,
|
# Eliminate any options that are already in the BOM,
|
||||||
|
Loading…
Reference in New Issue
Block a user