From 06f9c67b11e7969ce868e907f3b4a3ee27b3721f Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 27 Apr 2018 23:23:44 +1000 Subject: [PATCH 1/3] Prevent part from adding itself as a BOM item --- InvenTree/part/models.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index dd05862271..582725639d 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -3,6 +3,9 @@ from __future__ import unicode_literals import os +from django.utils.translation import gettext_lazy as _ +from django.core.exceptions import ValidationError + from django.db import models from django.db.models import Sum from django.core.validators import MinValueValidator @@ -348,6 +351,12 @@ class BomItem(models.Model): # Quantity required quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) + def clean(self): + + if self.part == self.sub_part: + raise ValidationError(_('A part cannot contain itself as a BOM item')) + + class Meta: verbose_name = "BOM Item" From f49474ace50329e81b37eb1020d950eb4bac16a9 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 27 Apr 2018 23:42:23 +1000 Subject: [PATCH 2/3] Prevent recursive BOMs - If A has B in its BOM, A cannot be added to the BOM of B --- InvenTree/InvenTree/settings.py | 9 ++++++++- InvenTree/part/models.py | 4 ++++ InvenTree/part/templates/part/bom.html | 5 ++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 91f0a66730..e82f33ee65 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -11,7 +11,8 @@ https://docs.djangoproject.com/en/1.10/ref/settings/ """ import os - +import logging +import logging.config # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -28,6 +29,12 @@ DEBUG = True ALLOWED_HOSTS = [] +if DEBUG: + # will output to your console + logging.basicConfig( + level = logging.DEBUG, + format = '%(asctime)s %(levelname)s %(message)s', + ) # Application definition diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 582725639d..236649214f 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -353,9 +353,13 @@ class BomItem(models.Model): def clean(self): + # A part cannot refer to itself in its BOM if self.part == self.sub_part: raise ValidationError(_('A part cannot contain itself as a BOM item')) + for item in self.sub_part.bom_items.all(): + if self.part == item.sub_part: + raise ValidationError(_("Part '{p1}' is used in BOM for '{p2}' (recursive)".format(p1=str(self.part), p2=str(self.sub_part)))) class Meta: verbose_name = "BOM Item" diff --git a/InvenTree/part/templates/part/bom.html b/InvenTree/part/templates/part/bom.html index ec4c1635d9..1157279312 100644 --- a/InvenTree/part/templates/part/bom.html +++ b/InvenTree/part/templates/part/bom.html @@ -60,7 +60,10 @@ $(document).ready(function(){ var button = $(this); launchDeleteForm("#modal-delete", - button.attr('url')); + button.attr('url'), + { + reload: true + }); }); $('#bom-table').on('click', '.edit-row-button', function () { From 1df42b2397577268768ce54410d04c42661ab34a Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 28 Apr 2018 00:06:39 +1000 Subject: [PATCH 3/3] Sanity checking for StockItem - If a SupplierPart is selected, it must point to the same Part type as the Part field! --- InvenTree/stock/models.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index f77550b609..1c765180c1 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext_lazy as _ +from django.core.exceptions import ValidationError from django.db import models, transaction from django.core.validators import MinValueValidator @@ -13,6 +14,8 @@ from datetime import datetime from InvenTree.models import InvenTreeTree +from part.models import Part + class StockLocation(InvenTreeTree): """ Organization tree for StockItem objects @@ -54,6 +57,26 @@ class StockItem(models.Model): If a serial number is assigned, then StockItem cannot have a quantity other than 1 """ + def clean(self): + + + # The 'supplier_part' field must point to the same part! + try: + if self.supplier_part is not None: + if not self.supplier_part.part == self.part: + raise ValidationError({ + 'supplier_part': _( + "Part type ('{pf}') must be {pe}").format( + pf=str(self.supplier_part.part), + pe=str(self.part) + ) + }) + except Part.DoesNotExist: + # This gets thrown if self.supplier_part is null + # TODO - Find a test than can be perfomed... + pass + + def get_absolute_url(self): return '/stock/item/{id}/'.format(id=self.id)