From d8b9420d2d25712b05f45b53d472cc969ef9cdcf Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 8 Oct 2021 12:47:03 +1100 Subject: [PATCH 1/4] Add a query param `?include_pricing' to the BomItem API - Set this to false to disable pricing info in BOM - Drastic reduction in query speed --- InvenTree/part/api.py | 19 +++++++++++++++++++ InvenTree/part/serializers.py | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 34441286ff..c73d76df4b 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,19 @@ 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') From 69d932e19317b18b760885b41fe1b66df1ff6b0b Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 8 Oct 2021 12:47:21 +1100 Subject: [PATCH 2/4] Add a global setting to control price display in BOM tables --- InvenTree/common/models.py | 12 ++++++++++++ InvenTree/templates/InvenTree/settings/part.html | 1 + 2 files changed, 13 insertions(+) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 41bfa596ed..9a9373d5c3 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/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" %} From 77c6e5e57ebd62330e56a2c8c2dcddb97677a694 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 8 Oct 2021 12:47:51 +1100 Subject: [PATCH 3/4] Update display of BOM table based on the configurable setting --- InvenTree/templates/js/translated/bom.js | 55 ++++++++++++++---------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/InvenTree/templates/js/translated/bom.js b/InvenTree/templates/js/translated/bom.js index 8f571df02e..ec37f71d15 100644 --- a/InvenTree/templates/js/translated/bom.js +++ b/InvenTree/templates/js/translated/bom.js @@ -148,6 +148,13 @@ function loadBomTable(table, options) { ordering: 'name', }; + // Do we show part pricing in the BOM table? + var show_pricing = global_settings.PART_SHOW_PRICE_IN_BOM; + + if (!show_pricing) { + params.include_pricing = false; + } + if (options.part_detail) { params.part_detail = true; } @@ -282,32 +289,34 @@ function loadBomTable(table, options) { } }); - cols.push({ - field: 'purchase_price_range', - title: '{% trans "Purchase Price Range" %}', - searchable: false, - sortable: true, - }); + if (show_pricing) { + cols.push({ + field: 'purchase_price_range', + title: '{% trans "Purchase Price Range" %}', + searchable: false, + sortable: true, + }); - cols.push({ - field: 'purchase_price_avg', - title: '{% trans "Purchase Price Average" %}', - searchable: false, - sortable: true, - }); + cols.push({ + field: 'purchase_price_avg', + title: '{% trans "Purchase Price Average" %}', + searchable: false, + sortable: true, + }); - cols.push({ - field: 'price_range', - title: '{% trans "Supplier Cost" %}', - sortable: true, - formatter: function(value) { - if (value) { - return value; - } else { - return `{% trans 'No supplier pricing available' %}`; + cols.push({ + field: 'price_range', + title: '{% trans "Supplier Cost" %}', + sortable: true, + formatter: function(value) { + if (value) { + return value; + } else { + return `{% trans 'No supplier pricing available' %}`; + } } - } - }); + }); + } cols.push({ field: 'optional', From 07d05ed0003414729a8166504f9b78a9e7328dee Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 8 Oct 2021 12:50:24 +1100 Subject: [PATCH 4/4] PEP fix --- InvenTree/part/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index c73d76df4b..de37d4ea52 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -1153,7 +1153,6 @@ class BomList(generics.ListCreateAPIView): queryset = self.annotate_pricing(queryset) return queryset - def annotate_pricing(self, queryset): """