diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 823fc8e512..bdf7dcb5ae 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -662,6 +662,18 @@ class InvenTreeSetting(BaseInvenTreeSetting): 'validator': bool, }, + # 2021-10-08 + # This setting exists as an interim solution for https://github.com/inventree/InvenTree/issues/2042 + # The BOM API can be extremely slow when calculating pricing information "on the fly" + # A future solution will solve this properly, + # but as an interim step we provide a global to enable / disable BOM pricing + 'PART_SHOW_PRICE_IN_BOM': { + 'name': _('Show Price in BOM'), + 'description': _('Include pricing information in BOM tables'), + 'default': True, + 'validator': bool, + }, + 'PART_SHOW_RELATED': { 'name': _('Show related parts'), 'description': _('Display related parts for a part'), diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 34441286ff..de37d4ea52 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -1100,6 +1100,12 @@ class BomList(generics.ListCreateAPIView): except AttributeError: pass + try: + # Include or exclude pricing information in the serialized data + kwargs['include_pricing'] = str2bool(self.request.GET.get('include_pricing', True)) + except AttributeError: + pass + # Ensure the request context is passed through! kwargs['context'] = self.get_serializer_context() @@ -1141,6 +1147,18 @@ class BomList(generics.ListCreateAPIView): except (ValueError, Part.DoesNotExist): pass + include_pricing = str2bool(params.get('include_pricing', True)) + + if include_pricing: + queryset = self.annotate_pricing(queryset) + + return queryset + + def annotate_pricing(self, queryset): + """ + Add part pricing information to the queryset + """ + # Annotate with purchase prices queryset = queryset.annotate( purchase_price_min=Min('sub_part__stock_items__purchase_price'), diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 4f1ba8cc8b..509de43b68 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -419,6 +419,7 @@ class BomItemSerializer(InvenTreeModelSerializer): part_detail = kwargs.pop('part_detail', False) sub_part_detail = kwargs.pop('sub_part_detail', False) + include_pricing = kwargs.pop('include_pricing', False) super(BomItemSerializer, self).__init__(*args, **kwargs) @@ -428,6 +429,14 @@ class BomItemSerializer(InvenTreeModelSerializer): if sub_part_detail is not True: self.fields.pop('sub_part_detail') + if not include_pricing: + # Remove all pricing related fields + self.fields.pop('price_range') + self.fields.pop('purchase_price_min') + self.fields.pop('purchase_price_max') + self.fields.pop('purchase_price_avg') + self.fields.pop('purchase_price_range') + @staticmethod def setup_eager_loading(queryset): queryset = queryset.prefetch_related('part') diff --git a/InvenTree/templates/InvenTree/settings/part.html b/InvenTree/templates/InvenTree/settings/part.html index 837f59e997..0ec5f56db6 100644 --- a/InvenTree/templates/InvenTree/settings/part.html +++ b/InvenTree/templates/InvenTree/settings/part.html @@ -18,6 +18,7 @@ {% include "InvenTree/settings/setting.html" with key="PART_ALLOW_DUPLICATE_IPN" %} {% include "InvenTree/settings/setting.html" with key="PART_ALLOW_EDIT_IPN" %} {% include "InvenTree/settings/setting.html" with key="PART_SHOW_PRICE_IN_FORMS" icon="fa-dollar-sign" %} + {% include "InvenTree/settings/setting.html" with key="PART_SHOW_PRICE_IN_BOM" icon="fa-dollar-sign" %} {% include "InvenTree/settings/setting.html" with key="PART_SHOW_RELATED" icon="fa-random" %} {% include "InvenTree/settings/setting.html" with key="PART_CREATE_INITIAL" icon="fa-boxes" %}