diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 0c8c686503..834ac93eed 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -27,7 +27,8 @@ from djmoney.contrib.exchange.exceptions import MissingRate from decimal import Decimal, InvalidOperation -from .models import Part, PartCategory, BomItem +from .models import Part, PartCategory +from .models import BomItem, BomItemSubstitute from .models import PartParameter, PartParameterTemplate from .models import PartAttachment, PartTestTemplate from .models import PartSellPriceBreak, PartInternalPriceBreak @@ -1114,7 +1115,7 @@ class BomList(generics.ListCreateAPIView): try: # Include or exclude pricing information in the serialized data - kwargs['include_pricing'] = str2bool(self.request.GET.get('include_pricing', True)) + kwargs['include_pricing'] = self.include_pricing() except AttributeError: pass @@ -1159,15 +1160,19 @@ class BomList(generics.ListCreateAPIView): except (ValueError, Part.DoesNotExist): pass - pricing_default = InvenTreeSetting.get_setting('PART_SHOW_PRICE_IN_BOM') - - include_pricing = str2bool(params.get('include_pricing', pricing_default)) - - if include_pricing: + if self.include_pricing(): queryset = self.annotate_pricing(queryset) return queryset + def include_pricing(self): + """ + Determine if pricing information should be included in the response + """ + pricing_default = InvenTreeSetting.get_setting('PART_SHOW_PRICE_IN_BOM') + + return str2bool(self.request.query_params.get('include_pricing', pricing_default)) + def annotate_pricing(self, queryset): """ Add part pricing information to the queryset @@ -1276,6 +1281,36 @@ class BomItemValidate(generics.UpdateAPIView): return Response(serializer.data) + +class BomItemSubstituteList(generics.ListCreateAPIView): + """ + API endpoint for accessing a list of BomItemSubstitute objects + """ + + serializer_class = part_serializers.BomItemSubstituteSerializer + queryset = BomItemSubstitute.objects.all() + + filter_backends = [ + DjangoFilterBackend, + filters.SearchFilter, + filters.OrderingFilter, + ] + + filter_fields = [ + 'part', + 'bom_item', + ] + + +class BomItemSubstituteDetail(generics.RetrieveUpdateDestroyAPIView): + """ + API endpoint for detail view of a single BomItemSubstitute object + """ + + queryset = BomItemSubstitute.objects.all() + serializer_class = part_serializers.BomItemSubstituteSerializer + + part_api_urls = [ url(r'^tree/?', PartCategoryTree.as_view(), name='api-part-tree'), @@ -1328,6 +1363,16 @@ part_api_urls = [ ] bom_api_urls = [ + + url(r'^substitute/', include([ + + # Detail view + url(r'^(?P\d+)/', BomItemSubstituteDetail.as_view(), name='api-bom-substitute-detail'), + + # Catch all + url(r'^.*$', BomItemSubstituteList.as_view(), name='api-bom-substitute-list'), + ])), + # BOM Item Detail url(r'^(?P\d+)/', include([ url(r'^validate/?', BomItemValidate.as_view(), name='api-bom-item-validate'), diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index f883250811..0be1f5fc31 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -2623,6 +2623,10 @@ class BomItemSubstitute(models.Model): part: The part which can be used as a substitute """ + @staticmethod + def get_api_url(): + return reverse('api-bom-substitute-list') + bom_item = models.ForeignKey( BomItem, on_delete=models.CASCADE, diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 3fc8e30c1e..869145e1af 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -23,7 +23,8 @@ from InvenTree.serializers import (InvenTreeAttachmentSerializerField, from InvenTree.status_codes import BuildStatus, PurchaseOrderStatus from stock.models import StockItem -from .models import (BomItem, Part, PartAttachment, PartCategory, +from .models import (BomItem, BomItemSubstitute, + Part, PartAttachment, PartCategory, PartParameter, PartParameterTemplate, PartSellPriceBreak, PartStar, PartTestTemplate, PartCategoryParameterTemplate, PartInternalPriceBreak) @@ -388,6 +389,23 @@ class PartStarSerializer(InvenTreeModelSerializer): ] +class BomItemSubstituteSerializer(InvenTreeModelSerializer): + """ + Serializer for the BomItemSubstitute class + """ + + part_detail = PartBriefSerializer(source='part', read_only=True, many=False) + + class Meta: + model = BomItemSubstitute + fields = [ + 'pk', + 'bom_item', + 'part', + 'part_detail', + ] + + class BomItemSerializer(InvenTreeModelSerializer): """ Serializer for BomItem object @@ -399,7 +417,7 @@ class BomItemSerializer(InvenTreeModelSerializer): part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(assembly=True)) - substitutes = PartBriefSerializer(many=True, read_only=True) + substitutes = BomItemSubstituteSerializer(many=True, read_only=True) part_detail = PartBriefSerializer(source='part', many=False, read_only=True)