diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index f9a40af893..c33689be61 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -29,11 +29,11 @@ from users.urls import user_urls admin.site.site_header = "InvenTree Admin" apipatterns = [ - url(r'^part/?', include(part_api_urls)), - url(r'^bom/?', include(bom_api_urls)), - url(r'^company/?', include(company_api_urls)), - url(r'^stock/?', include(stock_api_urls)), - url(r'^build/?', include(build_api_urls)), + url(r'^part/', include(part_api_urls)), + url(r'^bom/', include(bom_api_urls)), + url(r'^company/', include(company_api_urls)), + url(r'^stock/', include(stock_api_urls)), + url(r'^build/', include(build_api_urls)), # User URLs url(r'^user/', include(user_urls)), diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 2b4ceb69f5..839c00c7f2 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -220,7 +220,7 @@ part_api_urls = [ url(r'^tree/?', PartCategoryTree.as_view(), name='api-part-tree'), url(r'^category/', include(cat_api_urls)), - url(r'^supplier/?', include(supplier_part_api_urls)), + url(r'^supplier/', include(supplier_part_api_urls)), url(r'^price-break/?', SupplierPriceBreakList.as_view(), name='api-part-supplier-price'), diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 6c9dc4ec54..40cf511b78 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -359,11 +359,12 @@ class BomItem(models.Model): # 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')) + raise ValidationError({'sub_part': _('Part cannot be added to its own Bill of Materials')}) + # Test for simple recursion 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)))) + raise ValidationError({'sub_part': _("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/serializers.py b/InvenTree/part/serializers.py index 102da8bd76..fbd9421806 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -69,6 +69,11 @@ class BomItemSerializer(serializers.ModelSerializer): # url = serializers.CharField(source='get_absolute_url', read_only=True) + def validate(self, data): + instance = BomItem(**data) + instance.clean() + return data + part_detail = PartBriefSerializer(source='part', many=False, read_only=True) sub_part_detail = PartBriefSerializer(source='sub_part', many=False, read_only=True)