From e7357726ca9f7860809a4f235a328fa7d05830f9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Apr 2022 11:19:30 +0200 Subject: [PATCH 1/8] Add oauth for zapier --- InvenTree/InvenTree/settings.py | 2 ++ InvenTree/InvenTree/urls.py | 3 +++ requirements.txt | 1 + 3 files changed, 6 insertions(+) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index e1c584362f..3f1f41d24c 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -269,6 +269,8 @@ INSTALLED_APPS = [ 'django_q', 'formtools', # Form wizard tools + 'oauth2_provider', # Oauth provider + 'allauth', # Base app for SSO 'allauth.account', # Extend user with accounts 'allauth.socialaccount', # Use 'social' providers diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index ec8b891f93..101130045e 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -194,6 +194,9 @@ frontendpatterns = [ url(r"^accounts/password/reset/key/(?P[0-9A-Za-z]+)-(?P.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"), url(r'^accounts/', include('allauth_2fa.urls')), # MFA support url(r'^accounts/', include('allauth.urls')), # included urlpatterns + + # Oauth provider urls + url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')), ] # Append custom plugin URLs (if plugin support is enabled) diff --git a/requirements.txt b/requirements.txt index 9aef6607d7..3777c24f12 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,6 +22,7 @@ django-markdownify==0.8.0 # Markdown rendering django-markdownx==3.0.1 # Markdown form fields django-money==1.1 # Django app for currency management django-mptt==0.11.0 # Modified Preorder Tree Traversal +django-oauth-toolkit==1.7.1 # Oauth endpoints django-redis>=5.0.0 # Redis integration django-q==1.3.4 # Background task scheduling django-sql-utils==0.5.0 # Advanced query annotation / aggregation From 1603bf4e60eb253776b2636a0e461e9f7595125c Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 26 Apr 2022 01:32:31 +0200 Subject: [PATCH 2/8] fix api call --- InvenTree/plugin/builtin/integration/mixins.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/InvenTree/plugin/builtin/integration/mixins.py b/InvenTree/plugin/builtin/integration/mixins.py index 118f0b775b..18c1afe64a 100644 --- a/InvenTree/plugin/builtin/integration/mixins.py +++ b/InvenTree/plugin/builtin/integration/mixins.py @@ -504,10 +504,10 @@ class APICallMixin: @property def api_headers(self): - return { - self.API_TOKEN: self.get_setting(self.API_TOKEN_SETTING), - 'Content-Type': 'application/json' - } + headers = {'Content-Type': 'application/json'} + if getattr(self, 'API_TOKEN_SETTING'): + headers[self.API_TOKEN] = self.get_setting(self.API_TOKEN_SETTING) + return headers def api_build_url_args(self, arguments): groups = [] @@ -515,16 +515,21 @@ class APICallMixin: groups.append(f'{key}={",".join([str(a) for a in val])}') return f'?{"&".join(groups)}' - def api_call(self, endpoint, method: str = 'GET', url_args=None, data=None, headers=None, simple_response: bool = True): + def api_call(self, endpoint, method: str = 'GET', url_args=None, data=None, headers=None, simple_response: bool = True, endpoint_is_url: bool = False): if url_args: endpoint += self.api_build_url_args(url_args) if headers is None: headers = self.api_headers + if endpoint_is_url: + url = endpoint + else: + url = f'{self.api_url}/{endpoint}' + # build kwargs for call kwargs = { - 'url': f'{self.api_url}/{endpoint}', + 'url': url, 'headers': headers, } if data: From d9c0698c345ff756d0b1032749a61bbd5abbdab1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 26 Apr 2022 23:53:07 +0200 Subject: [PATCH 3/8] remove oauth-toolkit --- InvenTree/InvenTree/settings.py | 2 -- InvenTree/InvenTree/urls.py | 3 --- requirements.txt | 1 - 3 files changed, 6 deletions(-) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 3f1f41d24c..e1c584362f 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -269,8 +269,6 @@ INSTALLED_APPS = [ 'django_q', 'formtools', # Form wizard tools - 'oauth2_provider', # Oauth provider - 'allauth', # Base app for SSO 'allauth.account', # Extend user with accounts 'allauth.socialaccount', # Use 'social' providers diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 101130045e..ec8b891f93 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -194,9 +194,6 @@ frontendpatterns = [ url(r"^accounts/password/reset/key/(?P[0-9A-Za-z]+)-(?P.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"), url(r'^accounts/', include('allauth_2fa.urls')), # MFA support url(r'^accounts/', include('allauth.urls')), # included urlpatterns - - # Oauth provider urls - url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')), ] # Append custom plugin URLs (if plugin support is enabled) diff --git a/requirements.txt b/requirements.txt index 3777c24f12..9aef6607d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,7 +22,6 @@ django-markdownify==0.8.0 # Markdown rendering django-markdownx==3.0.1 # Markdown form fields django-money==1.1 # Django app for currency management django-mptt==0.11.0 # Modified Preorder Tree Traversal -django-oauth-toolkit==1.7.1 # Oauth endpoints django-redis>=5.0.0 # Redis integration django-q==1.3.4 # Background task scheduling django-sql-utils==0.5.0 # Advanced query annotation / aggregation From 08ab99adc6181432a4fe949965c2931404895464 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 27 Apr 2022 09:04:57 +1000 Subject: [PATCH 4/8] Build order table improvements: - Display tick / cross badge for stock availability in build order table - Correctly order available quantity --- InvenTree/templates/js/translated/build.js | 34 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index eb955d7ff0..a084b6ecb4 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -1031,6 +1031,23 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { return row.required; } + function availableQuantity(row) { + + // Base stock + var available = row.available_stock; + + // Substitute stock + available += (row.available_substitute_stock || 0); + + // Variant stock + if (row.allow_variants) { + available += (row.available_variant_stock || 0); + } + + return available; + + } + function sumAllocations(row) { // Calculat total allocations for a given row if (!row.allocations) { @@ -1429,12 +1446,13 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { var url = `/part/${row.sub_part_detail.pk}/?display=part-stock`; // Calculate total "available" (unallocated) quantity - var base_stock = row.available_stock; var substitute_stock = row.available_substitute_stock || 0; var variant_stock = row.allow_variants ? (row.available_variant_stock || 0) : 0; - var available_stock = base_stock + substitute_stock + variant_stock; + var available_stock = availableQuantity(row); + var required = requiredQuantity(row); + var text = `${available_stock}`; if (available_stock <= 0) { @@ -1453,9 +1471,19 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { text += ``; } } + + if (available_stock < required) { + text += ``; + } else { + text += ``; + } return renderLink(text, url); - } + }, + sorter: function(valA, valB, rowA, rowB) { + + return availableQuantity(rowA) > availableQuantity(rowB) ? 1 : -1; + }, }, { field: 'allocated', From 2a24fc43e76df2dd2946c876aea7ca348980ebbb Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 27 Apr 2022 09:07:10 +1000 Subject: [PATCH 5/8] Text formatting --- InvenTree/templates/js/translated/build.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index a084b6ecb4..65fc3a4d6c 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -1453,10 +1453,20 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { var required = requiredQuantity(row); - var text = `${available_stock}`; + var text = ''; + + if (available_stock > 0) { + text += `${available_stock}`; + } + + if (available_stock < required) { + text += ``; + } else { + text += ``; + } if (available_stock <= 0) { - text = `{% trans "No Stock Available" %}`; + text += `{% trans "No Stock Available" %}`; } else { var extra = ''; if ((substitute_stock > 0) && (variant_stock > 0)) { @@ -1471,12 +1481,6 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { text += ``; } } - - if (available_stock < required) { - text += ``; - } else { - text += ``; - } return renderLink(text, url); }, From 481350b138af15eef6a21231d8ad1946aabd9bcd Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 27 Apr 2022 09:16:57 +1000 Subject: [PATCH 6/8] Refactor available quantity calculation for BOM table --- InvenTree/templates/js/translated/bom.js | 27 ++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/InvenTree/templates/js/translated/bom.js b/InvenTree/templates/js/translated/bom.js index 0d27a5e028..2d7796edcd 100644 --- a/InvenTree/templates/js/translated/bom.js +++ b/InvenTree/templates/js/translated/bom.js @@ -691,8 +691,24 @@ function loadBomTable(table, options={}) { setupFilterList('bom', $(table)); - // Construct the table columns + function availableQuantity(row) { + // Base stock + var available = row.available_stock; + + // Substitute stock + available += (row.available_substitute_stock || 0); + + // Variant stock + if (row.allow_variants) { + available += (row.available_variant_stock || 0); + } + + return available; + + } + + // Construct the table columns var cols = []; if (options.editable) { @@ -807,11 +823,10 @@ function loadBomTable(table, options={}) { var url = `/part/${row.sub_part_detail.pk}/?display=part-stock`; // Calculate total "available" (unallocated) quantity - var base_stock = row.available_stock; var substitute_stock = row.available_substitute_stock || 0; var variant_stock = row.allow_variants ? (row.available_variant_stock || 0) : 0; - var available_stock = base_stock + substitute_stock + variant_stock; + var available_stock = availableQuantity(row); var text = `${available_stock}`; @@ -923,7 +938,7 @@ function loadBomTable(table, options={}) { formatter: function(value, row) { var can_build = 0; - var available = row.available_stock + (row.available_substitute_stock || 0) + (row.available_variant_stock || 0); + var available = availableQuantity(row); if (row.quantity > 0) { can_build = available / row.quantity; @@ -937,11 +952,11 @@ function loadBomTable(table, options={}) { var cb_b = 0; if (rowA.quantity > 0) { - cb_a = (rowA.available_stock + rowA.available_substitute_stock) / rowA.quantity; + cb_a = availableQuantity(rowA) / rowA.quantity; } if (rowB.quantity > 0) { - cb_b = (rowB.available_stock + rowB.available_substitute_stock) / rowB.quantity; + cb_b = availableQuantity(rowB) / rowB.quantity; } return (cb_a > cb_b) ? 1 : -1; From 86f562f3b8ecc49619e3298763d6b07b7f888d9f Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 27 Apr 2022 13:46:50 +1000 Subject: [PATCH 7/8] Add gdk-pixbuf - Required for weasyprint (reports) to render jpg files --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 9978460e8f..63535bd83d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -65,8 +65,8 @@ RUN apk add --no-cache git make bash \ libjpeg-turbo libjpeg-turbo-dev jpeg jpeg-dev \ libffi libffi-dev \ zlib zlib-dev \ - # Cairo deps for WeasyPrint (these will be deprecated once WeasyPrint drops cairo requirement) - cairo cairo-dev pango pango-dev \ + # Special deps for WeasyPrint (these will be deprecated once WeasyPrint drops cairo requirement) + cairo cairo-dev pango pango-dev gdk-pixbuf \ # Fonts fontconfig ttf-droid ttf-liberation ttf-dejavu ttf-opensans ttf-ubuntu-font-family font-croscore font-noto \ # Core python From f98225334e13c63d7c945c20d5eb627fca89b4fa Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 27 Apr 2022 15:36:44 +1000 Subject: [PATCH 8/8] Simplify allocation display for part page --- InvenTree/part/templates/part/part_base.html | 34 +++---------------- .../part/templatetags/inventree_extras.py | 13 ++++--- 2 files changed, 12 insertions(+), 35 deletions(-) diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index e45620798e..56a96c60ed 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -211,44 +211,18 @@ {% if part.component %} {% if required_build_order_quantity > 0 %} - - {% trans "Required for Build Orders" %} - {% decimal required_build_order_quantity %} - - - + {% trans "Allocated to Build Orders" %} - - {% decimal allocated_build_order_quantity %} - {% if allocated_build_order_quantity < required_build_order_quantity %} - - {% else %} - - {% endif %} - + {% progress_bar allocated_build_order_quantity required_build_order_quantity id='build-order-allocated' max_width='150px' %} {% endif %} {% endif %} {% if part.salable %} {% if required_sales_order_quantity > 0 %} - - {% trans "Required for Sales Orders" %} - - {% decimal required_sales_order_quantity %} - - - - + {% trans "Allocated to Sales Orders" %} - - {% decimal allocated_sales_order_quantity %} - {% if allocated_sales_order_quantity < required_sales_order_quantity %} - - {% else %} - - {% endif %} - + {% progress_bar allocated_sales_order_quantity required_sales_order_quantity id='sales-order-allocated' max_width='150px' %} {% endif %} {% endif %} diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index dc93e00efa..08fa8ce583 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -352,21 +352,24 @@ def visible_global_settings(*args, **kwargs): @register.simple_tag() -def progress_bar(val, max, *args, **kwargs): +def progress_bar(val, max_val, *args, **kwargs): """ Render a progress bar element """ item_id = kwargs.get('id', 'progress-bar') - if val > max: + val = InvenTree.helpers.normalize(val) + max_val = InvenTree.helpers.normalize(max_val) + + if val > max_val: style = 'progress-bar-over' - elif val < max: + elif val < max_val: style = 'progress-bar-under' else: style = '' - percent = float(val / max) * 100 + percent = float(val / max_val) * 100 if percent > 100: percent = 100 @@ -383,7 +386,7 @@ def progress_bar(val, max, *args, **kwargs): html = f"""
-
{val} / {max}
+
{val} / {max_val}
"""