From a0b3359d62a6d685c4052e599f6be371b84663e2 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 19:58:47 +1000 Subject: [PATCH 01/35] Fix filtering for build orders --- InvenTree/build/api.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/InvenTree/build/api.py b/InvenTree/build/api.py index 069b6e58fe..47edb55545 100644 --- a/InvenTree/build/api.py +++ b/InvenTree/build/api.py @@ -68,10 +68,6 @@ class BuildList(generics.ListCreateAPIView): filters.OrderingFilter, ] - filter_fields = [ - 'sales_order', - ] - ordering_fields = [ 'reference', 'part__name', @@ -114,6 +110,12 @@ class BuildList(generics.ListCreateAPIView): if parent is not None: queryset = queryset.filter(parent=parent) + # Filter by sales_order + sales_order = params.get('sales_order', None) + + if sales_order is not None: + queryset = queryset.filter(sales_order=sales_order) + # Filter by "ancestor" builds ancestor = params.get('ancestor', None) From 39c58e40154eed53687bf5ba045ef92a24ffdd57 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 19:59:11 +1000 Subject: [PATCH 02/35] Move all "SalesOrder" content onto a single page --- .../templates/order/sales_order_detail.html | 152 ++++++++++++++++-- InvenTree/templates/two_column.html | 4 + 2 files changed, 139 insertions(+), 17 deletions(-) diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 4af0e219d6..9da0c88c82 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -4,38 +4,156 @@ {% load status_codes %} {% load i18n %} {% load static %} +{% load markdownify %} {% block menubar %} {% include "order/so_navbar.html" with tab='details' %} {% endblock %} -{% block heading %} -{% trans "Sales Order Items" %} -{% endblock %} +{% block page_content %} -{% block details %} - - -{% if roles.sales_order.change %} -
- +
+
+

{% trans "Sales Order Items" %}

+
+
+ {% if roles.sales_order.change %} +
+ +
+ {% endif %} + +
+
-{% endif %} - +
+
+

{% trans "Build Orders" %}

+
+
+
+
+ - +
+
+

{% trans "Attachments" %}

+
+
+ {% include "attachment_table.html" %} +
+
+ +
+
+
+
+

{% trans "Notes" %}

+
+
+
+ +
+
+
+
+
+ {{ order.notes | markdownify }} +
+
{% endblock %} {% block js_ready %} {{ block.super }} -function reloadTable() { - $("#so-lines-table").bootstrapTable("refresh"); -} + $('#edit-notes').click(function() { + constructForm('{% url "api-so-detail" order.pk %}', { + fields: { + notes: { + multiline: true, + } + }, + title: '{% trans "Edit Notes" %}', + reload: true, + }); + }); + + enableDragAndDrop( + '#attachment-dropzone', + '{% url "api-so-attachment-list" %}', + { + data: { + order: {{ order.id }}, + }, + label: 'attachment', + success: function(data, status, xhr) { + location.reload(); + } + } + ); + + loadAttachmentTable( + '{% url "api-so-attachment-list" %}', + { + filters: { + order: {{ order.pk }}, + }, + onEdit: function(pk) { + var url = `/api/order/so/attachment/${pk}/`; + + constructForm(url, { + fields: { + comment: {}, + }, + onSuccess: reloadAttachmentTable, + title: '{% trans "Edit Attachment" %}', + }); + }, + onDelete: function(pk) { + constructForm(`/api/order/so/attachment/${pk}/`, { + method: 'DELETE', + confirmMessage: '{% trans "Confirm Delete Operation" %}', + title: '{% trans "Delete Attachment" %}', + onSuccess: reloadAttachmentTable, + }); + } + } + ); + + $("#new-attachment").click(function() { + + constructForm('{% url "api-so-attachment-list" %}', { + method: 'POST', + fields: { + attachment: {}, + comment: {}, + order: { + value: {{ order.pk }}, + hidden: true + } + }, + onSuccess: reloadAttachmentTable, + title: '{% trans "Add Attachment" %}' + }); + }); + + loadBuildTable($("#builds-table"), { + url: "{% url 'api-build-list' %}", + params: { + sales_order: {{ order.id }}, + }, + }); + + function reloadTable() { + $("#so-lines-table").bootstrapTable("refresh"); + } $("#new-so-line").click(function() { diff --git a/InvenTree/templates/two_column.html b/InvenTree/templates/two_column.html index c942bef1fa..bcc85c7269 100644 --- a/InvenTree/templates/two_column.html +++ b/InvenTree/templates/two_column.html @@ -43,6 +43,8 @@ {% endblock %} +{% block page_content %} + {% block pre_content_panels %} {% endblock %} @@ -71,6 +73,8 @@ {% endblock %} +{% endblock %} + {% block js_ready %} {{ block.super }} From 970f08260cc3dc05c41dfe0eddc32c2cfe3300c7 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 20:04:02 +1000 Subject: [PATCH 03/35] Update navbar --- .../order/templates/order/so_navbar.html | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/InvenTree/order/templates/order/so_navbar.html b/InvenTree/order/templates/order/so_navbar.html index 4623febd02..b3b0ac30f5 100644 --- a/InvenTree/order/templates/order/so_navbar.html +++ b/InvenTree/order/templates/order/so_navbar.html @@ -9,29 +9,29 @@ -
  • - - - {% trans "Details" %} +
  • + + + {% trans "Order Items" %}
  • -
  • - +
  • + {% trans "Build Orders" %}
  • -
  • - +
  • + {% trans "Attachments" %}
  • -
  • - +
  • + {% trans "Notes" %} From 9889e314a9e6c386f08987d9788527820472af18 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 20:04:12 +1000 Subject: [PATCH 04/35] Remove unused templates --- .../templates/order/sales_order_notes.html | 56 ------------- .../order/templates/order/so_attachments.html | 83 ------------------- .../order/templates/order/so_builds.html | 33 -------- InvenTree/order/urls.py | 4 - InvenTree/order/views.py | 22 ----- 5 files changed, 198 deletions(-) delete mode 100644 InvenTree/order/templates/order/sales_order_notes.html delete mode 100644 InvenTree/order/templates/order/so_attachments.html delete mode 100644 InvenTree/order/templates/order/so_builds.html diff --git a/InvenTree/order/templates/order/sales_order_notes.html b/InvenTree/order/templates/order/sales_order_notes.html deleted file mode 100644 index 0a2e105b2e..0000000000 --- a/InvenTree/order/templates/order/sales_order_notes.html +++ /dev/null @@ -1,56 +0,0 @@ -{% extends "order/sales_order_base.html" %} - -{% load inventree_extras %} -{% load i18n %} -{% load static %} -{% load markdownify %} -{% load status_codes %} - -{% block menubar %} -{% include 'order/so_navbar.html' with tab='notes' %} -{% endblock %} - -{% block heading %} -{% trans "Sales Order Notes" %} -{% if roles.sales_order.change and not editing %} - -{% endif %} -{% endblock %} - -{% block details %} - -{% if editing %} - -
    - {% csrf_token %} - - {{ form }} -
    - -
    - -{{ form.media }} - -{% else %} -
    -
    - {{ order.notes | markdownify }} -
    -
    - -{% endif %} - -{% endblock %} - -{% block js_ready %} - -{{ block.super }} - -{% if editing %} -{% else %} -$("#edit-notes").click(function() { - location.href = "{% url 'so-notes' order.id %}?edit=1"; -}); -{% endif %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/so_attachments.html b/InvenTree/order/templates/order/so_attachments.html deleted file mode 100644 index 9c29fe5abe..0000000000 --- a/InvenTree/order/templates/order/so_attachments.html +++ /dev/null @@ -1,83 +0,0 @@ -{% extends "order/sales_order_base.html" %} - -{% load inventree_extras %} -{% load i18n %} -{% load static %} - -{% block menubar %} -{% include 'order/so_navbar.html' with tab='attachments' %} -{% endblock %} - -{% block heading %} -{% trans "Sales Order Attachments" %} -{% endblock %} - -{% block details %} - -{% include "attachment_table.html" with attachments=order.attachments.all %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -enableDragAndDrop( - '#attachment-dropzone', - '{% url "api-so-attachment-list" %}', - { - data: { - order: {{ order.id }}, - }, - label: 'attachment', - success: function(data, status, xhr) { - location.reload(); - } - } -); - -loadAttachmentTable( - '{% url "api-so-attachment-list" %}', - { - filters: { - order: {{ order.pk }}, - }, - onEdit: function(pk) { - var url = `/api/order/so/attachment/${pk}/`; - - constructForm(url, { - fields: { - comment: {}, - }, - onSuccess: reloadAttachmentTable, - title: '{% trans "Edit Attachment" %}', - }); - }, - onDelete: function(pk) { - constructForm(`/api/order/so/attachment/${pk}/`, { - method: 'DELETE', - confirmMessage: '{% trans "Confirm Delete Operation" %}', - title: '{% trans "Delete Attachment" %}', - onSuccess: reloadAttachmentTable, - }); - } - } -); - -$("#new-attachment").click(function() { - - constructForm('{% url "api-so-attachment-list" %}', { - method: 'POST', - fields: { - attachment: {}, - comment: {}, - order: { - value: {{ order.pk }}, - hidden: true - } - }, - onSuccess: reloadAttachmentTable, - title: '{% trans "Add Attachment" %}' - }); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/so_builds.html b/InvenTree/order/templates/order/so_builds.html deleted file mode 100644 index e29a76b64d..0000000000 --- a/InvenTree/order/templates/order/so_builds.html +++ /dev/null @@ -1,33 +0,0 @@ -{% extends "order/sales_order_base.html" %} - -{% load inventree_extras %} -{% load i18n %} -{% load static %} - -{% block menubar %} -{% include 'order/so_navbar.html' with tab='builds' %} -{% endblock %} - -{% block heading %} -{% trans "Build Orders" %} -{% endblock %} - -{% block details %} - - -
    - -{% endblock %} - -{% block js_ready %} - -{{ block.super }} - -loadBuildTable($("#builds-table"), { - url: "{% url 'api-build-list' %}", - params: { - sales_order: {{ order.id }}, - }, -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/urls.py b/InvenTree/order/urls.py index 16be6e77ce..768607a93b 100644 --- a/InvenTree/order/urls.py +++ b/InvenTree/order/urls.py @@ -42,10 +42,6 @@ sales_order_detail_urls = [ url(r'^cancel/', views.SalesOrderCancel.as_view(), name='so-cancel'), url(r'^ship/', views.SalesOrderShip.as_view(), name='so-ship'), - url(r'^builds/', views.SalesOrderDetail.as_view(template_name='order/so_builds.html'), name='so-builds'), - url(r'^attachments/', views.SalesOrderDetail.as_view(template_name='order/so_attachments.html'), name='so-attachments'), - url(r'^notes/', views.SalesOrderNotes.as_view(), name='so-notes'), - url(r'^.*$', views.SalesOrderDetail.as_view(), name='so-detail'), ] diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index 2ec06e600e..7267df1094 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -122,28 +122,6 @@ class PurchaseOrderNotes(InvenTreeRoleMixin, UpdateView): return ctx -class SalesOrderNotes(InvenTreeRoleMixin, UpdateView): - """ View for editing the 'notes' field of a SalesORder """ - - context_object_name = 'order' - template_name = 'order/sales_order_notes.html' - model = SalesOrder - role_required = 'sales_order.view' - - fields = ['notes'] - - def get_success_url(self): - return reverse('so-notes', kwargs={'pk': self.get_object().pk}) - - def get_context_data(self, **kwargs): - - ctx = super().get_context_data(**kwargs) - - ctx['editing'] = str2bool(self.request.GET.get('edit', False)) - - return ctx - - class PurchaseOrderCancel(AjaxUpdateView): """ View for cancelling a purchase order """ From 65de52b705fe31ed7d9bc45425663eb1bf225827 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 20:58:05 +1000 Subject: [PATCH 05/35] Add javascript to dynamically switch between views --- InvenTree/InvenTree/static/css/inventree.css | 4 ++ InvenTree/InvenTree/urls.py | 11 ++-- .../templates/order/sales_order_detail.html | 13 ++-- .../order/templates/order/so_navbar.html | 16 ++--- InvenTree/templates/base.html | 17 +++--- InvenTree/templates/js/nav.js | 60 +++++++++++++++++++ 6 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 InvenTree/templates/js/nav.js diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index ac7cf1f4e1..1f01037f28 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -912,6 +912,10 @@ input[type="submit"] { box-shadow: 1px 1px #DDD; } +.panel-hidden { + display: none; +} + .float-right { float: right; } diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index f3ea86e8cc..a3af143f92 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -104,22 +104,23 @@ settings_urls = [ dynamic_javascript_urls = [ url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.js'), url(r'^attachment.js', DynamicJsView.as_view(template_name='js/attachment.js'), name='attachment.js'), - url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'), - url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'), - url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'), url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'), url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'), url(r'^build.js', DynamicJsView.as_view(template_name='js/build.js'), name='build.js'), url(r'^calendar.js', DynamicJsView.as_view(template_name='js/calendar.js'), name='calendar.js'), url(r'^company.js', DynamicJsView.as_view(template_name='js/company.js'), name='company.js'), + url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'), + url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'), + url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'), + url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'), + url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'), + url(r'^nav.js', DynamicJsView.as_view(template_name='js/nav.js'), name='nav.js'), url(r'^order.js', DynamicJsView.as_view(template_name='js/order.js'), name='order.js'), url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'), - url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'), url(r'^report.js', DynamicJsView.as_view(template_name='js/report.js'), name='report.js'), url(r'^stock.js', DynamicJsView.as_view(template_name='js/stock.js'), name='stock.js'), url(r'^tables.js', DynamicJsView.as_view(template_name='js/tables.js'), name='tables.js'), url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/table_filters.js'), name='table_filters.js'), - url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'), ] urlpatterns = [ diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 9da0c88c82..8ba91ee0ab 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -12,7 +12,7 @@ {% block page_content %} -
    +

    {% trans "Sales Order Items" %}

    @@ -29,7 +29,7 @@
    -
    +

    {% trans "Build Orders" %}

    @@ -38,7 +38,7 @@
    -
    +

    {% trans "Attachments" %}

    @@ -47,7 +47,7 @@
    -
    +
    @@ -611,6 +611,11 @@ function setupCallbacks() { } ); }); + + attachNavCallbacks({ + name: 'sales-order', + default: 'order-items' + }); } {% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/so_navbar.html b/InvenTree/order/templates/order/so_navbar.html index b3b0ac30f5..d7571ab691 100644 --- a/InvenTree/order/templates/order/so_navbar.html +++ b/InvenTree/order/templates/order/so_navbar.html @@ -9,29 +9,29 @@
  • -
  • - +
  • -
  • - +
  • -
  • - +
  • -
  • - +
  • -
  • - - - {% trans "Details" %} +
  • + + + {% trans "Order Items" %}
  • {% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %} -
  • +
  • {% trans "Upload File" %}
  • {% endif %} -
  • - +
  • + {% trans "Received Items" %}
  • -
  • - +
  • + {% trans "Attachments" %}
  • -
  • - +
  • + {% trans "Notes" %} diff --git a/InvenTree/order/templates/order/po_received_items.html b/InvenTree/order/templates/order/po_received_items.html deleted file mode 100644 index 487dbd1284..0000000000 --- a/InvenTree/order/templates/order/po_received_items.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "order/order_base.html" %} - -{% load inventree_extras %} -{% load i18n %} -{% load static %} - -{% block menubar %} -{% include 'order/po_navbar.html' with tab='received' %} -{% endblock %} - -{% block heading %} -{% trans "Received Items" %} -{% endblock %} - -{% block details %} - -{% include "stock_table.html" with read_only=True %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadStockTable($("#stock-table"), { - params: { - purchase_order: {{ order.id }}, - part_detail: true, - supplier_part_detail: true, - location_detail: true, - }, - buttons: [ - '#stock-options', - ], - filterkey: "postock" -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index 2e1ec0c39c..8832974510 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -4,31 +4,71 @@ {% load status_codes %} {% load i18n %} {% load static %} +{% load markdownify %} {% block menubar %} {% include 'order/po_navbar.html' with tab='details' %} {% endblock %} -{% block heading %} -{% trans "Purchase Order Items" %} -{% endblock %} +{% block page_content %} - -{% block details %} - - -
    - {% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %} - - {% endif %} +
    +
    +

    {% trans "Purchase Order Items" %}

    +
    +
    +
    + {% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %} + + {% endif %} +
    + + +
    +
    +
    +
    +

    {% trans "Received Items" %}

    +
    +
    + {% include "stock_table.html" with read_only=True %} +
    +
    - -
    +
    +
    +

    {% trans "Purchase Order Attachments" %}

    +
    +
    + {% include "attachment_table.html" %} +
    +
    + +
    +
    +
    +
    +

    {% trans "Order Notes" %}

    +
    +
    +
    + +
    +
    +
    +
    +
    + {{ order.notes | markdownify }} +
    +
    {% endblock %} @@ -36,6 +76,91 @@ {{ block.super }} + $('#edit-notes').click(function() { + constructForm('{% url "api-po-detail" order.pk %}', { + fields: { + notes: { + multiline: true, + } + }, + title: '{% trans "Edit Notes" %}', + reload: true, + }); + }); + + enableDragAndDrop( + '#attachment-dropzone', + '{% url "api-po-attachment-list" %}', + { + data: { + order: {{ order.id }}, + }, + label: 'attachment', + success: function(data, status, xhr) { + location.reload(); + } + } + ); + + loadAttachmentTable( + '{% url "api-po-attachment-list" %}', + { + filters: { + order: {{ order.pk }}, + }, + onEdit: function(pk) { + var url = `/api/order/po/attachment/${pk}/`; + + constructForm(url, { + fields: { + comment: {}, + }, + onSuccess: reloadAttachmentTable, + title: '{% trans "Edit Attachment" %}', + }); + }, + onDelete: function(pk) { + + constructForm(`/api/order/po/attachment/${pk}/`, { + method: 'DELETE', + confirmMessage: '{% trans "Confirm Delete Operation" %}', + title: '{% trans "Delete Attachment" %}', + onSuccess: reloadAttachmentTable, + }); + } + } + ); + + $("#new-attachment").click(function() { + + constructForm('{% url "api-po-attachment-list" %}', { + method: 'POST', + fields: { + attachment: {}, + comment: {}, + order: { + value: {{ order.pk }}, + hidden: true, + }, + }, + reload: true, + title: '{% trans "Add Attachment" %}', + }); + }); + + loadStockTable($("#stock-table"), { + params: { + purchase_order: {{ order.id }}, + part_detail: true, + supplier_part_detail: true, + location_detail: true, + }, + buttons: [ + '#stock-options', + ], + filterkey: "postock" + }); + {% if order.status == PurchaseOrderStatus.PENDING %} $('#new-po-line').click(function() { @@ -301,4 +426,9 @@ $("#po-table").inventreeTable({ ] }); + attachNavCallbacks({ + name: 'purchase-order', + default: 'order-items' + }); + {% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 8ba91ee0ab..a61f6a11ce 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -51,7 +51,7 @@
    -

    {% trans "Notes" %}

    +

    {% trans "Order Notes" %}

    diff --git a/InvenTree/order/templates/order/so_navbar.html b/InvenTree/order/templates/order/so_navbar.html index d7571ab691..710976ed3f 100644 --- a/InvenTree/order/templates/order/so_navbar.html +++ b/InvenTree/order/templates/order/so_navbar.html @@ -9,28 +9,28 @@
  • -
  • {% trans "Order Items" %}
  • -
  • {% trans "Build Orders" %}
  • -
  • {% trans "Attachments" %}
  • -
  • {% trans "Notes" %} diff --git a/InvenTree/order/urls.py b/InvenTree/order/urls.py index 768607a93b..2ce90f1f81 100644 --- a/InvenTree/order/urls.py +++ b/InvenTree/order/urls.py @@ -19,10 +19,6 @@ purchase_order_detail_urls = [ url(r'^upload/', views.PurchaseOrderUpload.as_view(), name='po-upload'), url(r'^export/', views.PurchaseOrderExport.as_view(), name='po-export'), - url(r'^notes/', views.PurchaseOrderNotes.as_view(), name='po-notes'), - - url(r'^received/', views.PurchaseOrderDetail.as_view(template_name='order/po_received_items.html'), name='po-received'), - url(r'^attachments/', views.PurchaseOrderDetail.as_view(template_name='order/po_attachments.html'), name='po-attachments'), url(r'^.*$', views.PurchaseOrderDetail.as_view(), name='po-detail'), ] diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index 7267df1094..be1107f17b 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -13,7 +13,7 @@ from django.core.exceptions import ValidationError from django.urls import reverse from django.http import HttpResponseRedirect from django.utils.translation import ugettext_lazy as _ -from django.views.generic import DetailView, ListView, UpdateView +from django.views.generic import DetailView, ListView from django.views.generic.edit import FormMixin from django.forms import HiddenInput, IntegerField @@ -97,31 +97,6 @@ class SalesOrderDetail(InvenTreeRoleMixin, DetailView): template_name = 'order/sales_order_detail.html' -class PurchaseOrderNotes(InvenTreeRoleMixin, UpdateView): - """ View for updating the 'notes' field of a PurchaseOrder """ - - context_object_name = 'order' - template_name = 'order/order_notes.html' - model = PurchaseOrder - - # Override the default permission roles - role_required = 'purchase_order.view' - - fields = ['notes'] - - def get_success_url(self): - - return reverse('po-notes', kwargs={'pk': self.get_object().id}) - - def get_context_data(self, **kwargs): - - ctx = super().get_context_data(**kwargs) - - ctx['editing'] = str2bool(self.request.GET.get('edit', False)) - - return ctx - - class PurchaseOrderCancel(AjaxUpdateView): """ View for cancelling a purchase order """ diff --git a/InvenTree/templates/js/nav.js b/InvenTree/templates/js/nav.js index a7f4ac8555..ed0e1dcc31 100644 --- a/InvenTree/templates/js/nav.js +++ b/InvenTree/templates/js/nav.js @@ -24,7 +24,7 @@ function attachNavCallbacks(options={}) { var panelClass = options.name || 'unknown'; // Look for a default panel to initialize - var defaultPanel = localStorage.getItem(`selected-panel-${panelClass}`) || options.default; + var defaultPanel = localStorage.getItem(`inventree-selected-panel-${panelClass}`) || options.default; if (defaultPanel) { activatePanel(defaultPanel); @@ -37,7 +37,7 @@ function activatePanel(panelName, options={}) { var panelClass = options.name || 'unknown'; // Save the selected panel - localStorage.setItem(`selected-panel-${panelClass}`, panelName); + localStorage.setItem(`inventree-selected-panel-${panelClass}`, panelName); // First, cause any other panels to "fade out" $('.panel-visible').hide(); @@ -48,13 +48,13 @@ function activatePanel(panelName, options={}) { // Display the panel $(panel).addClass('panel-visible'); - $(panel).fadeIn(50); + $(panel).fadeIn(100); // Un-select all selectors - $('.nav-item').removeClass('active'); + $('.list-group-item').removeClass('active'); // Find the associated selector var select = `#select-${panelName}`; - $(select).parent('.nav-item').addClass('active'); + $(select).parent('.list-group-item').addClass('active'); } \ No newline at end of file From c1c0a262b2e477dfe6182b45e47aa6fdf5ca2a37 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 21:53:48 +1000 Subject: [PATCH 07/35] Refactor Company detail view --- .../templates/company/assigned_stock.html | 38 -- .../templates/company/company_base.html | 27 + .../company/templates/company/detail.html | 467 +++++++++++++++--- .../company/detail_manufacturer_part.html | 119 ----- .../templates/company/detail_stock.html | 49 -- .../company/detail_supplier_part.html | 127 ----- .../company/templates/company/navbar.html | 35 +- .../company/templates/company/notes.html | 47 -- .../templates/company/purchase_orders.html | 56 --- .../templates/company/sales_orders.html | 51 -- InvenTree/company/urls.py | 9 - InvenTree/company/views.py | 24 +- InvenTree/templates/js/nav.js | 31 +- 13 files changed, 478 insertions(+), 602 deletions(-) delete mode 100644 InvenTree/company/templates/company/assigned_stock.html delete mode 100644 InvenTree/company/templates/company/detail_manufacturer_part.html delete mode 100644 InvenTree/company/templates/company/detail_stock.html delete mode 100644 InvenTree/company/templates/company/detail_supplier_part.html delete mode 100644 InvenTree/company/templates/company/notes.html delete mode 100644 InvenTree/company/templates/company/purchase_orders.html delete mode 100644 InvenTree/company/templates/company/sales_orders.html diff --git a/InvenTree/company/templates/company/assigned_stock.html b/InvenTree/company/templates/company/assigned_stock.html deleted file mode 100644 index d64719407b..0000000000 --- a/InvenTree/company/templates/company/assigned_stock.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "company/company_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "company/navbar.html" with tab="assigned" %} -{% endblock %} - -{% block heading %} -{% trans "Assigned Stock" %} -{% endblock %} - -{% block details %} - -
    -
    - -
    -
    - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadStockTable($("#stock-table"), { - params: { - customer: {{ company.id }}, - part_detail: true, - location_detail: true, - }, - url: "{% url 'api-stock-list' %}", - filterKey: "customerstock", -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/company_base.html b/InvenTree/company/templates/company/company_base.html index 8c6b077137..3b8f1e7734 100644 --- a/InvenTree/company/templates/company/company_base.html +++ b/InvenTree/company/templates/company/company_base.html @@ -71,6 +71,17 @@
    {{ company.website }}{% include "clip.html"%} {% endif %} + + + {% trans "Currency" %} + + {% if company.currency %} + {{ company.currency }} + {% else %} + {% trans "Uses default currency" %} + {% endif %} + + {% if company.address %} @@ -99,6 +110,22 @@ {{ company.contact }}{% include "clip.html"%} {% endif %} + + + + {%trans "Manufacturer" %} + {% include "yesnolabel.html" with value=company.is_manufacturer %} + + + + {% trans "Supplier" %} + {% include 'yesnolabel.html' with value=company.is_supplier %} + + + + {% trans "Customer" %} + {% include 'yesnolabel.html' with value=company.is_customer %} + {% endblock %} diff --git a/InvenTree/company/templates/company/detail.html b/InvenTree/company/templates/company/detail.html index 9c3cbfb84a..48f9d9895b 100644 --- a/InvenTree/company/templates/company/detail.html +++ b/InvenTree/company/templates/company/detail.html @@ -1,79 +1,430 @@ {% extends "company/company_base.html" %} {% load static %} {% load i18n %} +{% load markdownify %} {% block menubar %} {% include 'company/navbar.html' with tab='details' %} {% endblock %} -{% block heading %} -{% trans "Company Details" %} -{% endblock %} +{% block page_content %} -{% block details %} -
    -
    - - - - - - - - - {% if company.description %} - - - - - - {% endif %} - - - - - - - - - - +
    + +
    + +
    + +
    + + + {% endif %} + +
    {% trans "Company Name" %}{{ company.name }}{% include "clip.html"%}
    {% trans "Description" %}{{ company.description }}{% include "clip.html"%}
    {% trans "Website" %} - {% if company.website %}{{ company.website }}{% include "clip.html"%} - {% else %}{% trans "No website specified" %} +
    +
    +

    {% trans "Supplier Parts" %}

    +
    +
    + {% if roles.purchase_order.change %} +
    +
    +
    + {% if roles.purchase_order.add %} + {% endif %} -
    {% trans "Currency" %} - {% if company.currency %}{{ company.currency }} - {% else %}{% trans "Uses default currency" %} - {% endif %} -
    -
    - - - - - - - - - - - - - - - - - - -
    {% trans "Manufacturer" %}{% include "yesnolabel.html" with value=company.is_manufacturer %}
    {% trans "Supplier" %}{% include 'yesnolabel.html' with value=company.is_supplier %}
    {% trans "Customer" %}{% include 'yesnolabel.html' with value=company.is_customer %}
    +
    +
    +
    +

    {% trans "Manufacturer Parts" %}

    +
    +
    + {% if roles.purchase_order.change %} +
    +
    +
    + {% if roles.purchase_order.add %} + + {% endif %} +
    + +
    +
    +
    + +
    +
    +
    + {% endif %} + +
    +
    +
    + +
    +
    +

    {% trans "Supplier Stock" %}

    +
    +
    + {% include "stock_table.html" %} +
    +
    + +
    +
    +

    {% trans "Purchase Orders" %}

    +
    +
    + {% if roles.purchase_order.add %} +
    +
    + +
    + +
    +
    +
    + {% endif %} + + +
    +
    +
    + +
    +
    +

    {% trans "Sales Orders" %}

    +
    +
    + {% if roles.sales_order.add %} +
    +
    + +
    + +
    +
    +
    + {% endif %} + + +
    +
    +
    + +
    +
    +

    {% trans "Assigned Stock" %}

    +
    +
    +
    +
    + +
    +
    + +
    + +
    +
    + +
    +
    +
    +
    +

    {% trans "Company Notes" %}

    +
    +
    +
    + +
    +
    +
    +
    +
    + {{ company.notes | markdownify }}
    {% endblock %} + {% block js_ready %} {{ block.super }} + $('#edit-notes').click(function() { + constructForm('{% url "api-company-detail" company.pk %}', { + fields: { + notes: { + multiline: true, + } + }, + title: '{% trans "Edit Notes" %}', + reload: true, + }); + }); + + loadStockTable($("#assigned-stock-table"), { + params: { + customer: {{ company.id }}, + part_detail: true, + location_detail: true, + }, + url: "{% url 'api-stock-list' %}", + filterKey: "customerstock", + }); + + {% if company.is_customer %} + loadSalesOrderTable("#sales-order-table", { + url: "{% url 'api-so-list' %}", + params: { + customer: {{ company.id }}, + } + }); + + $("#new-sales-order").click(function() { + + createSalesOrder({ + customer: {{ company.pk }}, + }); + }); + {% endif %} + + {% if company.is_supplier %} + loadPurchaseOrderTable("#purchase-order-table", { + url: "{% url 'api-po-list' %}", + params: { + supplier: {{ company.id }}, + } + }); + + function newOrder() { + createPurchaseOrder({ + supplier: {{ company.pk }}, + }); + } + + $("#company-order").click(function() { + newOrder(); + }); + + $("#company-order2").click(function() { + newOrder(); + }); + + {% endif %} + + loadStockTable($('#stock-table'), { + url: "{% url 'api-stock-list' %}", + params: { + company: {{ company.id }}, + part_detail: true, + supplier_part_detail: true, + location_detail: true, + }, + buttons: [ + '#stock-options', + ], + filterKey: "companystock", + }); + + $("#stock-export").click(function() { + launchModalForm("{% url 'stock-export-options' %}", { + submit_text: '{% trans "Export" %}', + success: function(response) { + var url = "{% url 'stock-export' %}"; + + url += "?format=" + response.format; + url += "&supplier={{ company.id }}"; + + location.href = url; + }, + }); + }); + + {% if company.is_manufacturer %} + + $("#manufacturer-part-create").click(function () { + + constructForm('{% url "api-manufacturer-part-list" %}', { + fields: { + part: {}, + manufacturer: { + value: {{ company.pk }}, + }, + MPN: { + icon: 'fa-hashtag', + }, + description: {}, + link: { + icon: 'fa-link', + }, + }, + method: 'POST', + title: '{% trans "Add Manufacturer Part" %}', + onSuccess: function() { + $("#part-table").bootstrapTable("refresh"); + } + }); + }); + + loadManufacturerPartTable( + "#part-table", + "{% url 'api-manufacturer-part-list' %}", + { + params: { + part_detail: true, + manufacturer_detail: true, + manufacturer: {{ company.id }}, + }, + } + ); + + linkButtonsToSelection($("#manufacturer-table"), ['#table-options']); + + $("#multi-part-delete").click(function() { + var selections = $("#part-table").bootstrapTable("getSelections"); + + deleteManufacturerParts(selections, { + onSuccess: function() { + $("#part-table").bootstrapTable("refresh"); + } + }); + }); + + $("#multi-part-order").click(function() { + var selections = $("#part-table").bootstrapTable("getSelections"); + + var parts = []; + + selections.forEach(function(item) { + parts.push(item.part); + }); + + launchModalForm("/order/purchase-order/order-parts/", { + data: { + parts: parts, + }, + }); + }); + + {% endif %} + + {% if company.is_supplier %} + + $("#supplier-part-create").click(function () { + launchModalForm( + "{% url 'supplier-part-create' %}", + { + data: { + supplier: {{ company.id }}, + }, + reload: true, + secondary: [ + { + field: 'part', + label: '{% trans "New Part" %}', + title: '{% trans "Create new Part" %}', + url: "{% url 'part-create' %}" + }, + { + field: 'supplier', + label: "{% trans 'New Supplier' %}", + title: "{% trans 'Create new Supplier' %}", + }, + ] + }); + }); + + loadSupplierPartTable( + "#part-table", + "{% url 'api-supplier-part-list' %}", + { + params: { + part_detail: true, + supplier_detail: true, + manufacturer_detail: true, + supplier: {{ company.id }}, + }, + } + ); + + {% endif %} + + $("#multi-part-delete").click(function() { + var selections = $("#part-table").bootstrapTable("getSelections"); + + var parts = []; + + selections.forEach(function(item) { + parts.push(item.pk); + }); + + var url = "{% url 'supplier-part-delete' %}" + + launchModalForm(url, { + data: { + parts: parts, + }, + reload: true, + }); + }); + + $("#multi-part-order").click(function() { + var selections = $("#part-table").bootstrapTable("getSelections"); + + var parts = []; + + selections.forEach(function(item) { + parts.push(item.part); + }); + + launchModalForm("/order/purchase-order/order-parts/", { + data: { + parts: parts, + }, + }); + }); + + attachNavCallbacks({ + panelClass: 'company', + default: 'company-stock' + }); + {% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/detail_manufacturer_part.html b/InvenTree/company/templates/company/detail_manufacturer_part.html deleted file mode 100644 index 0ff261ec67..0000000000 --- a/InvenTree/company/templates/company/detail_manufacturer_part.html +++ /dev/null @@ -1,119 +0,0 @@ -{% extends "company/company_base.html" %} -{% load static %} -{% load i18n %} -{% load inventree_extras %} - -{% block menubar %} -{% include 'company/navbar.html' with tab='manufacturer_parts' %} -{% endblock %} - -{% block heading %} -{% trans "Manufacturer Parts" %} -{% endblock %} - - -{% block details %} - -{% if roles.purchase_order.change %} -
    -
    -
    - {% if roles.purchase_order.add %} - - {% endif %} -
    - -
    -
    -
    - -
    -
    -
    -{% endif %} - -
    - -{% endblock %} -{% block js_ready %} -{{ block.super }} - - $("#manufacturer-part-create").click(function () { - - constructForm('{% url "api-manufacturer-part-list" %}', { - fields: { - part: {}, - manufacturer: { - value: {{ company.pk }}, - }, - MPN: { - icon: 'fa-hashtag', - }, - description: {}, - link: { - icon: 'fa-link', - }, - }, - method: 'POST', - title: '{% trans "Add Manufacturer Part" %}', - onSuccess: function() { - $("#part-table").bootstrapTable("refresh"); - } - }); - }); - - loadManufacturerPartTable( - "#part-table", - "{% url 'api-manufacturer-part-list' %}", - { - params: { - part_detail: true, - manufacturer_detail: true, - manufacturer: {{ company.id }}, - }, - } - ); - - linkButtonsToSelection($("#manufacturer-table"), ['#table-options']); - - $("#multi-part-delete").click(function() { - var selections = $("#part-table").bootstrapTable("getSelections"); - - deleteManufacturerParts(selections, { - onSuccess: function() { - $("#part-table").bootstrapTable("refresh"); - } - }); - }); - - $("#multi-part-order").click(function() { - var selections = $("#part-table").bootstrapTable("getSelections"); - - var parts = []; - - selections.forEach(function(item) { - parts.push(item.part); - }); - - launchModalForm("/order/purchase-order/order-parts/", { - data: { - parts: parts, - }, - }); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/detail_stock.html b/InvenTree/company/templates/company/detail_stock.html deleted file mode 100644 index 87f88bb550..0000000000 --- a/InvenTree/company/templates/company/detail_stock.html +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "company/company_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "company/navbar.html" with tab='stock' %} -{% endblock %} - -{% block heading %} -{% trans "Supplier Stock" %} -{% endblock %} - -{% block details %} - -{% include "stock_table.html" %} - -{% endblock %} -{% block js_ready %} -{{ block.super }} - - loadStockTable($('#stock-table'), { - url: "{% url 'api-stock-list' %}", - params: { - company: {{ company.id }}, - part_detail: true, - supplier_part_detail: true, - location_detail: true, - }, - buttons: [ - '#stock-options', - ], - filterKey: "companystock", - }); - - $("#stock-export").click(function() { - launchModalForm("{% url 'stock-export-options' %}", { - submit_text: '{% trans "Export" %}', - success: function(response) { - var url = "{% url 'stock-export' %}"; - - url += "?format=" + response.format; - url += "&supplier={{ company.id }}"; - - location.href = url; - }, - }); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/detail_supplier_part.html b/InvenTree/company/templates/company/detail_supplier_part.html deleted file mode 100644 index 7cf9b66a11..0000000000 --- a/InvenTree/company/templates/company/detail_supplier_part.html +++ /dev/null @@ -1,127 +0,0 @@ -{% extends "company/company_base.html" %} -{% load static %} -{% load i18n %} -{% load inventree_extras %} - -{% block menubar %} -{% include 'company/navbar.html' with tab='supplier_parts' %} -{% endblock %} - -{% block heading %} -{% trans "Supplier Parts" %} -{% endblock %} - - -{% block details %} -{% if roles.purchase_order.change %} -
    -
    -
    - {% if roles.purchase_order.add %} - - {% endif %} -
    - -
    -
    -
    - -
    -
    -
    -{% endif %} - - -
    - -{% endblock %} -{% block js_ready %} -{{ block.super }} - - $("#supplier-part-create").click(function () { - launchModalForm( - "{% url 'supplier-part-create' %}", - { - data: { - supplier: {{ company.id }}, - }, - reload: true, - secondary: [ - { - field: 'part', - label: '{% trans "New Part" %}', - title: '{% trans "Create new Part" %}', - url: "{% url 'part-create' %}" - }, - { - field: 'supplier', - label: "{% trans 'New Supplier' %}", - title: "{% trans 'Create new Supplier' %}", - }, - ] - }); - }); - - loadSupplierPartTable( - "#part-table", - "{% url 'api-supplier-part-list' %}", - { - params: { - part_detail: true, - supplier_detail: true, - manufacturer_detail: true, - supplier: {{ company.id }}, - }, - } - ); - - $("#multi-part-delete").click(function() { - var selections = $("#part-table").bootstrapTable("getSelections"); - - var parts = []; - - selections.forEach(function(item) { - parts.push(item.pk); - }); - - var url = "{% url 'supplier-part-delete' %}" - - launchModalForm(url, { - data: { - parts: parts, - }, - reload: true, - }); - }); - - $("#multi-part-order").click(function() { - var selections = $("#part-table").bootstrapTable("getSelections"); - - var parts = []; - - selections.forEach(function(item) { - parts.push(item.part); - }); - - launchModalForm("/order/purchase-order/order-parts/", { - data: { - parts: parts, - }, - }); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/navbar.html b/InvenTree/company/templates/company/navbar.html index 715d448b0f..025b1c6b4a 100644 --- a/InvenTree/company/templates/company/navbar.html +++ b/InvenTree/company/templates/company/navbar.html @@ -9,16 +9,9 @@
  • -
  • - - - {% trans "Details" %} - -
  • - {% if company.is_manufacturer %} -
  • - +
  • + {% trans "Manufactured Parts" %} @@ -26,8 +19,8 @@ {% endif %} {% if company.is_supplier or company.is_manufacturer %} -
  • - +
  • + {% trans "Supplied Parts" %} @@ -35,8 +28,8 @@ {% endif %} {% if company.is_manufacturer or company.is_supplier %} -
  • - +
  • + {% trans "Stock" %} @@ -44,8 +37,8 @@ {% endif %} {% if company.is_supplier %} -
  • - +
  • + {% trans "Purchase Orders" %} @@ -53,22 +46,22 @@ {% endif %} {% if company.is_customer %} -
  • - +
  • + {% trans "Sales Orders" %}
  • -
  • - +
  • + {% trans "Assigned Stock" %}
  • {% endif %} -
  • - +
  • + {% trans "Notes" %} diff --git a/InvenTree/company/templates/company/notes.html b/InvenTree/company/templates/company/notes.html deleted file mode 100644 index 6b0e65e2d0..0000000000 --- a/InvenTree/company/templates/company/notes.html +++ /dev/null @@ -1,47 +0,0 @@ -{% extends "company/company_base.html" %} -{% load static %} -{% load i18n %} -{% load markdownify %} - -{% block menubar %} -{% include 'company/navbar.html' with tab='notes' %} -{% endblock %} - -{% block heading %} -{% trans "Company Notes" %} -{% if not editing %} - -{% endif %} -{% endblock %} - -{% block details %} -{% if editing %} -
    - {% csrf_token %} - - {{ form }} -
    - - -
    - -{{ form.media }} - -{% else %} - -{{ company.notes | markdownify }} -{% endif %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -{% if editing %} -{% else %} -$("#edit-notes").click(function() { - location.href = "{% url 'company-notes' company.id %}?edit=1"; -}); -{% endif %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/purchase_orders.html b/InvenTree/company/templates/company/purchase_orders.html deleted file mode 100644 index f23d360a8f..0000000000 --- a/InvenTree/company/templates/company/purchase_orders.html +++ /dev/null @@ -1,56 +0,0 @@ -{% extends "company/company_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'company/navbar.html' with tab='po' %} -{% endblock %} - -{% block heading %} -{% trans "Purchase Orders" %} -{% endblock %} - -{% block details %} - -{% if roles.purchase_order.add %} -
    -
    - -
    - -
    -
    -
    -{% endif %} - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - loadPurchaseOrderTable("#purchase-order-table", { - url: "{% url 'api-po-list' %}", - params: { - supplier: {{ company.id }}, - } - }); - - function newOrder() { - createPurchaseOrder({ - supplier: {{ company.pk }}, - }); - } - - $("#company-order").click(function() { - newOrder(); - }); - - $("#company-order2").click(function() { - newOrder(); - }); - -{% endblock %} diff --git a/InvenTree/company/templates/company/sales_orders.html b/InvenTree/company/templates/company/sales_orders.html deleted file mode 100644 index c21a9afc21..0000000000 --- a/InvenTree/company/templates/company/sales_orders.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends "company/company_base.html" %} -{% load static %} -{% load i18n %} - - -{% block menubar %} -{% include 'company/navbar.html' with tab='so' %} -{% endblock %} - -{% block heading %} -{% trans "Sales Orders" %} -{% endblock %} - -{% block details %} - -{% if roles.sales_order.add %} -
    -
    - -
    - -
    -
    -
    -{% endif %} - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - loadSalesOrderTable("#sales-order-table", { - url: "{% url 'api-so-list' %}", - params: { - customer: {{ company.id }}, - } - }); - - $("#new-sales-order").click(function() { - - createSalesOrder({ - customer: {{ company.pk }}, - }); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index e9e125d9e4..4f844176ee 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -8,15 +8,6 @@ from . import views company_detail_urls = [ - # url(r'orders/?', views.CompanyDetail.as_view(template_name='company/orders.html'), name='company-detail-orders'), - - url(r'^supplier-parts/', views.CompanyDetail.as_view(template_name='company/detail_supplier_part.html'), name='company-detail-supplier-parts'), - url(r'^manufacturer-parts/', views.CompanyDetail.as_view(template_name='company/detail_manufacturer_part.html'), name='company-detail-manufacturer-parts'), - url(r'^stock/', views.CompanyDetail.as_view(template_name='company/detail_stock.html'), name='company-detail-stock'), - url(r'^purchase-orders/', views.CompanyDetail.as_view(template_name='company/purchase_orders.html'), name='company-detail-purchase-orders'), - url(r'^assigned-stock/', views.CompanyDetail.as_view(template_name='company/assigned_stock.html'), name='company-detail-assigned-stock'), - url(r'^sales-orders/', views.CompanyDetail.as_view(template_name='company/sales_orders.html'), name='company-detail-sales-orders'), - url(r'^notes/', views.CompanyNotes.as_view(), name='company-notes'), url(r'^thumb-download/', views.CompanyImageDownloadFromURL.as_view(), name='company-image-download'), diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py index 03fe03d411..ab6344e810 100644 --- a/InvenTree/company/views.py +++ b/InvenTree/company/views.py @@ -7,7 +7,7 @@ Django views for interacting with Company app from __future__ import unicode_literals from django.utils.translation import ugettext_lazy as _ -from django.views.generic import DetailView, ListView, UpdateView +from django.views.generic import DetailView, ListView from django.urls import reverse from django.forms import HiddenInput @@ -113,28 +113,6 @@ class CompanyIndex(InvenTreeRoleMixin, ListView): return queryset -class CompanyNotes(UpdateView): - """ View for editing the 'notes' field of a Company object. - """ - - context_object_name = 'company' - template_name = 'company/notes.html' - model = Company - fields = ['notes'] - permission_required = 'company.view_company' - - def get_success_url(self): - return reverse('company-notes', kwargs={'pk': self.get_object().id}) - - def get_context_data(self, **kwargs): - - ctx = super().get_context_data(**kwargs) - - ctx['editing'] = str2bool(self.request.GET.get('edit', '')) - - return ctx - - class CompanyDetail(DetailView): """ Detail view for Company object """ context_obect_name = 'company' diff --git a/InvenTree/templates/js/nav.js b/InvenTree/templates/js/nav.js index ed0e1dcc31..e8207f9251 100644 --- a/InvenTree/templates/js/nav.js +++ b/InvenTree/templates/js/nav.js @@ -36,15 +36,38 @@ function activatePanel(panelName, options={}) { var panelClass = options.name || 'unknown'; - // Save the selected panel - localStorage.setItem(`inventree-selected-panel-${panelClass}`, panelName); - // First, cause any other panels to "fade out" $('.panel-visible').hide(); $('.panel-visible').removeClass('panel-visible'); - + // Find the target panel var panel = `#panel-${panelName}`; + var select = `#select-${panelName}`; + + // Check that the selected panel (and select) exist + if ($(panel).length && $(select).length) { + // Yep, both are displayed + } else { + // Either the select or the panel are not displayed! + // Iterate through the available 'select' elements until one matches + panelName = null; + + console.log("no match for panel:", panelName); + + $('.nav-toggle').each(function(item) { + var panel_name = $(this).attr('id').replace('select-', ''); + + console.log("checking:", panel_name); + + if ($(`#panel-${panel_name}`).length && (panelName == null)) { + console.log("found match -", panel_name); + panelName = panel_name; + } + }); + } + + // Save the selected panel + localStorage.setItem(`inventree-selected-panel-${panelClass}`, panelName); // Display the panel $(panel).addClass('panel-visible'); From 8dde89e781b9b6009b48fb7489522dc2d9a1de96 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 21:57:49 +1000 Subject: [PATCH 08/35] Table fixes --- .../company/templates/company/detail.html | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/InvenTree/company/templates/company/detail.html b/InvenTree/company/templates/company/detail.html index 48f9d9895b..9bc47e3b63 100644 --- a/InvenTree/company/templates/company/detail.html +++ b/InvenTree/company/templates/company/detail.html @@ -15,7 +15,7 @@
    {% if roles.purchase_order.change %} -
    +
    {% if roles.purchase_order.add %} @@ -46,7 +46,7 @@
    {% endif %} - +
    @@ -57,7 +57,7 @@
    {% if roles.purchase_order.change %} -
    +
    {% if roles.purchase_order.add %} @@ -87,7 +87,7 @@
    {% endif %} - +
    @@ -107,7 +107,7 @@
    {% if roles.purchase_order.add %} -
    +
    @@ -118,7 +118,7 @@
    {% endif %} - +
    @@ -129,7 +129,7 @@
    {% if roles.sales_order.add %} -
    +
    {% endif %} - +
    @@ -151,13 +151,13 @@

    {% trans "Assigned Stock" %}

    -
    +
    -
    +
    @@ -373,7 +373,7 @@ }); loadSupplierPartTable( - "#part-table", + "#supplier-part-table", "{% url 'api-supplier-part-list' %}", { params: { From 8fed3b3522df92d301b46c41bbf1ec9aeee380c9 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 13 Jul 2021 22:03:49 +1000 Subject: [PATCH 09/35] Typo fix --- InvenTree/company/templates/company/detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/company/templates/company/detail.html b/InvenTree/company/templates/company/detail.html index 9bc47e3b63..1f2bcf3784 100644 --- a/InvenTree/company/templates/company/detail.html +++ b/InvenTree/company/templates/company/detail.html @@ -423,7 +423,7 @@ }); attachNavCallbacks({ - panelClass: 'company', + name: 'company', default: 'company-stock' }); From 06678577547e7f89310a5979941583c10a42b014 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 12:04:48 +1000 Subject: [PATCH 10/35] Refactor part base display --- InvenTree/part/templates/part/detail.html | 216 +------------------ InvenTree/part/templates/part/part_base.html | 58 +++-- 2 files changed, 47 insertions(+), 227 deletions(-) diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 8a78eb85a5..ecfddf66c5 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -18,131 +18,6 @@
    - - - - - - {% if part.IPN %} - - - - - - {% endif %} - {% if part.revision %} - - - - - - {% endif %} - {% if part.trackable %} - - - - - - {% endif %} - - - - - - {% if part.variant_of %} - - - - - - {% endif %} - {% if part.keywords %} - - - - - - {% endif %} - - - - - - {% if part.link %} - - - - - - {% endif %} - {% if part.default_location %} - - - - - - {% endif %} - {% if part.default_supplier %} - - - - - - {% endif %} - {% if part.units %} - - - - - - {% endif %} - {% if part.minimum_stock > 0 %} - - - - - - {% endif %} - {% if part.default_expiry > 0 %} - - - - - - {% endif %} - - - - - - {% if part.creation_user %} - - - - - - {% endif %} - {% if part.responsible %} - - - - - - {% endif %} - - @@ -171,96 +46,7 @@
    {% trans "Part name" %}{{ part.name }}{% include "clip.html"%}
    {% trans "IPN" %}{{ part.IPN }}{% include "clip.html"%}
    {% trans "Revision" %}{{ part.revision }}{% include "clip.html"%}
    {% trans "Latest Serial Number" %} - {% if part.getLatestSerialNumber %} - {{ part.getLatestSerialNumber }}{% include "clip.html"%} - {% else %} - {% trans "No serial numbers recorded" %} - {% endif %} -
    {% trans "Description" %}{{ part.description }}{% include "clip.html"%}
    {% trans "Variant Of" %}{{ part.variant_of.full_name }}{% include "clip.html"%}
    {% trans "Keywords" %}{{ part.keywords }}{% include "clip.html"%}
    {% trans "Category" %} - {% if part.category %} - {{ part.category.pathstring }}{% include "clip.html"%} - {% endif %} -
    {% trans "External Link" %}{{ part.link }}{% include "clip.html"%}
    {% trans "Default Location" %}{{ part.default_location.pathstring }}{% include "clip.html"%}
    {% trans "Default Supplier" %} - {{ part.default_supplier.supplier.name }} | {{ part.default_supplier.SKU }} - {% include "clip.html"%}
    {% trans "Units" %}{{ part.units }}{% include "clip.html"%}
    {% trans "Minimum Stock" %}{{ part.minimum_stock }}
    {% trans "Stock Expiry Time" %}{{ part.default_expiry }} {% trans "days" %}
    {% trans "Creation Date" %}{{ part.creation_date }}
    {% trans "Created By" %}{{ part.creation_user }}
    {% trans "Responsible User" %}{{ part.responsible }}
    - - - - - - - {% if part.virtual %} - - {% else %} - - {% endif %} - - - - - - {% if part.is_template %} - - {% else %} - - {% endif %} - - - - - - {% if part.assembly %} - - {% else %} - - {% endif %} - - - - - - {% if part.component %} - - {% else %} - - {% endif %} - - - - - - {% if part.trackable %} - - {% else %} - - {% endif %} - - - - - - {% if part.purchaseable %} - - {% else %} - - {% endif %} - - - - - - {% if part.salable %} - - {% else %} - - {% endif %} - - - - - - - {% if part.active %} - - {% else %} - - {% endif %} - -
    {% trans "Virtual" %}{% include "slide.html" with state=part.virtual field='virtual' %}{% trans "Part is virtual (not a physical part)" %}{% trans "Part is not a virtual part" %}
    {% trans "Template" %}{% include "slide.html" with state=part.is_template field='is_template' %}{% trans "Part is a template part (variants can be made from this part)" %}{% trans "Part is not a template part" %}
    {% trans "Assembly" %}{% include "slide.html" with state=part.assembly field='assembly' %}{% trans "Part can be assembled from other parts" %}{% trans "Part cannot be assembled from other parts" %}
    {% trans "Component" %}{% include "slide.html" with state=part.component field='component' %}{% trans "Part can be used in assemblies" %}{% trans "Part cannot be used in assemblies" %}
    {% trans "Trackable" %}{% include "slide.html" with state=part.trackable field='trackable' %}{% trans "Part stock is tracked by serial number" %}{% trans "Part stock is not tracked by serial number" %}
    {% trans "Purchaseable" %}{% include "slide.html" with state=part.purchaseable field='purchaseable' %}{% trans "Part can be purchased from external suppliers" %}{% trans "Part can be purchased from external suppliers" %}
    {% trans "Salable" %}{% include "slide.html" with state=part.salable field='salable' %}{% trans "Part can be sold to customers" %}{% trans "Part cannot be sold to customers" %}
    - {% if part.active %} - - {% else %} - - {% endif %} - {% trans "Active" %}{% include "slide.html" with state=part.active field='active' disabled=False %}{% trans "Part is active" %}{% trans "Part is not active" %}
    +
    diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index 391f6d1d35..2fdcbb278b 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -27,7 +27,34 @@ {% endif %} + {% if part.description %}

    {{ part.description }}

    + {% endif %} +

    +

    + {% if part.virtual %} + + {% endif %} + {% if part.is_template %} + + {% endif %} + {% if part.assembly %} + + {% endif %} + {% if part.component %} + + {% endif %} + {% if part.trackable %} + + {% endif %} + {% if part.purchaseable %} + + {% endif %} + {% if part.salable %} + + {% endif %} +
    +

    - {% if part.IPN %} + {% if part.keywords %} - - - + + + {% endif %} {% if part.link %} @@ -112,7 +139,22 @@ {% endif %} + + + + {% if part.trackable and part.getLatestSerialNumber %} + + + + + + {% endif %}
    {% trans "IPN" %}{{ part.IPN }}{% trans "Keywords" %}{{ part.keywords }}
    {% trans "Creation Date" %} + {{ part.creation_date }} + {% if part.creation_user %} + {{ part.creation_user }} + {% endif %} +
    {% trans "Latest Serial Number" %}{{ part.getLatestSerialNumber }}{% include "clip.html"%}
    @@ -197,14 +239,6 @@ {% endif %} {% endif %} {% endif %} - {% if part.trackable and part.getLatestSerialNumber %} - - - - {% trans "Latest Serial Number" %} - {{ part.getLatestSerialNumber }}{% include "clip.html"%} - - {% endif %} From 2d2ad91545477a7186ca6b46c8cbe0a888f96a4d Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 12:52:36 +1000 Subject: [PATCH 11/35] Move "stock" part view --- .../order/purchase_order_detail.html | 3 +- .../templates/order/sales_order_detail.html | 2 +- InvenTree/part/templates/part/detail.html | 160 +++++++++++------- InvenTree/part/templates/part/navbar.html | 76 +++++---- InvenTree/part/templates/part/part_base.html | 25 +-- InvenTree/part/templates/part/stock.html | 77 --------- InvenTree/part/urls.py | 1 - .../stock/templates/stock/item_base.html | 4 +- 8 files changed, 150 insertions(+), 198 deletions(-) delete mode 100644 InvenTree/part/templates/part/stock.html diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index 8832974510..8c9feab452 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -7,8 +7,7 @@ {% load markdownify %} {% block menubar %} -{% include 'order/po_navbar.html' with tab='details' %} - +{% include 'order/po_navbar.html' %} {% endblock %} {% block page_content %} diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index a61f6a11ce..8ada362092 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -7,7 +7,7 @@ {% load markdownify %} {% block menubar %} -{% include "order/so_navbar.html" with tab='details' %} +{% include "order/so_navbar.html" %} {% endblock %} {% block page_content %} diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index ecfddf66c5..c24690c868 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -5,84 +5,70 @@ {% block menubar %} -{% include 'part/navbar.html' with tab='details' %} +{% include 'part/navbar.html' %} {% endblock %} -{% block heading %} -{% trans "Part Details" %} -{% endblock %} +{% block page_content %} -{% block details %} +
    +
    +

    {% trans "Part Stock" %}

    +
    +
    + {% if part.is_template %} +
    + {% blocktrans with full_name=part.full_name%}Showing stock for all variants of {{full_name}}{% endblocktrans %} +
    + {% endif %} + {% include "stock_table.html" %} +
    +
    -
    -
    - - - - - - - - - - - - -
    - {% trans "Notes" %} - +
    +
    +
    +
    +

    {% trans "Notes" %}

    +
    +
    -
    - {% if part.notes %} -
    - {{ part.notes | markdownify }} -
    - {% endif %} -
    +
    +
    -
    - +
    + {{ part.notes | markdownify }}
    -{% endblock %} - -{% block post_content_panel %} - -
    -
    -
    -
    -

    {% trans "Parameters" %}

    -
    -
    -
    -
    - {% if roles.part.add %} - - {% endif %} -
    -
    -
    -
    -
    +
    +
    +

    {% trans "Parameters" %}

    -
    -
    -
    -

    {% trans "Attachments" %}

    -
    -
    - {% include "attachment_table.html" %} +
    +
    +
    + {% if roles.part.add %} + + {% endif %}
    +
    +
    +
    + +
    +
    +

    {% trans "Attachments" %}

    +
    +
    + {% include "attachment_table.html" %}
    @@ -95,6 +81,53 @@ {% block js_ready %} {{ block.super }} + $('#add-stock-item').click(function () { + createNewStockItem({ + reload: true, + data: { + part: {{ part.id }}, + } + }); + }); + + loadStockTable($("#stock-table"), { + params: { + part: {{ part.id }}, + location_detail: true, + part_detail: true, + supplier_part_detail: true, + }, + groupByField: 'location', + buttons: [ + '#stock-options', + ], + url: "{% url 'api-stock-list' %}", + }); + + $("#stock-export").click(function() { + launchModalForm("{% url 'stock-export-options' %}", { + submit_text: "{% trans 'Export' %}", + success: function(response) { + var url = "{% url 'stock-export' %}"; + + url += "?format=" + response.format; + url += "&cascade=" + response.cascade; + url += "&part={{ part.id }}"; + + location.href = url; + }, + }); + }); + + $('#item-create').click(function () { + createNewStockItem({ + reload: true, + data: { + part: {{ part.id }}, + } + }); + }); + $('#edit-notes').click(function() { constructForm('{% url "api-part-detail" part.pk %}', { fields: { @@ -239,4 +272,9 @@ ) }); + attachNavCallbacks({ + name: 'part', + default: 'part-stock' + }); + {% endblock %} diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index e8617dc677..d634229500 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -11,46 +11,44 @@
  • -
  • - - - - {% trans "Details" %} - +
  • + + + {% trans "Parameters" %}
  • {% if part.is_template %} -
  • - +
  • + {% trans "Variants" %}
  • {% endif %} -
  • - +
  • + {% trans "Stock" %}
  • {% if part.component or part.salable %} -
  • - +
  • + {% trans "Allocations" %}
  • {% endif %} {% if part.assembly %} -
  • - +
  • + {% trans "Bill of Materials" %}
  • {% if roles.build.view %} -
  • - +
  • + {% trans "Build Orders" %} @@ -58,55 +56,73 @@ {% endif %} {% endif %} {% if part.component %} -
  • - +
  • + {% trans "Used In" %}
  • {% endif %} -
  • - +
  • + {% trans "Prices" %}
  • {% if part.purchaseable and roles.purchase_order.view %} -
  • - +
  • + {% trans "Suppliers" %}
  • -
  • - +
  • + + + {% trans "Manufacturers" %} + +
  • +
  • + {% trans "Purchase Orders" %}
  • {% endif %} {% if roles.sales_order.view %} -
  • - +
  • + {% trans "Sales Orders" %}
  • {% endif %} {% if part.trackable %} -
  • - +
  • + {% trans "Test Templates" %}
  • {% endif %} {% if show_related %} -
  • - +
  • + {% trans "Related Parts" %}
  • {% endif %} +
  • + + + {% trans "Attachments" %} + +
  • +
  • + + + {% trans "Notes" %} + +
  • diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index 2fdcbb278b..e7ec892628 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -245,30 +245,7 @@ -{% block pre_content_panel %} - -{% endblock %} - -
    - - -
    -

    - {% block heading %} - - {% endblock %} -

    -
    - -
    - {% block details %} - - {% endblock %} -
    - -
    -{% block post_content_panel %} - +{% block page_content %} {% endblock %} {% endblock %} diff --git a/InvenTree/part/templates/part/stock.html b/InvenTree/part/templates/part/stock.html deleted file mode 100644 index ea745708dd..0000000000 --- a/InvenTree/part/templates/part/stock.html +++ /dev/null @@ -1,77 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='stock' %} -{% endblock %} - -{% block heading %} -{% trans "Part Stock" %} -{% endblock %} - -{% block details %} -{% if part.is_template %} -
    - {% blocktrans with full_name=part.full_name%}Showing stock for all variants of {{full_name}}{% endblocktrans %} -
    -{% endif %} - -{% include "stock_table.html" %} - -{% endblock %} - -{% block js_load %} -{{ block.super }} -{% endblock %} -{% block js_ready %} -{{ block.super }} - - $('#add-stock-item').click(function () { - createNewStockItem({ - reload: true, - data: { - part: {{ part.id }}, - } - }); - }); - - loadStockTable($("#stock-table"), { - params: { - part: {{ part.id }}, - location_detail: true, - part_detail: true, - supplier_part_detail: true, - }, - groupByField: 'location', - buttons: [ - '#stock-options', - ], - url: "{% url 'api-stock-list' %}", - }); - - $("#stock-export").click(function() { - launchModalForm("{% url 'stock-export-options' %}", { - submit_text: "{% trans 'Export' %}", - success: function(response) { - var url = "{% url 'stock-export' %}"; - - url += "?format=" + response.format; - url += "&cascade=" + response.cascade; - url += "&part={{ part.id }}"; - - location.href = url; - }, - }); - }); - - $('#item-create').click(function () { - createNewStockItem({ - reload: true, - data: { - part: {{ part.id }}, - } - }); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 1fa7227f5e..8248d7575a 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -49,7 +49,6 @@ part_detail_urls = [ url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'), url(r'^variants/?', views.PartDetail.as_view(template_name='part/variants.html'), name='part-variants'), - url(r'^stock/?', views.PartDetail.as_view(template_name='part/stock.html'), name='part-stock'), url(r'^allocation/?', views.PartDetail.as_view(template_name='part/allocation.html'), name='part-allocation'), url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'), url(r'^build/?', views.PartDetail.as_view(template_name='part/build.html'), name='part-build'), diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index 979c54ba28..ea57b981d8 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -235,7 +235,7 @@ {% trans "Base Part" %} {% if roles.part.view %} - + {% endif %} {{ item.part.full_name }} {% if roles.part.view %} @@ -561,7 +561,7 @@ $("#stock-delete").click(function () { launchModalForm( "{% url 'stock-item-delete' item.id %}", { - redirect: "{% url 'part-stock' item.part.id %}" + redirect: "{% url 'part-detail' item.part.id %}" } ); }); From 1a30a5bc16728db9f1155118e74654aff6001b19 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 12:56:17 +1000 Subject: [PATCH 12/35] Merge "test template" page --- InvenTree/part/templates/part/detail.html | 84 ++++++++++++++++ InvenTree/part/templates/part/part_tests.html | 96 ------------------- 2 files changed, 84 insertions(+), 96 deletions(-) delete mode 100644 InvenTree/part/templates/part/part_tests.html diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index c24690c868..1f217a872c 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -24,6 +24,26 @@ +
    +
    +

    {% trans "Part Test Templates" %}

    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    +
    @@ -81,6 +101,70 @@ {% block js_ready %} {{ block.super }} + loadPartTestTemplateTable( + $("#test-template-table"), + { + part: {{ part.pk }}, + params: { + part: {{ part.pk }}, + } + } + ); + + function reloadTable() { + $("#test-template-table").bootstrapTable("refresh"); + } + + $("#add-test-template").click(function() { + + constructForm('{% url "api-part-test-template-list" %}', { + method: 'POST', + fields: { + test_name: {}, + description: {}, + required: {}, + requires_value: {}, + requires_attachment: {}, + part: { + value: {{ part.pk }}, + hidden: true, + } + }, + title: '{% trans "Add Test Result Template" %}', + onSuccess: reloadTable + }); + }); + + $("#test-template-table").on('click', '.button-test-edit', function() { + var pk = $(this).attr('pk'); + + var url = `/api/part/test-template/${pk}/`; + + constructForm(url, { + fields: { + test_name: {}, + description: {}, + required: {}, + requires_value: {}, + requires_attachment: {}, + }, + title: '{% trans "Edit Test Result Template" %}', + onSuccess: reloadTable, + }); + }); + + $("#test-template-table").on('click', '.button-test-delete', function() { + var pk = $(this).attr('pk'); + + var url = `/api/part/test-template/${pk}/`; + + constructForm(url, { + method: 'DELETE', + title: '{% trans "Delete Test Result Template" %}', + onSuccess: reloadTable, + }); + }); + $('#add-stock-item').click(function () { createNewStockItem({ reload: true, diff --git a/InvenTree/part/templates/part/part_tests.html b/InvenTree/part/templates/part/part_tests.html deleted file mode 100644 index 3c131aa1d4..0000000000 --- a/InvenTree/part/templates/part/part_tests.html +++ /dev/null @@ -1,96 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='tests' %} -{% endblock %} - -{% block heading %} -{% trans "Part Test Templates" %} -{% endblock %} - -{% block details %} -
    -
    -
    - -
    -
    - -
    -
    -
    - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadPartTestTemplateTable( - $("#test-template-table"), - { - part: {{ part.pk }}, - params: { - part: {{ part.pk }}, - } - } -); - -function reloadTable() { - $("#test-template-table").bootstrapTable("refresh"); -} - -$("#add-test-template").click(function() { - - constructForm('{% url "api-part-test-template-list" %}', { - method: 'POST', - fields: { - test_name: {}, - description: {}, - required: {}, - requires_value: {}, - requires_attachment: {}, - part: { - value: {{ part.pk }}, - hidden: true, - } - }, - title: '{% trans "Add Test Result Template" %}', - onSuccess: reloadTable - }); -}); - -$("#test-template-table").on('click', '.button-test-edit', function() { - var pk = $(this).attr('pk'); - - var url = `/api/part/test-template/${pk}/`; - - constructForm(url, { - fields: { - test_name: {}, - description: {}, - required: {}, - requires_value: {}, - requires_attachment: {}, - }, - title: '{% trans "Edit Test Result Template" %}', - onSuccess: reloadTable, - }); -}); - -$("#test-template-table").on('click', '.button-test-delete', function() { - var pk = $(this).attr('pk'); - - var url = `/api/part/test-template/${pk}/`; - - constructForm(url, { - method: 'DELETE', - title: '{% trans "Delete Test Result Template" %}', - onSuccess: reloadTable, - }); -}); - -{% endblock %} \ No newline at end of file From 3786454e4c164035923600ea659e2477a10deec5 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 12:56:26 +1000 Subject: [PATCH 13/35] Remove URL --- InvenTree/part/urls.py | 1 - 1 file changed, 1 deletion(-) diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 8248d7575a..8aa254e126 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -57,7 +57,6 @@ part_detail_urls = [ url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'), url(r'^orders/?', views.PartDetail.as_view(template_name='part/orders.html'), name='part-orders'), url(r'^sales-orders/', views.PartDetail.as_view(template_name='part/sales_orders.html'), name='part-sales-orders'), - url(r'^tests/', views.PartDetail.as_view(template_name='part/part_tests.html'), name='part-test-templates'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'), From 352a58b37328491d6482dbe86650a5613bdebc30 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 13:41:26 +1000 Subject: [PATCH 14/35] Can select nav based on URL query parameter --- InvenTree/InvenTree/static/css/inventree.css | 2 +- .../examples/bootstrap-2.3.2/css/bootstrap.css | 2 +- InvenTree/templates/js/api.js | 8 ++++++++ InvenTree/templates/js/nav.js | 11 +++++++++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index 1f01037f28..b538aaad04 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -781,7 +781,7 @@ input[type="submit"] { } .sidenav .list-group-item.active { - background-color: #ddd; + background-color: #bbab8b; border-color: #ccc; } diff --git a/InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/css/bootstrap.css b/InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/css/bootstrap.css index 5b7fe7e856..c3de0d956c 100644 --- a/InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/css/bootstrap.css +++ b/InvenTree/InvenTree/static/treegrid/examples/bootstrap-2.3.2/css/bootstrap.css @@ -4678,7 +4678,7 @@ input[type="submit"].btn.btn-mini { .navbar .btn-navbar:active, .navbar .btn-navbar.active { - background-color: #cccccc \9; + background-color: #ba8; } .navbar .btn-navbar .icon-bar { diff --git a/InvenTree/templates/js/api.js b/InvenTree/templates/js/api.js index 93fa5a41e4..8169671836 100644 --- a/InvenTree/templates/js/api.js +++ b/InvenTree/templates/js/api.js @@ -3,6 +3,14 @@ var jQuery = window.$; +$.urlParam = function(name){ + var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href); + if (results==null) { + return null; + } + return decodeURI(results[1]) || 0; +} + // using jQuery function getCookie(name) { var cookieValue = null; diff --git a/InvenTree/templates/js/nav.js b/InvenTree/templates/js/nav.js index e8207f9251..7dc562b8ef 100644 --- a/InvenTree/templates/js/nav.js +++ b/InvenTree/templates/js/nav.js @@ -23,8 +23,12 @@ function attachNavCallbacks(options={}) { var panelClass = options.name || 'unknown'; - // Look for a default panel to initialize - var defaultPanel = localStorage.getItem(`inventree-selected-panel-${panelClass}`) || options.default; + /* Look for a default panel to initialize + * First preference = URL parameter e.g. ?display=part-stock + * Second preference = localStorage + * Third preference = default + */ + var defaultPanel = $.urlParam('display') || localStorage.getItem(`inventree-selected-panel-${panelClass}`) || options.default; if (defaultPanel) { activatePanel(defaultPanel); @@ -63,6 +67,9 @@ function activatePanel(panelName, options={}) { console.log("found match -", panel_name); panelName = panel_name; } + + panel = `#panel-${panelName}`; + select = `#select-${panelName}`; }); } From 984e16d5aff6e575159311889bb50c292bffe00a Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:07:46 +1000 Subject: [PATCH 15/35] Return all part parameters to the main part edit form - refactor purchaseorder view - refactor salesorder view --- InvenTree/InvenTree/static/css/inventree.css | 2 +- InvenTree/part/api.py | 2 +- InvenTree/part/templates/part/detail.html | 65 ++++++++++++++ InvenTree/part/templates/part/orders.html | 51 ----------- InvenTree/part/templates/part/part_base.html | 75 +--------------- .../part/templates/part/sales_orders.html | 41 --------- InvenTree/part/test_views.py | 15 ---- InvenTree/part/urls.py | 3 - InvenTree/part/views.py | 34 ------- InvenTree/templates/js/nav.js | 5 -- InvenTree/templates/js/part.js | 88 +++++++++++++++++++ 11 files changed, 156 insertions(+), 225 deletions(-) delete mode 100644 InvenTree/part/templates/part/orders.html delete mode 100644 InvenTree/part/templates/part/sales_orders.html diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index b538aaad04..1c8d529a92 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -781,7 +781,7 @@ input[type="submit"] { } .sidenav .list-group-item.active { - background-color: #bbab8b; + background-color: #b3a997; border-color: #ccc; } diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 599c4bba5d..9abee816fa 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -1104,7 +1104,7 @@ part_api_urls = [ url(r'^(?P\d+)/?', PartThumbsUpdate.as_view(), name='api-part-thumbs-update'), ])), - url(r'^(?P\d+)/?', PartDetail.as_view(), name='api-part-detail'), + url(r'^(?P\d+)/', PartDetail.as_view(), name='api-part-detail'), url(r'^.*$', PartList.as_view(), name='api-part-list'), ] diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 1f217a872c..5b377708f6 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -44,6 +44,48 @@
    +
    +
    +

    {% trans "Purchase Orders" %}

    +
    +
    +
    +
    + +
    + +
    +
    +
    + + +
    +
    +
    + +
    +
    +

    {% trans "Sales Orders" %}

    +
    +
    +
    +
    + {% if 0 %} + + {% endif %} +
    + +
    +
    +
    + + +
    +
    +
    +
    @@ -101,6 +143,29 @@ {% block js_ready %} {{ block.super }} + loadPurchaseOrderTable($("#purchase-order-table"), { + url: "{% url 'api-po-list' %}", + params: { + part: {{ part.id }}, + }, + }); + + $("#part-order2").click(function() { + launchModalForm("{% url 'order-parts' %}", { + data: { + part: {{ part.id }}, + }, + reload: true, + }); + }); + + loadSalesOrderTable($("#sales-order-table"), { + url: "{% url 'api-so-list' %}", + params: { + part: {{ part.id }}, + }, + }); + loadPartTestTemplateTable( $("#test-template-table"), { diff --git a/InvenTree/part/templates/part/orders.html b/InvenTree/part/templates/part/orders.html deleted file mode 100644 index 24a1cdbf3c..0000000000 --- a/InvenTree/part/templates/part/orders.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='orders' %} -{% endblock %} - -{% block heading %} -{% trans "Purchase Orders" %} -{% endblock %} - -{% block details %} - -
    -
    - -
    - -
    -
    -
    - - -
    - - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadPurchaseOrderTable($("#purchase-order-table"), { - url: "{% url 'api-po-list' %}", - params: { - part: {{ part.id }}, - }, -}); - -$("#part-order2").click(function() { - launchModalForm("{% url 'order-parts' %}", { - data: { - part: {{ part.id }}, - }, - reload: true, - }); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index e7ec892628..efbd7d2b0b 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -421,80 +421,7 @@ $("#part-edit").click(function() { - constructForm('{% url "api-part-detail" part.id %}', { - focus: 'name', - fields: { - category: { - secondary: { - label: '{% trans "New Category" %}', - title: '{% trans "Create New Part Category" %}', - api_url: '{% url "api-part-category-list" %}', - method: 'POST', - fields: { - name: {}, - description: {}, - parent: { - secondary: { - title: '{% trans "New Parent" %}', - api_url: '{% url "api-part-category-list" %}', - method: 'POST', - fields: { - name: {}, - description: {}, - parent: {}, - } - } - }, - } - }, - }, - name: { - placeholder: 'part name', - }, - IPN: {}, - description: {}, - revision: {}, - keywords: { - icon: 'fa-key', - }, - variant_of: {}, - link: { - icon: 'fa-link', - }, - default_location: { - secondary: { - label: '{% trans "New Location" %}', - title: '{% trans "Create new stock location" %}', - - }, - }, - default_supplier: { - filters: { - part: {{ part.pk }}, - part_detail: true, - manufacturer_detail: true, - supplier_detail: true, - }, - secondary: { - label: '{% trans "New Supplier Part" %}', - title: '{% trans "Create new supplier part" %}', - } - }, - units: {}, - minimum_stock: {}, - }, - title: '{% trans "Edit Part" %}', - reload: true, - }); - - return; - - launchModalForm( - "{% url 'part-edit' part.id %}", - { - reload: true, - } - ); + editPart({{ part.pk }}); }); {% endif %} diff --git a/InvenTree/part/templates/part/sales_orders.html b/InvenTree/part/templates/part/sales_orders.html deleted file mode 100644 index fa8d5dfd8a..0000000000 --- a/InvenTree/part/templates/part/sales_orders.html +++ /dev/null @@ -1,41 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='sales-orders' %} -{% endblock %} - -{% block heading %} -{% trans "Sales Orders" %} -{% endblock %} - -{% block details %} - -
    -
    - {% if 0 %} - - {% endif %} -
    - -
    -
    -
    - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadSalesOrderTable($("#sales-order-table"), { - url: "{% url 'api-so-list' %}", - params: { - part: {{ part.id }}, - }, -}); - -{% endblock %} diff --git a/InvenTree/part/test_views.py b/InvenTree/part/test_views.py index 3b6b245231..9779aac544 100644 --- a/InvenTree/part/test_views.py +++ b/InvenTree/part/test_views.py @@ -158,21 +158,6 @@ class PartDetailTest(PartViewTestCase): class PartTests(PartViewTestCase): """ Tests for Part forms """ - def test_part_edit(self): - - response = self.client.get(reverse('part-edit', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest') - - keys = response.context.keys() - data = str(response.content) - - self.assertEqual(response.status_code, 200) - - self.assertIn('part', keys) - self.assertIn('csrf_token', keys) - - self.assertIn('html_form', data) - self.assertIn('"title":', data) - def test_part_create(self): """ Launch form to create a new part """ response = self.client.get(reverse('part-create'), {'category': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 8aa254e126..7ea4ca4eff 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -36,7 +36,6 @@ part_parameter_urls = [ ] part_detail_urls = [ - url(r'^edit/?', views.PartEdit.as_view(), name='part-edit'), url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'), url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'), url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'), @@ -55,8 +54,6 @@ part_detail_urls = [ url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'), url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'), - url(r'^orders/?', views.PartDetail.as_view(template_name='part/orders.html'), name='part-orders'), - url(r'^sales-orders/', views.PartDetail.as_view(template_name='part/sales_orders.html'), name='part-sales-orders'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'), diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 4acf5fcdb6..1ebd37a469 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -1084,40 +1084,6 @@ class PartImageSelect(AjaxUpdateView): return self.renderJsonResponse(request, form, data) -class PartEdit(AjaxUpdateView): - """ View for editing Part object """ - - model = Part - form_class = part_forms.EditPartForm - ajax_template_name = 'modal_form.html' - ajax_form_title = _('Edit Part Properties') - context_object_name = 'part' - - def get_form(self): - """ Create form for Part editing. - Overrides default get_form() method to limit the choices - for the 'default_supplier' field to SupplierParts that reference this part - """ - - form = super(AjaxUpdateView, self).get_form() - - # Hide the "default expiry" field if the feature is not enabled - if not inventree_settings.stock_expiry_enabled(): - form.fields['default_expiry'].widget = HiddenInput() - - part = self.get_object() - - form.fields['default_supplier'].queryset = SupplierPart.objects.filter(part=part) - - # Check if IPN can be edited - ipn_edit_enable = InvenTreeSetting.get_setting('PART_ALLOW_EDIT_IPN') - if not ipn_edit_enable and not self.request.user.is_superuser: - # Admin can still change IPN - form.fields['IPN'].disabled = True - - return form - - class BomDuplicate(AjaxUpdateView): """ View for duplicating BOM from a parent item. diff --git a/InvenTree/templates/js/nav.js b/InvenTree/templates/js/nav.js index 7dc562b8ef..f33571d584 100644 --- a/InvenTree/templates/js/nav.js +++ b/InvenTree/templates/js/nav.js @@ -56,15 +56,10 @@ function activatePanel(panelName, options={}) { // Iterate through the available 'select' elements until one matches panelName = null; - console.log("no match for panel:", panelName); - $('.nav-toggle').each(function(item) { var panel_name = $(this).attr('id').replace('select-', ''); - console.log("checking:", panel_name); - if ($(`#panel-${panel_name}`).length && (panelName == null)) { - console.log("found match -", panel_name); panelName = panel_name; } diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index e106098ad4..7f034682de 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -13,6 +13,94 @@ function yesNoLabel(value) { } } + +function editPart(pk, options={}) { + + var url = `/api/part/${pk}/`; + + var fields = { + category: { + /* + secondary: { + label: '{% trans "New Category" %}', + title: '{% trans "Create New Part Category" %}', + api_url: '{% url "api-part-category-list" %}', + method: 'POST', + fields: { + name: {}, + description: {}, + parent: { + secondary: { + title: '{% trans "New Parent" %}', + api_url: '{% url "api-part-category-list" %}', + method: 'POST', + fields: { + name: {}, + description: {}, + parent: {}, + } + } + }, + } + }, + */ + }, + name: { + placeholder: 'part name', + }, + IPN: {}, + description: {}, + revision: {}, + keywords: { + icon: 'fa-key', + }, + variant_of: {}, + link: { + icon: 'fa-link', + }, + default_location: { + /* + secondary: { + label: '{% trans "New Location" %}', + title: '{% trans "Create new stock location" %}', + }, + */ + }, + default_supplier: { + filters: { + part: pk, + part_detail: true, + manufacturer_detail: true, + supplier_detail: true, + }, + /* + secondary: { + label: '{% trans "New Supplier Part" %}', + title: '{% trans "Create new supplier part" %}', + } + */ + }, + units: {}, + minimum_stock: {}, + virtual: {}, + is_template: {}, + assembly: {}, + component: {}, + trackable: {}, + purchaseable: {}, + salable: {}, + active: {}, + }; + + constructForm(url, { + fields: fields, + title: '{% trans "Edit Part" %}', + reload: true, + }); + +} + + function toggleStar(options) { /* Toggle the 'starred' status of a part. * Performs AJAX queries and updates the display on the button. From 84149d34a691e483ac475c7593c9de7ce092c2ce Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:12:27 +1000 Subject: [PATCH 16/35] Refactor part-supplier view --- .../company/manufacturer_part_base.html | 2 +- .../templates/company/supplier_part_base.html | 2 +- .../company/supplier_part_detail.html | 2 +- InvenTree/part/templates/part/detail.html | 150 +++++++++++++++ InvenTree/part/templates/part/supplier.html | 171 ------------------ InvenTree/part/urls.py | 1 - 6 files changed, 153 insertions(+), 175 deletions(-) delete mode 100644 InvenTree/part/templates/part/supplier.html diff --git a/InvenTree/company/templates/company/manufacturer_part_base.html b/InvenTree/company/templates/company/manufacturer_part_base.html index ed1612ea76..f68bf99122 100644 --- a/InvenTree/company/templates/company/manufacturer_part_base.html +++ b/InvenTree/company/templates/company/manufacturer_part_base.html @@ -62,7 +62,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Internal Part" %} {% if part.part %} -
    {{ part.part.full_name }}{% include "clip.html"%} + {{ part.part.full_name }}{% include "clip.html"%} {% endif %} diff --git a/InvenTree/company/templates/company/supplier_part_base.html b/InvenTree/company/templates/company/supplier_part_base.html index bf6d914f19..8b6a5d94cd 100644 --- a/InvenTree/company/templates/company/supplier_part_base.html +++ b/InvenTree/company/templates/company/supplier_part_base.html @@ -61,7 +61,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Internal Part" %} {% if part.part %} - {{ part.part.full_name }}{% include "clip.html"%} + {{ part.part.full_name }}{% include "clip.html"%} {% endif %} diff --git a/InvenTree/company/templates/company/supplier_part_detail.html b/InvenTree/company/templates/company/supplier_part_detail.html index fb73ca06f4..6ccfc43e3f 100644 --- a/InvenTree/company/templates/company/supplier_part_detail.html +++ b/InvenTree/company/templates/company/supplier_part_detail.html @@ -18,7 +18,7 @@ {% trans "Internal Part" %} {% if part.part %} - {{ part.part.full_name }} + {{ part.part.full_name }} {% endif %} diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 5b377708f6..3eedc54798 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -134,6 +134,54 @@
    +
    +
    +

    {% trans "Part Suppliers" %}

    +
    +
    +
    +
    + +
    + + +
    +
    +
    + + +
    +
    +
    + +
    +
    +

    {% trans "Part Manufacturers" %}

    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    + {% endblock %} {% block js_load %} @@ -426,4 +474,106 @@ default: 'part-stock' }); + $('#supplier-create').click(function () { + launchModalForm( + "{% url 'supplier-part-create' %}", + { + reload: true, + data: { + part: {{ part.id }} + }, + secondary: [ + { + field: 'supplier', + label: '{% trans "New Supplier" %}', + title: '{% trans "Create new supplier" %}', + }, + { + field: 'manufacturer', + label: '{% trans "New Manufacturer" %}', + title: '{% trans "Create new manufacturer" %}', + } + ] + }); + }); + + $("#supplier-part-delete").click(function() { + + var selections = $("#supplier-table").bootstrapTable("getSelections"); + + var parts = []; + + selections.forEach(function(item) { + parts.push(item.pk); + }); + + launchModalForm("{% url 'supplier-part-delete' %}", { + data: { + parts: parts, + }, + reload: true, + }); + }); + + loadSupplierPartTable( + "#supplier-table", + "{% url 'api-supplier-part-list' %}", + { + params: { + part: {{ part.id }}, + part_detail: false, + supplier_detail: true, + manufacturer_detail: true, + }, + } + ); + + linkButtonsToSelection($("#supplier-table"), ['#supplier-part-options']); + + loadManufacturerPartTable( + '#manufacturer-table', + "{% url 'api-manufacturer-part-list' %}", + { + params: { + part: {{ part.id }}, + part_detail: true, + manufacturer_detail: true, + }, + } + ); + + linkButtonsToSelection($("#manufacturer-table"), ['#manufacturer-part-options']); + + $("#manufacturer-part-delete").click(function() { + + var selections = $("#manufacturer-table").bootstrapTable("getSelections"); + + deleteManufacturerParts(selections, { + onSuccess: function() { + $("#manufacturer-table").bootstrapTable("refresh"); + } + }); + }); + + $('#manufacturer-create').click(function () { + + constructForm('{% url "api-manufacturer-part-list" %}', { + fields: { + part: { + value: {{ part.pk }}, + hidden: true, + }, + manufacturer: {}, + MPN: {}, + description: {}, + link: {}, + }, + method: 'POST', + title: '{% trans "Add Manufacturer Part" %}', + onSuccess: function() { + $("#manufacturer-table").bootstrapTable("refresh"); + } + }); + }); + {% endblock %} diff --git a/InvenTree/part/templates/part/supplier.html b/InvenTree/part/templates/part/supplier.html deleted file mode 100644 index 8ae73cd07c..0000000000 --- a/InvenTree/part/templates/part/supplier.html +++ /dev/null @@ -1,171 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='suppliers' %} -{% endblock %} - - -{% block heading %} -{% trans "Part Suppliers" %} -{% endblock %} - -{% block details %} -
    -
    - -
    - - -
    -
    -
    - - -
    - -{% endblock %} - -{% block post_content_panel %} - -
    -
    -

    - {% trans "Part Manufacturers" %} -

    -
    - -
    -
    -
    - -
    - - -
    -
    -
    -
    -
    -
    - -{% endblock %} - -{% block js_load %} -{{ block.super }} -{% endblock %} -{% block js_ready %} - {{ block.super }} - - $('#supplier-create').click(function () { - launchModalForm( - "{% url 'supplier-part-create' %}", - { - reload: true, - data: { - part: {{ part.id }} - }, - secondary: [ - { - field: 'supplier', - label: '{% trans "New Supplier" %}', - title: '{% trans "Create new supplier" %}', - }, - { - field: 'manufacturer', - label: '{% trans "New Manufacturer" %}', - title: '{% trans "Create new manufacturer" %}', - } - ] - }); - }); - - $("#supplier-part-delete").click(function() { - - var selections = $("#supplier-table").bootstrapTable("getSelections"); - - var parts = []; - - selections.forEach(function(item) { - parts.push(item.pk); - }); - - launchModalForm("{% url 'supplier-part-delete' %}", { - data: { - parts: parts, - }, - reload: true, - }); - }); - - loadSupplierPartTable( - "#supplier-table", - "{% url 'api-supplier-part-list' %}", - { - params: { - part: {{ part.id }}, - part_detail: false, - supplier_detail: true, - manufacturer_detail: true, - }, - } - ); - - linkButtonsToSelection($("#supplier-table"), ['#supplier-part-options']); - - loadManufacturerPartTable( - '#manufacturer-table', - "{% url 'api-manufacturer-part-list' %}", - { - params: { - part: {{ part.id }}, - part_detail: true, - manufacturer_detail: true, - }, - } - ); - - linkButtonsToSelection($("#manufacturer-table"), ['#manufacturer-part-options']); - - $("#manufacturer-part-delete").click(function() { - - var selections = $("#manufacturer-table").bootstrapTable("getSelections"); - - deleteManufacturerParts(selections, { - onSuccess: function() { - $("#manufacturer-table").bootstrapTable("refresh"); - } - }); - }); - - $('#manufacturer-create').click(function () { - - constructForm('{% url "api-manufacturer-part-list" %}', { - fields: { - part: { - value: {{ part.pk }}, - hidden: true, - }, - manufacturer: {}, - MPN: {}, - description: {}, - link: {}, - }, - method: 'POST', - title: '{% trans "Add Manufacturer Part" %}', - onSuccess: function() { - $("#manufacturer-table").bootstrapTable("refresh"); - } - }); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 7ea4ca4eff..1ab9a44c4b 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -53,7 +53,6 @@ part_detail_urls = [ url(r'^build/?', views.PartDetail.as_view(template_name='part/build.html'), name='part-build'), url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'), url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), - url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'), From 985bd392341b7a481bce855fe512b166ec6ca2aa Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:14:48 +1000 Subject: [PATCH 17/35] Fix links --- .../company/templates/company/manufacturer_part_base.html | 4 ++-- .../company/templates/company/manufacturer_part_detail.html | 4 ++-- InvenTree/company/templates/company/supplier_part_base.html | 6 +++--- .../company/templates/company/supplier_part_detail.html | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/InvenTree/company/templates/company/manufacturer_part_base.html b/InvenTree/company/templates/company/manufacturer_part_base.html index f68bf99122..c54401b172 100644 --- a/InvenTree/company/templates/company/manufacturer_part_base.html +++ b/InvenTree/company/templates/company/manufacturer_part_base.html @@ -83,7 +83,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Manufacturer" %} - {{ part.manufacturer.name }}{% include "clip.html"%} + {{ part.manufacturer.name }}{% include "clip.html"%} {% trans "MPN" %} @@ -136,7 +136,7 @@ $('#delete-part').click(function() { constructForm('{% url "api-manufacturer-part-detail" part.pk %}', { method: 'DELETE', title: '{% trans "Delete Manufacturer Part" %}', - redirect: "{% url 'company-detail-manufacturer-parts' part.manufacturer.id %}", + redirect: "{% url 'company-detail' part.manufacturer.id %}", }); }); diff --git a/InvenTree/company/templates/company/manufacturer_part_detail.html b/InvenTree/company/templates/company/manufacturer_part_detail.html index 3bc789e6b9..e25fb9dca3 100644 --- a/InvenTree/company/templates/company/manufacturer_part_detail.html +++ b/InvenTree/company/templates/company/manufacturer_part_detail.html @@ -18,11 +18,11 @@ {% trans "Internal Part" %} {% if part.part %} - {{ part.part.full_name }} + {{ part.part.full_name }} {% endif %} - {% trans "Manufacturer" %}{{ part.manufacturer.name }} + {% trans "Manufacturer" %}{{ part.manufacturer.name }} {% trans "MPN" %}{{ part.MPN }} {% if part.link %} {% trans "External Link" %}{{ part.link }} diff --git a/InvenTree/company/templates/company/supplier_part_base.html b/InvenTree/company/templates/company/supplier_part_base.html index 8b6a5d94cd..900e0750cc 100644 --- a/InvenTree/company/templates/company/supplier_part_base.html +++ b/InvenTree/company/templates/company/supplier_part_base.html @@ -82,7 +82,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Supplier" %} - {{ part.supplier.name }}{% include "clip.html"%} + {{ part.supplier.name }}{% include "clip.html"%} {% trans "SKU" %} @@ -92,7 +92,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Manufacturer" %} - + {{ part.manufacturer_part.manufacturer.name }}{% include "clip.html"%} {% endif %} @@ -153,7 +153,7 @@ $('#delete-part').click(function() { launchModalForm( "{% url 'supplier-part-delete' %}?part={{ part.id }}", { - redirect: "{% url 'company-detail-supplier-parts' part.supplier.id %}" + redirect: "{% url 'company-detail' part.supplier.id %}" } ); }); diff --git a/InvenTree/company/templates/company/supplier_part_detail.html b/InvenTree/company/templates/company/supplier_part_detail.html index 6ccfc43e3f..708885043a 100644 --- a/InvenTree/company/templates/company/supplier_part_detail.html +++ b/InvenTree/company/templates/company/supplier_part_detail.html @@ -22,7 +22,7 @@ {% endif %} - {% trans "Supplier" %}{{ part.supplier.name }} + {% trans "Supplier" %}{{ part.supplier.name }} {% trans "SKU" %}{{ part.SKU }} {% if part.link %} {% trans "External Link" %}{{ part.link }} From 8607d702c4c7b439aae29fc9764200ea7ec13362 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:17:41 +1000 Subject: [PATCH 18/35] Refactor variants page --- InvenTree/part/templates/part/detail.html | 36 ++++++++++++++ InvenTree/part/templates/part/navbar.html | 2 +- InvenTree/part/templates/part/part_base.html | 2 +- InvenTree/part/templates/part/variants.html | 49 -------------------- InvenTree/part/urls.py | 1 - 5 files changed, 38 insertions(+), 52 deletions(-) delete mode 100644 InvenTree/part/templates/part/variants.html diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 3eedc54798..1c1dc4569f 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -107,6 +107,31 @@
    +
    +
    +

    {% trans "Part Variants" %}

    +
    +
    +
    +
    +
    + {% if part.is_template and part.active %} + + {% endif %} +
    +
    + +
    +
    +
    + + +
    +
    +
    +

    {% trans "Parameters" %}

    @@ -191,6 +216,17 @@ {% block js_ready %} {{ block.super }} + loadPartVariantTable($('#variants-table'), {{ part.pk }}); + + $('#new-variant').click(function() { + launchModalForm( + "{% url 'make-part-variant' part.id %}", + { + follow: true, + } + ); + }); + loadPurchaseOrderTable($("#purchase-order-table"), { url: "{% url 'api-po-list' %}", params: { diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index d634229500..dbd9423a02 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -19,7 +19,7 @@ {% if part.is_template %}
  • - + {% trans "Variants" %} diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index efbd7d2b0b..2437662cba 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -167,7 +167,7 @@ {% endif %} {% if part.variant_of %}
    - {% object_link 'part-variants' part.variant_of.id part.variant_of.full_name as link %} + {% object_link 'part-detail' part.variant_of.id part.variant_of.full_name as link %} {% blocktrans %}This part is a variant of {{link}}{% endblocktrans %}
    {% endif %} diff --git a/InvenTree/part/templates/part/variants.html b/InvenTree/part/templates/part/variants.html deleted file mode 100644 index 11a548ba49..0000000000 --- a/InvenTree/part/templates/part/variants.html +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} -{% load inventree_extras %} - -{% block menubar %} -{% include "part/navbar.html" with tab='variants' %} -{% endblock %} - -{% block heading %} -{% trans "Part Variants" %} -{% endblock %} - -{% block details %} -
    -
    -
    - {% if part.is_template and part.active %} - - {% endif %} -
    -
    - -
    -
    -
    - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - loadPartVariantTable($('#variants-table'), {{ part.pk }}); - - $('#new-variant').click(function() { - launchModalForm( - "{% url 'make-part-variant' part.id %}", - { - follow: true, - } - ); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 1ab9a44c4b..b483c1e7a3 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -47,7 +47,6 @@ part_detail_urls = [ url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'), url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'), - url(r'^variants/?', views.PartDetail.as_view(template_name='part/variants.html'), name='part-variants'), url(r'^allocation/?', views.PartDetail.as_view(template_name='part/allocation.html'), name='part-allocation'), url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'), url(r'^build/?', views.PartDetail.as_view(template_name='part/build.html'), name='part-build'), From c8c7f78ce903a5957ef3b6e6fdcb507a25cf3fb6 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:28:26 +1000 Subject: [PATCH 19/35] Refactor "related parts" view --- InvenTree/part/templates/part/detail.html | 66 ++++++++++++++++++ InvenTree/part/templates/part/related.html | 80 ---------------------- InvenTree/part/urls.py | 1 - 3 files changed, 66 insertions(+), 81 deletions(-) delete mode 100644 InvenTree/part/templates/part/related.html diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 1c1dc4569f..8910766972 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -159,6 +159,52 @@
  • + +

    {% trans "Part Suppliers" %}

    @@ -216,6 +262,26 @@ {% block js_ready %} {{ block.super }} + $('#table-related-part').inventreeTable({ + }); + + $("#add-related-part").click(function() { + launchModalForm("{% url 'part-related-create' %}", { + data: { + part: {{ part.id }}, + }, + reload: true, + }); + }); + + $('.delete-related-part').click(function() { + var button = $(this); + + launchModalForm(button.attr('url'), { + reload: true, + }); + }); + loadPartVariantTable($('#variants-table'), {{ part.pk }}); $('#new-variant').click(function() { diff --git a/InvenTree/part/templates/part/related.html b/InvenTree/part/templates/part/related.html deleted file mode 100644 index 77c2e1bc9f..0000000000 --- a/InvenTree/part/templates/part/related.html +++ /dev/null @@ -1,80 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='related' %} -{% endblock %} - -{% block heading %} -{% trans "Related Parts" %} -{% endblock %} - -{% block details %} - -
    -
    - {% if roles.part.change %} - - - {% endif %} -
    -
    - - - - - - - - - {% for item in part.get_related_parts %} - {% with part_related=item.0 part=item.1 %} - - - - {% endwith %} - {% endfor %} - - - - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - $('#table-related-part').inventreeTable({ - }); - - $("#add-related-part").click(function() { - launchModalForm("{% url 'part-related-create' %}", { - data: { - part: {{ part.id }}, - }, - reload: true, - }); - }); - - $('.delete-related-part').click(function() { - var button = $(this); - - launchModalForm(button.attr('url'), { - reload: true, - }); - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index b483c1e7a3..3d50e64261 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -53,7 +53,6 @@ part_detail_urls = [ url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'), url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), - url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'), url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'), From 57851b0eaf88029fc0eb044a43fdf4e1d11bf10f Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:36:20 +1000 Subject: [PATCH 20/35] Refactor build orders display --- .../build/templates/build/build_base.html | 2 +- InvenTree/build/templates/build/detail.html | 2 +- InvenTree/part/templates/part/build.html | 48 ------------------- InvenTree/part/templates/part/detail.html | 36 ++++++++++++++ InvenTree/part/urls.py | 1 - 5 files changed, 38 insertions(+), 51 deletions(-) delete mode 100644 InvenTree/part/templates/part/build.html diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html index ece6de36bb..7100e82838 100644 --- a/InvenTree/build/templates/build/build_base.html +++ b/InvenTree/build/templates/build/build_base.html @@ -126,7 +126,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Part" %} - {{ build.part.full_name }} + {{ build.part.full_name }} diff --git a/InvenTree/build/templates/build/detail.html b/InvenTree/build/templates/build/detail.html index 1b4c577b07..63c04f7590 100644 --- a/InvenTree/build/templates/build/detail.html +++ b/InvenTree/build/templates/build/detail.html @@ -24,7 +24,7 @@ {% trans "Part" %} - {{ build.part.full_name }}{% include "clip.html"%} + {{ build.part.full_name }}{% include "clip.html"%} diff --git a/InvenTree/part/templates/part/build.html b/InvenTree/part/templates/part/build.html deleted file mode 100644 index 29f32c770a..0000000000 --- a/InvenTree/part/templates/part/build.html +++ /dev/null @@ -1,48 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='build' %} -{% endblock %} - -{% block heading %} -{% trans "Part Builds" %} -{% endblock %} - -{% block details %} -
    -
    - {% if part.active %} - {% if roles.build.add %} - - {% endif %} - {% endif %} -
    - -
    -
    -
    - - -
    - - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - $("#start-build").click(function() { - newBuildOrder({ - part: {{ part.pk }}, - }); - }); - - loadBuildTable($("#build-table"), { - url: "{% url 'api-build-list' %}", - params: { - part: {{ part.id }}, - } - }); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 8910766972..afef20d714 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -229,6 +229,29 @@
    +
    +
    +

    {% trans "Part Builds" %}

    +
    +
    +
    +
    + {% if part.active %} + {% if roles.build.add %} + + {% endif %} + {% endif %} +
    + +
    +
    +
    + + +
    +
    +
    +

    {% trans "Part Manufacturers" %}

    @@ -262,6 +285,19 @@ {% block js_ready %} {{ block.super }} + $("#start-build").click(function() { + newBuildOrder({ + part: {{ part.pk }}, + }); + }); + + loadBuildTable($("#build-table"), { + url: "{% url 'api-build-list' %}", + params: { + part: {{ part.id }}, + } + }); + $('#table-related-part').inventreeTable({ }); diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 3d50e64261..3cf96604e4 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -49,7 +49,6 @@ part_detail_urls = [ url(r'^allocation/?', views.PartDetail.as_view(template_name='part/allocation.html'), name='part-allocation'), url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'), - url(r'^build/?', views.PartDetail.as_view(template_name='part/build.html'), name='part-build'), url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'), url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), From e7c7bdcd00fcc3f73b28a20ca1b008c296d3a2a3 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:42:28 +1000 Subject: [PATCH 21/35] Refactor BOM page --- InvenTree/part/templates/part/bom.html | 144 +--------------------- InvenTree/part/templates/part/detail.html | 127 +++++++++++++++++++ InvenTree/part/templates/part/navbar.html | 2 +- InvenTree/part/views.py | 2 +- 4 files changed, 133 insertions(+), 142 deletions(-) diff --git a/InvenTree/part/templates/part/bom.html b/InvenTree/part/templates/part/bom.html index 048b98fc01..4376c23ab9 100644 --- a/InvenTree/part/templates/part/bom.html +++ b/InvenTree/part/templates/part/bom.html @@ -1,16 +1,5 @@ -{% extends "part/part_base.html" %} -{% load static %} {% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='bom' %} -{% endblock %} - -{% block heading %} -{% trans "Bill of Materials" %} -{% endblock %} - -{% block details %} +{% load inventree_extras %} {% if roles.part.change != True and editing_enabled %}
    @@ -32,7 +21,7 @@
    {% endif %} -
    +
    {% if editing_enabled %}
    - +
    -{% endif %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - // Load the BOM table data - loadBomTable($("#bom-table"), { - editable: {{ editing_enabled }}, - bom_url: "{% url 'api-bom-list' %}", - part_url: "{% url 'api-part-list' %}", - parent_id: {{ part.id }} , - sub_part_detail: true, - }); - - linkButtonsToSelection($("#bom-table"), - [ - "#bom-item-delete", - ] - ); - - {% if editing_enabled %} - $("#editing-finished").click(function() { - location.href = "{% url 'part-bom' part.id %}"; - }); - - $('#bom-item-delete').click(function() { - - // Get a list of the selected BOM items - var rows = $("#bom-table").bootstrapTable('getSelections'); - - // TODO - In the future, display (in the dialog) which items are going to be deleted - - showQuestionDialog( - '{% trans "Delete selected BOM items?" %}', - '{% trans "All selected BOM items will be deleted" %}', - { - accept: function() { - - // Keep track of each DELETE request - var requests = []; - - rows.forEach(function(row) { - requests.push( - inventreeDelete( - `/api/bom/${row.pk}/`, - ) - ); - }); - - // Wait for *all* the requests to complete - $.when.apply($, requests).then(function() { - location.reload(); - }); - } - } - ); - }); - - $('#bom-upload').click(function() { - location.href = "{% url 'upload-bom' part.id %}"; - }); - - $('#bom-duplicate').click(function() { - launchModalForm( - "{% url 'duplicate-bom' part.id %}", - { - success: function() { - $('#bom-table').bootstrapTable('refresh'); - } - } - ); - }); - - $("#bom-item-new").click(function () { - launchModalForm( - "{% url 'bom-item-create' %}?parent={{ part.id }}", - { - success: function() { - $("#bom-table").bootstrapTable('refresh'); - }, - secondary: [ - { - field: 'sub_part', - label: '{% trans "New Part" %}', - title: '{% trans "Create New Part" %}', - url: "{% url 'part-create' %}", - }, - ] - } - ); - }); - - {% else %} - - $("#validate-bom").click(function() { - launchModalForm( - "{% url 'bom-validate' part.id %}", - { - reload: true, - } - ); - }); - - $("#edit-bom").click(function () { - location.href = "{% url 'part-bom' part.id %}?edit=1"; - }); - - $("#download-bom").click(function () { - launchModalForm("{% url 'bom-export' part.id %}", - { - success: function(response) { - location.href = response.url; - }, - } - ); - }); - - {% endif %} - - $("#print-bom-report").click(function() { - printBomReports([{{ part.pk }}]); - }); - -{% endblock %} +{% endif %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index afef20d714..3def22cf03 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -229,6 +229,15 @@
    +
    +
    +

    {% trans "Bill of Materials" %}

    +
    +
    + {% include "part/bom.html" with part=part %} +
    +
    +

    {% trans "Part Builds" %}

    @@ -285,6 +294,124 @@ {% block js_ready %} {{ block.super }} + // Load the BOM table data + loadBomTable($("#bom-table"), { + editable: {{ editing_enabled }}, + bom_url: "{% url 'api-bom-list' %}", + part_url: "{% url 'api-part-list' %}", + parent_id: {{ part.id }} , + sub_part_detail: true, + }); + + linkButtonsToSelection($("#bom-table"), + [ + "#bom-item-delete", + ] + ); + + {% if editing_enabled %} + $("#editing-finished").click(function() { + location.href = "{% url 'part-detail' part.id %}?display=bom"; + }); + + $('#bom-item-delete').click(function() { + + // Get a list of the selected BOM items + var rows = $("#bom-table").bootstrapTable('getSelections'); + + // TODO - In the future, display (in the dialog) which items are going to be deleted + + showQuestionDialog( + '{% trans "Delete selected BOM items?" %}', + '{% trans "All selected BOM items will be deleted" %}', + { + accept: function() { + + // Keep track of each DELETE request + var requests = []; + + rows.forEach(function(row) { + requests.push( + inventreeDelete( + `/api/bom/${row.pk}/`, + ) + ); + }); + + // Wait for *all* the requests to complete + $.when.apply($, requests).then(function() { + location.reload(); + }); + } + } + ); + }); + + $('#bom-upload').click(function() { + location.href = "{% url 'upload-bom' part.id %}"; + }); + + $('#bom-duplicate').click(function() { + launchModalForm( + "{% url 'duplicate-bom' part.id %}", + { + success: function() { + $('#bom-table').bootstrapTable('refresh'); + } + } + ); + }); + + $("#bom-item-new").click(function () { + launchModalForm( + "{% url 'bom-item-create' %}?parent={{ part.id }}", + { + success: function() { + $("#bom-table").bootstrapTable('refresh'); + }, + secondary: [ + { + field: 'sub_part', + label: '{% trans "New Part" %}', + title: '{% trans "Create New Part" %}', + url: "{% url 'part-create' %}", + }, + ] + } + ); + }); + + {% else %} + + $("#validate-bom").click(function() { + launchModalForm( + "{% url 'bom-validate' part.id %}", + { + reload: true, + } + ); + }); + + $("#edit-bom").click(function () { + location.href = "{% url 'part-detail' part.id %}?display=bom&edit=1"; + }); + + $("#download-bom").click(function () { + launchModalForm("{% url 'bom-export' part.id %}", + { + success: function(response) { + location.href = response.url; + }, + } + ); + }); + + {% endif %} + + $("#print-bom-report").click(function() { + printBomReports([{{ part.pk }}]); + }); + $("#start-build").click(function() { newBuildOrder({ part: {{ part.pk }}, diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index dbd9423a02..e9d11207ed 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -41,7 +41,7 @@ {% endif %} {% if part.assembly %}
  • - + {% trans "Bill of Materials" %} diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 1ebd37a469..bf8c32ba78 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -1441,7 +1441,7 @@ class BomUpload(InvenTreeRoleMixin, FileManagementFormView): # BomItem already exists pass - return HttpResponseRedirect(reverse('part-bom', kwargs={'pk': self.kwargs['pk']})) + return HttpResponseRedirect(reverse('part-detail', kwargs={'pk': self.kwargs['pk']})) class PartExport(AjaxView): From e38d740bbc4ab59e4e5be1cd34affdbce378c932 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:44:46 +1000 Subject: [PATCH 22/35] Refactor "used in" page --- InvenTree/part/templates/part/detail.html | 26 +++++++++++++++ InvenTree/part/templates/part/used_in.html | 39 ---------------------- InvenTree/part/urls.py | 2 -- 3 files changed, 26 insertions(+), 41 deletions(-) delete mode 100644 InvenTree/part/templates/part/used_in.html diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 3def22cf03..6949879aa4 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -238,6 +238,22 @@
  • +
    +
    +

    {% trans "Assemblies" %}

    +
    +
    +
    +
    + +
    +
    + + +
    +
    +
    +

    {% trans "Part Builds" %}

    @@ -294,6 +310,16 @@ {% block js_ready %} {{ block.super }} + loadPartTable('#used-table', + '{% url "api-part-list" %}', + { + params: { + uses: {{ part.pk }}, + }, + filterTarget: '#filter-list-usedin', + } + ); + // Load the BOM table data loadBomTable($("#bom-table"), { editable: {{ editing_enabled }}, diff --git a/InvenTree/part/templates/part/used_in.html b/InvenTree/part/templates/part/used_in.html deleted file mode 100644 index e7d8863d42..0000000000 --- a/InvenTree/part/templates/part/used_in.html +++ /dev/null @@ -1,39 +0,0 @@ -{% extends "part/part_base.html" %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='used' %} -{% endblock %} - -{% block heading %} -{% trans "Assemblies" %} -{% endblock %} - -{% block details %} - -
    -
    - -
    -
    - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - loadPartTable('#used-table', - '{% url "api-part-list" %}', - { - params: { - uses: {{ part.pk }}, - }, - filterTarget: '#filter-list-usedin', - } - ); - - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 3cf96604e4..ded9e0b3c4 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -48,8 +48,6 @@ part_detail_urls = [ url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'), url(r'^allocation/?', views.PartDetail.as_view(template_name='part/allocation.html'), name='part-allocation'), - url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'), - url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'), url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), From df8900811650d9ec38ce4f271e7a75273d20862a Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:53:14 +1000 Subject: [PATCH 23/35] Refactor allocation page(s) - Also perform null check on notes before displaying --- InvenTree/build/templates/build/notes.html | 2 + .../company/templates/company/detail.html | 2 + .../order/purchase_order_detail.html | 2 + .../templates/order/sales_order_detail.html | 2 + InvenTree/part/templates/part/allocation.html | 50 ------------------- InvenTree/part/templates/part/detail.html | 28 +++++++++++ InvenTree/part/templates/part/navbar.html | 8 --- InvenTree/part/urls.py | 1 - 8 files changed, 36 insertions(+), 59 deletions(-) delete mode 100644 InvenTree/part/templates/part/allocation.html diff --git a/InvenTree/build/templates/build/notes.html b/InvenTree/build/templates/build/notes.html index 8eff2eff10..2bdbf07970 100644 --- a/InvenTree/build/templates/build/notes.html +++ b/InvenTree/build/templates/build/notes.html @@ -31,8 +31,10 @@ {% else %} +{% if build.notes %} {{ build.notes | markdownify }} {% endif %} +{% endif %} {% endblock %} diff --git a/InvenTree/company/templates/company/detail.html b/InvenTree/company/templates/company/detail.html index 1f2bcf3784..105e0f82ae 100644 --- a/InvenTree/company/templates/company/detail.html +++ b/InvenTree/company/templates/company/detail.html @@ -179,7 +179,9 @@
    + {% if company.notes %} {{ company.notes | markdownify }} + {% endif %}
    diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index 8c9feab452..cbff1b2d1c 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -65,7 +65,9 @@
    + {% if order.notes %} {{ order.notes | markdownify }} + {% endif %}
    diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 8ada362092..277c1f4278 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -64,7 +64,9 @@
    + {% if order.notes %} {{ order.notes | markdownify }} + {% endif %}
    diff --git a/InvenTree/part/templates/part/allocation.html b/InvenTree/part/templates/part/allocation.html deleted file mode 100644 index e78456ea3a..0000000000 --- a/InvenTree/part/templates/part/allocation.html +++ /dev/null @@ -1,50 +0,0 @@ -{% extends "part/part_base.html" %} -{% load status_codes %} -{% load i18n %} -{% load inventree_extras %} - -{% block menubar %} -{% include "part/navbar.html" with tab="allocation" %} -{% endblock %} - -{% block heading %} -{% trans "Build Order Allocations" %} -{% endblock %} - -{% block details %} - -
    - -{% endblock %} - -{% block pre_content_panel %} - -
    -
    -

    {% trans "Sales Order Allocations" %}

    -
    - -
    -
    -
    -
    - -{% endblock %} - - -{% block js_ready %} -{{ block.super }} - - loadSalesOrderAllocationTable("#sales-order-table", { - params: { - part: {{ part.id }}, - } - }); - - loadBuildOrderAllocationTable("#build-order-table", { - params: { - part: {{ part.id }}, - } - }); - -{% endblock %} diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 6949879aa4..b44bd25acc 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -84,6 +84,13 @@
    + +
    +

    {% trans "Sales Order Allocations" %}

    +
    +
    +
    +
    @@ -103,7 +110,9 @@
    + {% if part.notes %} {{ part.notes | markdownify }} + {% endif %}
    @@ -275,6 +284,13 @@
    + +
    +

    {% trans "Build Order Allocations" %}

    +
    +
    +
    +
    @@ -310,6 +326,18 @@ {% block js_ready %} {{ block.super }} + loadBuildOrderAllocationTable("#build-order-allocation-table", { + params: { + part: {{ part.id }}, + } + }); + + loadSalesOrderAllocationTable("#sales-order-allocation-table", { + params: { + part: {{ part.id }}, + } + }); + loadPartTable('#used-table', '{% url "api-part-list" %}', { diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index e9d11207ed..4f0e92a80d 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -31,14 +31,6 @@ {% trans "Stock" %} - {% if part.component or part.salable %} -
  • - - - {% trans "Allocations" %} - -
  • - {% endif %} {% if part.assembly %}
  • diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index ded9e0b3c4..a2489de058 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -47,7 +47,6 @@ part_detail_urls = [ url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'), url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'), - url(r'^allocation/?', views.PartDetail.as_view(template_name='part/allocation.html'), name='part-allocation'), url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), From d5bf108fef39b9e49e88e6496a09e644216710e2 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 16:54:49 +1000 Subject: [PATCH 24/35] Remove unused template file --- InvenTree/part/templates/part/track.html | 14 -------------- InvenTree/part/urls.py | 1 - 2 files changed, 15 deletions(-) delete mode 100644 InvenTree/part/templates/part/track.html diff --git a/InvenTree/part/templates/part/track.html b/InvenTree/part/templates/part/track.html deleted file mode 100644 index 8e89419a11..0000000000 --- a/InvenTree/part/templates/part/track.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "part/part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/navbar.html' with tab='track' %} -{% endblock %} - -{% block heading %} -{% trans "Part Tracking" %} -{% endblock %} - -{% block details %} -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index a2489de058..0640807e51 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -48,7 +48,6 @@ part_detail_urls = [ url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'), url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), - url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'), From 72337dab49e12e7be1c246a2854c991046760e87 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 17:26:06 +1000 Subject: [PATCH 25/35] Refactor PartCategory views --- InvenTree/part/templates/part/category.html | 133 ++++++++++++------ .../part/templates/part/category_navbar.html | 24 ++-- .../templates/part/category_parametric.html | 37 ----- .../templates/part/category_partlist.html | 16 --- InvenTree/part/templates/part/detail.html | 15 +- .../part/templates/part/subcategory.html | 51 ------- InvenTree/part/urls.py | 3 - InvenTree/part/views.py | 14 +- 8 files changed, 106 insertions(+), 187 deletions(-) delete mode 100644 InvenTree/part/templates/part/category_parametric.html delete mode 100644 InvenTree/part/templates/part/category_partlist.html delete mode 100644 InvenTree/part/templates/part/subcategory.html diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index cf7348be76..224d855aa3 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -3,7 +3,7 @@ {% load i18n %} {% block menubar %} -{% include 'part/category_navbar.html' with tab='parts' %} +{% include 'part/category_navbar.html' %} {% endblock %} {% block content %} @@ -115,63 +115,81 @@
  • -{% block category_content %} +{% block page_content %} -
    -
    - - {% if roles.part.add %} - - {% endif %} +
    +
    +

    {% trans "Parts" %}

    +
    +
    - - - -
    - + + {% if roles.part.add %} + + {% endif %} +
    + + +
    + + + +
    + +
    +
    + +
    +
    -
    +
    -

    - {% block heading %} - {% trans "Parts" %} - {% endblock %} -

    +

    {% trans "Part Parameters" %}

    -
    - {% block details %} - -
    - {% endblock %} +
    + +
    +
    +
    + +
    +
    +

    {% trans "Subcategories" %}

    +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    {% endblock %} - -{% block category_tables %} -{% endblock category_tables %} - {% endblock %} {% block js_load %} {{ block.super }} @@ -180,6 +198,26 @@ {% block js_ready %} {{ block.super }} + loadPartCategoryTable($('#subcategory-table'), { + params: { + {% if category %} + parent: {{ category.pk }} + {% else %} + parent: 'null' + {% endif %} + } + }); + + {% if category %} + loadParametricPartTable( + "#parametric-part-table", + { + headers: {{ headers|safe }}, + data: {{ parameters|safe }}, + } + ); + {% endif %} + enableNavbar({ label: 'category', toggleId: '#category-menu-toggle', @@ -328,4 +366,9 @@ $('#view-list').hide(); } + attachNavCallbacks({ + name: 'partcategory', + default: 'part-stock' + }); + {% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/category_navbar.html b/InvenTree/part/templates/part/category_navbar.html index bd61300531..8e5e085f93 100644 --- a/InvenTree/part/templates/part/category_navbar.html +++ b/InvenTree/part/templates/part/category_navbar.html @@ -11,31 +11,23 @@ -
  • - {% if category %} - - {% else %} - - {% endif %} +
  • + {% trans "Subcategories" %}
  • -
  • - {% if category %} - - {% else %} - - {% endif %} +
  • + {% trans "Parts" %}
  • {% if show_import and user.is_staff and roles.part.add %} -
  • - +
  • + {% trans "Import Parts" %} @@ -43,8 +35,8 @@ {% endif %} {% if category %} -
  • - +
  • + {% trans "Parameters" %} diff --git a/InvenTree/part/templates/part/category_parametric.html b/InvenTree/part/templates/part/category_parametric.html deleted file mode 100644 index 881a292986..0000000000 --- a/InvenTree/part/templates/part/category_parametric.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "part/category.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/category_navbar.html' with tab='parameters' %} -{% endblock %} - -{% block heading %} -{% trans "Part Parameters" %} -{% endblock %} - -{% block details %} - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - /* Hide Button Toolbar */ - window.onload = function hideButtonToolbar() { - var toolbar = document.getElementById("button-toolbar"); - toolbar.style.display = "none"; - }; - - loadParametricPartTable( - "#parametric-part-table", - { - headers: {{ headers|safe }}, - data: {{ parameters|safe }}, - } - ); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/category_partlist.html b/InvenTree/part/templates/part/category_partlist.html deleted file mode 100644 index e78254c541..0000000000 --- a/InvenTree/part/templates/part/category_partlist.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends "part/category.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include 'part/category_navbar.html' with tab='parts' %} -{% endblock %} - -{% block heading %} -{% trans "Parts" %} -{% endblock %} - -{% block details %} - -
    -{% endblock %} diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index b44bd25acc..2cb430ccf8 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -3,7 +3,6 @@ {% load i18n %} {% load markdownify %} - {% block menubar %} {% include 'part/navbar.html' %} {% endblock %} @@ -116,6 +115,10 @@
  • +
    + +
    +

    {% trans "Part Variants" %}

    @@ -788,11 +791,6 @@ ) }); - attachNavCallbacks({ - name: 'part', - default: 'part-stock' - }); - $('#supplier-create').click(function () { launchModalForm( "{% url 'supplier-part-create' %}", @@ -895,4 +893,9 @@ }); }); + attachNavCallbacks({ + name: 'part', + default: 'part-stock' + }); + {% endblock %} diff --git a/InvenTree/part/templates/part/subcategory.html b/InvenTree/part/templates/part/subcategory.html deleted file mode 100644 index e9e0d27468..0000000000 --- a/InvenTree/part/templates/part/subcategory.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends "part/category.html" %} - -{% load i18n %} -{% load inventree_extras %} -{% load static %} - -{% block menubar %} -{% include 'part/category_navbar.html' with tab='subcategories' %} -{% endblock %} - -{% block category_content %} - -
    - -
    -

    {% trans "Subcategories" %}

    -
    - -
    -
    - -
    - -
    -
    -
    - -
    - -
    -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - enableNavbar({ - label: 'category', - toggleId: '#category-menu-toggle', - }); - - loadPartCategoryTable($('#subcategory-table'), { - params: { - {% if category %} - parent: {{ category.pk }} - {% else %} - parent: 'null' - {% endif %} - } - }); - -{% endblock %} diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 0640807e51..e59ea88a05 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -78,9 +78,6 @@ category_urls = [ url(r'^delete/', views.CategoryDelete.as_view(), name='category-delete'), url(r'^parameters/', include(category_parameter_urls)), - url(r'^subcategory/', views.CategoryDetail.as_view(template_name='part/subcategory.html'), name='category-subcategory'), - url(r'^parametric/', views.CategoryParametric.as_view(), name='category-parametric'), - # Anything else url(r'^.*$', views.CategoryDetail.as_view(), name='category-detail'), ])) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index bf8c32ba78..cbaa7f3d72 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -1818,7 +1818,7 @@ class CategoryDetail(InvenTreeRoleMixin, DetailView): model = PartCategory context_object_name = 'category' queryset = PartCategory.objects.all().prefetch_related('children') - template_name = 'part/category_partlist.html' + template_name = 'part/category.html' def get_context_data(self, **kwargs): @@ -1829,18 +1829,6 @@ class CategoryDetail(InvenTreeRoleMixin, DetailView): except KeyError: context['part_count'] = 0 - return context - - -class CategoryParametric(CategoryDetail): - """ Parametric view for PartCategory """ - - template_name = 'part/category_parametric.html' - - def get_context_data(self, **kwargs): - - context = super(CategoryParametric, self).get_context_data(**kwargs).copy() - # Get current category category = kwargs.get('object', None) From 52da678636257cbdaf5ee0f9c2e5af7318f9e4a3 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 21:24:33 +1000 Subject: [PATCH 26/35] Refactor SupplierPart page --- .../company/manufacturer_part_create.html | 17 - .../templates/company/supplier_part.html | 352 ++++++++++++++++++ .../templates/company/supplier_part_base.html | 161 -------- .../company/supplier_part_detail.html | 48 --- .../company/supplier_part_navbar.html | 12 +- .../company/supplier_part_orders.html | 35 -- .../company/supplier_part_pricing.html | 124 ------ .../company/supplier_part_stock.html | 58 --- InvenTree/company/urls.py | 7 +- InvenTree/part/templates/part/category.html | 4 +- 10 files changed, 361 insertions(+), 457 deletions(-) delete mode 100644 InvenTree/company/templates/company/manufacturer_part_create.html create mode 100644 InvenTree/company/templates/company/supplier_part.html delete mode 100644 InvenTree/company/templates/company/supplier_part_base.html delete mode 100644 InvenTree/company/templates/company/supplier_part_detail.html delete mode 100644 InvenTree/company/templates/company/supplier_part_orders.html delete mode 100644 InvenTree/company/templates/company/supplier_part_pricing.html delete mode 100644 InvenTree/company/templates/company/supplier_part_stock.html diff --git a/InvenTree/company/templates/company/manufacturer_part_create.html b/InvenTree/company/templates/company/manufacturer_part_create.html deleted file mode 100644 index 21c23f9075..0000000000 --- a/InvenTree/company/templates/company/manufacturer_part_create.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "modal_form.html" %} - -{% load i18n %} - -{% block pre_form_content %} -{{ block.super }} - -{% if part %} -
    - {% include "hover_image.html" with image=part.image %} - {{ part.full_name}} -
    - {{ part.description }} -
    -{% endif %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/supplier_part.html b/InvenTree/company/templates/company/supplier_part.html new file mode 100644 index 0000000000..c3c2f89aa7 --- /dev/null +++ b/InvenTree/company/templates/company/supplier_part.html @@ -0,0 +1,352 @@ +{% extends "two_column.html" %} +{% load static %} +{% load i18n %} +{% load inventree_extras %} + +{% block page_title %} +{% inventree_title %} | {% trans "Supplier Part" %} +{% endblock %} + +{% block menubar %} +{% include "company/supplier_part_navbar.html" %} +{% endblock %} + +{% block thumbnail %} + +{% endblock %} + +{% block page_data %} +

    {% trans "Supplier Part" %}

    +
    +

    + {{ part.part.full_name }} + {% if user.is_staff and perms.company.change_company %} + + + + {% endif %} +

    +

    {{ part.supplier.name }} - {{ part.SKU }}

    + +{% if roles.purchase_order.change %} +
    +
    + {% if roles.purchase_order.add %} + + {% endif %} + + {% if roles.purchase_order.delete %} + + {% endif %} +
    +
    +{% endif %} + +{% endblock %} + +{% block page_details %} + +

    {% trans "Supplier Part Details" %}

    + + + + + + + + {% if part.description %} + + + + + + {% endif %} + {% if part.link %} + + + + + + {% endif %} + + + + + + + + + + {% if part.manufacturer_part.manufacturer %} + + + + + + {% endif %} + {% if part.manufacturer_part.MPN %} + + + + + + {% endif %} + {% if part.packaging %} + + + + + + {% endif %} + {% if part.note %} + + + + + + {% endif %} +
    {% trans "Internal Part" %} + {% if part.part %} + {{ part.part.full_name }}{% include "clip.html"%} + {% endif %} +
    {% trans "Description" %}{{ part.description }}{% include "clip.html"%}
    {% trans "External Link" %}{{ part.link }}{% include "clip.html"%}
    {% trans "Supplier" %}{{ part.supplier.name }}{% include "clip.html"%}
    {% trans "SKU" %}{{ part.SKU }}{% include "clip.html"%}
    {% trans "Manufacturer" %} + {{ part.manufacturer_part.manufacturer.name }}{% include "clip.html"%}
    {% trans "MPN" %}{{ part.manufacturer_part.MPN }}{% include "clip.html"%}
    {% trans "Packaging" %}{{ part.packaging }}{% include "clip.html"%}
    {% trans "Note" %}{{ part.note }}{% include "clip.html"%}
    +{% endblock %} + +{% block page_content %} + +
    +
    +

    {% trans "Supplier Part Stock" %}

    +
    +
    + {% include "stock_table.html" %} +
    +
    + +
    +
    +

    {% trans "Supplier Part Orders" %}

    +
    +
    + {% if roles.purchase_order.add %} +
    +
    + +
    +
    + {% endif %} + +
    +
    +
    + +
    +
    +

    {% trans "Pricing Information" %}

    +
    +
    + {% if roles.purchase_order.add %} +
    + +
    + {% endif %} + + +
    +
    +
    + +{% endblock %} + +{% block js_ready %} +{{ block.super }} + +function reloadPriceBreaks() { + $("#price-break-table").bootstrapTable("refresh"); +} + +$('#price-break-table').inventreeTable({ + name: 'buypricebreaks', + formatNoMatches: function() { return "{% trans "No price break information found" %}"; }, + queryParams: { + part: {{ part.id }}, + }, + url: "{% url 'api-part-supplier-price-list' %}", + onPostBody: function() { + var table = $('#price-break-table'); + + table.find('.button-price-break-delete').click(function() { + var pk = $(this).attr('pk'); + + constructForm(`/api/company/price-break/${pk}/`, { + method: 'DELETE', + onSuccess: reloadPriceBreaks, + title: '{% trans "Delete Price Break" %}', + }); + }); + + table.find('.button-price-break-edit').click(function() { + var pk = $(this).attr('pk'); + + constructForm(`/api/company/price-break/${pk}/`, { + fields: { + quantity: {}, + price: {}, + price_currency: {}, + }, + onSuccess: reloadPriceBreaks, + title: '{% trans "Edit Price Break" %}', + }); + }); + }, + columns: [ + { + field: 'pk', + title: 'ID', + visible: false, + switchable: false, + }, + { + field: 'quantity', + title: '{% trans "Quantity" %}', + sortable: true, + }, + { + field: 'price', + title: '{% trans "Price" %}', + sortable: true, + formatter: function(value, row, index) { + var html = value; + + html += `
    ` + + html += makeIconButton('fa-edit icon-blue', 'button-price-break-edit', row.pk, '{% trans "Edit price break" %}'); + html += makeIconButton('fa-trash-alt icon-red', 'button-price-break-delete', row.pk, '{% trans "Delete price break" %}'); + + html += `
    `; + + return html; + } + }, + ] +}); + +$('#new-price-break').click(function() { + + constructForm( + '{% url "api-part-supplier-price-list" %}', + { + method: 'POST', + fields: { + quantity: {}, + part: { + value: {{ part.pk }}, + hidden: true, + }, + price: {}, + price_currency: { + }, + }, + title: '{% trans "Add Price Break" %}', + onSuccess: reloadPriceBreaks, + } + ); +}); + +loadPurchaseOrderTable($("#purchase-order-table"), { + url: "{% url 'api-po-list' %}?supplier_part={{ part.id }}", +}); + +loadStockTable($("#stock-table"), { + params: { + supplier_part: {{ part.id }}, + location_detail: true, + part_detail: false, + }, + groupByField: 'location', + buttons: ['#stock-options'], + url: "{% url 'api-stock-list' %}", +}); + +$("#stock-export").click(function() { + launchModalForm("{% url 'stock-export-options' %}", { + submit_text: '{% trans "Export" %}', + success: function(response) { + var url = "{% url 'stock-export' %}"; + + url += "?format=" + response.format; + url += "&cascade=" + response.cascade; + url += "&supplier_part={{ part.id }}"; + + location.href = url; + }, + }); +}); + +$("#item-create").click(function() { + createNewStockItem({ + data: { + part: {{ part.part.id }}, + supplier_part: {{ part.id }}, + }, + reload: true, + }); +}); + + +enableNavbar({ + label: 'supplier-part', + toggleId: '#supplier-part-menu-toggle' +}) + +$('#order-part, #order-part2').click(function() { + launchModalForm( + "{% url 'order-parts' %}", + { + data: { + part: {{ part.part.id }}, + }, + reload: true, + }, + ); +}); + +$('#edit-part').click(function () { + launchModalForm( + "{% url 'supplier-part-edit' part.id %}", + { + reload: true + } + ); +}); + +$('#delete-part').click(function() { + launchModalForm( + "{% url 'supplier-part-delete' %}?part={{ part.id }}", + { + redirect: "{% url 'company-detail' part.supplier.id %}" + } + ); +}); + +attachNavCallbacks({ + name: 'supplierpart', + default: 'stock' +}); + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/supplier_part_base.html b/InvenTree/company/templates/company/supplier_part_base.html deleted file mode 100644 index 900e0750cc..0000000000 --- a/InvenTree/company/templates/company/supplier_part_base.html +++ /dev/null @@ -1,161 +0,0 @@ -{% extends "two_column.html" %} -{% load static %} -{% load i18n %} -{% load inventree_extras %} - -{% block page_title %} -{% inventree_title %} | {% trans "Supplier Part" %} -{% endblock %} - -{% block thumbnail %} - -{% endblock %} - -{% block page_data %} -

    {% trans "Supplier Part" %}

    -
    -

    - {{ part.part.full_name }} - {% if user.is_staff and perms.company.change_company %} - - - - {% endif %} -

    -

    {{ part.supplier.name }} - {{ part.SKU }}

    - -{% if roles.purchase_order.change %} -
    -
    - {% if roles.purchase_order.add %} - - {% endif %} - - {% if roles.purchase_order.delete %} - - {% endif %} -
    -
    -{% endif %} - -{% endblock %} - -{% block page_details %} - -

    {% trans "Supplier Part Details" %}

    - - - - - - - - {% if part.description %} - - - - - - {% endif %} - {% if part.link %} - - - - - - {% endif %} - - - - - - - - - - {% if part.manufacturer_part.manufacturer %} - - - - - - {% endif %} - {% if part.manufacturer_part.MPN %} - - - - - - {% endif %} - {% if part.packaging %} - - - - - - {% endif %} - {% if part.note %} - - - - - - {% endif %} -
    {% trans "Internal Part" %} - {% if part.part %} - {{ part.part.full_name }}{% include "clip.html"%} - {% endif %} -
    {% trans "Description" %}{{ part.description }}{% include "clip.html"%}
    {% trans "External Link" %}{{ part.link }}{% include "clip.html"%}
    {% trans "Supplier" %}{{ part.supplier.name }}{% include "clip.html"%}
    {% trans "SKU" %}{{ part.SKU }}{% include "clip.html"%}
    {% trans "Manufacturer" %} - {{ part.manufacturer_part.manufacturer.name }}{% include "clip.html"%}
    {% trans "MPN" %}{{ part.manufacturer_part.MPN }}{% include "clip.html"%}
    {% trans "Packaging" %}{{ part.packaging }}{% include "clip.html"%}
    {% trans "Note" %}{{ part.note }}{% include "clip.html"%}
    -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -enableNavbar({ - label: 'supplier-part', - toggleId: '#supplier-part-menu-toggle' -}) - -$('#order-part, #order-part2').click(function() { - launchModalForm( - "{% url 'order-parts' %}", - { - data: { - part: {{ part.part.id }}, - }, - reload: true, - }, - ); -}); - -$('#edit-part').click(function () { - launchModalForm( - "{% url 'supplier-part-edit' part.id %}", - { - reload: true - } - ); -}); - -$('#delete-part').click(function() { - launchModalForm( - "{% url 'supplier-part-delete' %}?part={{ part.id }}", - { - redirect: "{% url 'company-detail' part.supplier.id %}" - } - ); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/supplier_part_detail.html b/InvenTree/company/templates/company/supplier_part_detail.html deleted file mode 100644 index 708885043a..0000000000 --- a/InvenTree/company/templates/company/supplier_part_detail.html +++ /dev/null @@ -1,48 +0,0 @@ -{% extends "company/supplier_part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "company/supplier_part_navbar.html" with tab='details' %} -{% endblock %} - -{% block heading %} -{% trans "Supplier Part Details" %} -{% endblock %} - - -{% block details %} - - - - - - - - -{% if part.link %} - -{% endif %} -{% if part.description %} - -{% endif %} -{% if part.manufacturer %} - - -{% endif %} -{% if part.note %} - -{% endif %} -
    {% trans "Internal Part" %} - {% if part.part %} - {{ part.part.full_name }} - {% endif %} -
    {% trans "Supplier" %}{{ part.supplier.name }}
    {% trans "SKU" %}{{ part.SKU }}
    {% trans "External Link" %}{{ part.link }}
    {% trans "Description" %}{{ part.description }}{% include "clip.html"%}
    {% trans "Manufacturer" %}{{ part.manufacturer }}{% include "clip.html"%}
    {% trans "MPN" %}{{ part.MPN }}{% include "clip.html"%}
    {% trans "Note" %}{{ part.note }}{% include "clip.html"%}
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/supplier_part_navbar.html b/InvenTree/company/templates/company/supplier_part_navbar.html index e52c1798ba..4f7783701a 100644 --- a/InvenTree/company/templates/company/supplier_part_navbar.html +++ b/InvenTree/company/templates/company/supplier_part_navbar.html @@ -9,22 +9,22 @@ -
  • - +
  • + {% trans "Stock" %}
  • -
  • - +
  • + {% trans "Orders" %}
  • -
  • - +
  • + {% trans "Pricing" %} diff --git a/InvenTree/company/templates/company/supplier_part_orders.html b/InvenTree/company/templates/company/supplier_part_orders.html deleted file mode 100644 index 05e425fc97..0000000000 --- a/InvenTree/company/templates/company/supplier_part_orders.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "company/supplier_part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "company/supplier_part_navbar.html" with tab='orders' %} -{% endblock %} - -{% block heading %} -{% trans "Supplier Part Orders" %} -{% endblock %} - -{% block details %} -{% if roles.purchase_order.add %} -
    -
    - -
    -
    -{% endif %} - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadPurchaseOrderTable($("#purchase-order-table"), { - url: "{% url 'api-po-list' %}?supplier_part={{ part.id }}", -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/supplier_part_pricing.html b/InvenTree/company/templates/company/supplier_part_pricing.html deleted file mode 100644 index a476b53a13..0000000000 --- a/InvenTree/company/templates/company/supplier_part_pricing.html +++ /dev/null @@ -1,124 +0,0 @@ -{% extends "company/supplier_part_base.html" %} -{% load static %} -{% load i18n %} -{% load inventree_extras %} - -{% block menubar %} -{% include "company/supplier_part_navbar.html" with tab='pricing' %} -{% endblock %} - -{% block heading %} -{% trans "Pricing Information" %} -{% endblock %} - -{% block details %} - -{% if roles.purchase_order.add %} -
    - -
    -{% endif %} - - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -function reloadPriceBreaks() { - $("#price-break-table").bootstrapTable("refresh"); -} - -$('#price-break-table').inventreeTable({ - name: 'buypricebreaks', - formatNoMatches: function() { return "{% trans "No price break information found" %}"; }, - queryParams: { - part: {{ part.id }}, - }, - url: "{% url 'api-part-supplier-price-list' %}", - onPostBody: function() { - var table = $('#price-break-table'); - - table.find('.button-price-break-delete').click(function() { - var pk = $(this).attr('pk'); - - constructForm(`/api/company/price-break/${pk}/`, { - method: 'DELETE', - onSuccess: reloadPriceBreaks, - title: '{% trans "Delete Price Break" %}', - }); - }); - - table.find('.button-price-break-edit').click(function() { - var pk = $(this).attr('pk'); - - constructForm(`/api/company/price-break/${pk}/`, { - fields: { - quantity: {}, - price: {}, - price_currency: {}, - }, - onSuccess: reloadPriceBreaks, - title: '{% trans "Edit Price Break" %}', - }); - }); - }, - columns: [ - { - field: 'pk', - title: 'ID', - visible: false, - switchable: false, - }, - { - field: 'quantity', - title: '{% trans "Quantity" %}', - sortable: true, - }, - { - field: 'price', - title: '{% trans "Price" %}', - sortable: true, - formatter: function(value, row, index) { - var html = value; - - html += `
    ` - - html += makeIconButton('fa-edit icon-blue', 'button-price-break-edit', row.pk, '{% trans "Edit price break" %}'); - html += makeIconButton('fa-trash-alt icon-red', 'button-price-break-delete', row.pk, '{% trans "Delete price break" %}'); - - html += `
    `; - - return html; - } - }, - ] -}); - -$('#new-price-break').click(function() { - - constructForm( - '{% url "api-part-supplier-price-list" %}', - { - method: 'POST', - fields: { - quantity: {}, - part: { - value: {{ part.pk }}, - hidden: true, - }, - price: {}, - price_currency: { - }, - }, - title: '{% trans "Add Price Break" %}', - onSuccess: reloadPriceBreaks, - } - ); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/supplier_part_stock.html b/InvenTree/company/templates/company/supplier_part_stock.html deleted file mode 100644 index 1187b95bca..0000000000 --- a/InvenTree/company/templates/company/supplier_part_stock.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends "company/supplier_part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "company/supplier_part_navbar.html" with tab='stock' %} -{% endblock %} - -{% block heading %} -{% trans "Supplier Part Stock" %} -{% endblock %} - -{% block details %} -{% include "stock_table.html" %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - loadStockTable($("#stock-table"), { - params: { - supplier_part: {{ part.id }}, - location_detail: true, - part_detail: false, - }, - groupByField: 'location', - buttons: ['#stock-options'], - url: "{% url 'api-stock-list' %}", - }); - - $("#stock-export").click(function() { - launchModalForm("{% url 'stock-export-options' %}", { - submit_text: '{% trans "Export" %}', - success: function(response) { - var url = "{% url 'stock-export' %}"; - - url += "?format=" + response.format; - url += "&cascade=" + response.cascade; - url += "&supplier_part={{ part.id }}"; - - location.href = url; - }, - }); - }); - - $("#item-create").click(function() { - createNewStockItem({ - data: { - part: {{ part.part.id }}, - supplier_part: {{ part.id }}, - }, - reload: true, - }); - }); - - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index 4f844176ee..817ee27988 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -39,12 +39,7 @@ manufacturer_part_urls = [ supplier_part_detail_urls = [ url(r'^edit/?', views.SupplierPartEdit.as_view(), name='supplier-part-edit'), - url(r'^manufacturers/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_manufacturers.html'), name='supplier-part-manufacturers'), - url(r'^pricing/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_pricing.html'), name='supplier-part-pricing'), - url(r'^orders/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_orders.html'), name='supplier-part-orders'), - url(r'^stock/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_stock.html'), name='supplier-part-stock'), - - url('^.*$', views.SupplierPartDetail.as_view(template_name='company/supplier_part_pricing.html'), name='supplier-part-detail'), + url('^.*$', views.SupplierPartDetail.as_view(template_name='company/supplier_part.html'), name='supplier-part-detail'), ] supplier_part_urls = [ diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index 224d855aa3..0aee97a5e3 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -244,11 +244,11 @@ "{% url 'category-create' %}", { follow: true, - {% if category %} data: { + {% if category %} category: {{ category.id }} + {% endif %} }, - {% endif %} secondary: [ { field: 'default_location', From 676cca89a1745058986dcc6f3dc3868e95a230b8 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 21:32:46 +1000 Subject: [PATCH 27/35] Refactor ManufacturerPart pages --- .../templates/company/manufacturer_part.html | 330 ++++++++++++++++++ .../company/manufacturer_part_base.html | 143 -------- .../company/manufacturer_part_detail.html | 38 -- .../company/manufacturer_part_navbar.html | 13 +- .../company/manufacturer_part_suppliers.html | 187 ---------- InvenTree/company/urls.py | 3 +- 6 files changed, 341 insertions(+), 373 deletions(-) create mode 100644 InvenTree/company/templates/company/manufacturer_part.html delete mode 100644 InvenTree/company/templates/company/manufacturer_part_base.html delete mode 100644 InvenTree/company/templates/company/manufacturer_part_detail.html delete mode 100644 InvenTree/company/templates/company/manufacturer_part_suppliers.html diff --git a/InvenTree/company/templates/company/manufacturer_part.html b/InvenTree/company/templates/company/manufacturer_part.html new file mode 100644 index 0000000000..da5ea36173 --- /dev/null +++ b/InvenTree/company/templates/company/manufacturer_part.html @@ -0,0 +1,330 @@ +{% extends "two_column.html" %} +{% load static %} +{% load i18n %} + +{% block page_title %} +InvenTree | {% trans "Manufacturer Part" %} +{% endblock %} + +{% block menubar %} +{% include "company/manufacturer_part_navbar.html" %} +{% endblock %} + +{% block thumbnail %} + +{% endblock %} + +{% block page_data %} +

    {% trans "Manufacturer Part" %}

    +
    +

    + {{ part.part.full_name }} + {% if user.is_staff and perms.company.change_company %} + + + + {% endif %} +

    +

    {{ part.manufacturer.name }} - {{ part.MPN }}

    + +{% if roles.purchase_order.change %} +
    +
    + {% comment "for later" %} + {% if roles.purchase_order.add %} + + {% endif %} + {% endcomment %} + + {% if roles.purchase_order.delete %} + + {% endif %} +
    +
    +{% endif %} + +{% endblock %} + +{% block page_details %} + +

    {% trans "Manufacturer Part Details" %}

    + + + + + + + + {% if part.description %} + + + + + + {% endif %} + {% if part.link %} + + + + + + {% endif %} + + + + + + + + + +
    {% trans "Internal Part" %} + {% if part.part %} + {{ part.part.full_name }}{% include "clip.html"%} + {% endif %} +
    {% trans "Description" %}{{ part.description }}{% include "clip.html"%}
    {% trans "External Link" %}{{ part.link }}{% include "clip.html"%}
    {% trans "Manufacturer" %}{{ part.manufacturer.name }}{% include "clip.html"%}
    {% trans "MPN" %}{{ part.MPN }}{% include "clip.html"%}
    +{% endblock %} + +{% block page_content %} + +
    +
    +

    {% trans "Suppliers" %}

    +
    +
    +
    +
    + +
    + + +
    +
    +
    + + +
    +
    +
    + +
    +
    +

    {% trans "Parameters" %}

    +
    +
    +
    +
    + +
    + + +
    +
    +
    + +
    +
    +
    + +{% endblock %} + + +{% block js_ready %} +{{ block.super }} + +enableNavbar({ + label: 'manufacturer-part', + toggleId: '#manufacturer-part-menu-toggle' +}); + +function reloadParameters() { + $("#parameter-table").bootstrapTable("refresh"); +} + +$('#parameter-create').click(function() { + + constructForm('{% url "api-manufacturer-part-parameter-list" %}', { + method: 'POST', + fields: { + name: {}, + value: {}, + units: {}, + manufacturer_part: { + value: {{ part.pk }}, + hidden: true, + } + }, + title: '{% trans "Add Parameter" %}', + onSuccess: reloadParameters + }); +}); + +$('#supplier-create').click(function () { + launchModalForm( + "{% url 'supplier-part-create' %}", + { + reload: true, + data: { + manufacturer_part: {{ part.id }} + }, + secondary: [ + { + field: 'supplier', + label: '{% trans "New Supplier" %}', + title: '{% trans "Create new supplier" %}', + }, + ] + }); +}); + +$("#supplier-part-delete").click(function() { + + var selections = $("#supplier-table").bootstrapTable("getSelections"); + + var parts = []; + + selections.forEach(function(item) { + parts.push(item.pk); + }); + + launchModalForm("{% url 'supplier-part-delete' %}", { + data: { + parts: parts, + }, + reload: true, + }); +}); + +$("#multi-parameter-delete").click(function() { + + var selections = $("#parameter-table").bootstrapTable("getSelections"); + + var text = ` +
    +

    {% trans "Selected parameters will be deleted" %}:

    +
      `; + + selections.forEach(function(item) { + text += `
    • ${item.name} - ${item.value}
    • `; + }); + + text += ` +
    +
    `; + + showQuestionDialog( + '{% trans "Delete Parameters" %}', + text, + { + accept_text: '{% trans "Delete" %}', + accept: function() { + // Delete each parameter via the API + var requests = []; + + selections.forEach(function(item) { + var url = `/api/company/part/manufacturer/parameter/${item.pk}/`; + + requests.push(inventreeDelete(url)); + }); + + $.when.apply($, requests).then(function() { + $('#parameter-table').bootstrapTable('refresh'); + }); + } + } + ); +}); + +loadSupplierPartTable( + "#supplier-table", + "{% url 'api-supplier-part-list' %}", + { + params: { + part: {{ part.part.id }}, + manufacturer_part: {{ part.id }}, + part_detail: false, + supplier_detail: true, + manufacturer_detail: false, + }, + } +); + +loadManufacturerPartParameterTable( + "#parameter-table", + "{% url 'api-manufacturer-part-parameter-list' %}", + { + params: { + manufacturer_part: {{ part.id }}, + } + } +); + +linkButtonsToSelection($("#supplier-table"), ['#supplier-part-options']); + +linkButtonsToSelection($("#parameter-table"), ['#parameter-options']); + +$('#order-part, #order-part2').click(function() { + launchModalForm( + "{% url 'order-parts' %}", + { + data: { + part: {{ part.part.id }}, + }, + reload: true, + }, + ); +}); + +$('#edit-part').click(function () { + + constructForm('{% url "api-manufacturer-part-detail" part.pk %}', { + fields: { + part: {}, + manufacturer: {}, + MPN: { + icon: 'fa-hashtag', + }, + description: {}, + link: { + icon: 'fa-link', + }, + }, + title: '{% trans "Edit Manufacturer Part" %}', + reload: true, + }); +}); + +$('#delete-part').click(function() { + + constructForm('{% url "api-manufacturer-part-detail" part.pk %}', { + method: 'DELETE', + title: '{% trans "Delete Manufacturer Part" %}', + redirect: "{% url 'company-detail' part.manufacturer.id %}", + }); +}); + +attachNavCallbacks({ + name: 'manufacturerpart', + default: 'parameters' +}); + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/manufacturer_part_base.html b/InvenTree/company/templates/company/manufacturer_part_base.html deleted file mode 100644 index c54401b172..0000000000 --- a/InvenTree/company/templates/company/manufacturer_part_base.html +++ /dev/null @@ -1,143 +0,0 @@ -{% extends "two_column.html" %} -{% load static %} -{% load i18n %} - -{% block page_title %} -InvenTree | {% trans "Manufacturer Part" %} -{% endblock %} - -{% block thumbnail %} - -{% endblock %} - -{% block page_data %} -

    {% trans "Manufacturer Part" %}

    -
    -

    - {{ part.part.full_name }} - {% if user.is_staff and perms.company.change_company %} - - - - {% endif %} -

    -

    {{ part.manufacturer.name }} - {{ part.MPN }}

    - -{% if roles.purchase_order.change %} -
    -
    - {% comment "for later" %} - {% if roles.purchase_order.add %} - - {% endif %} - {% endcomment %} - - {% if roles.purchase_order.delete %} - - {% endif %} -
    -
    -{% endif %} - -{% endblock %} - -{% block page_details %} - -

    {% trans "Manufacturer Part Details" %}

    - - - - - - - - {% if part.description %} - - - - - - {% endif %} - {% if part.link %} - - - - - - {% endif %} - - - - - - - - - -
    {% trans "Internal Part" %} - {% if part.part %} - {{ part.part.full_name }}{% include "clip.html"%} - {% endif %} -
    {% trans "Description" %}{{ part.description }}{% include "clip.html"%}
    {% trans "External Link" %}{{ part.link }}{% include "clip.html"%}
    {% trans "Manufacturer" %}{{ part.manufacturer.name }}{% include "clip.html"%}
    {% trans "MPN" %}{{ part.MPN }}{% include "clip.html"%}
    -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -enableNavbar({ - label: 'manufacturer-part', - toggleId: '#manufacturer-part-menu-toggle' -}) - -$('#order-part, #order-part2').click(function() { - launchModalForm( - "{% url 'order-parts' %}", - { - data: { - part: {{ part.part.id }}, - }, - reload: true, - }, - ); -}); - -$('#edit-part').click(function () { - - constructForm('{% url "api-manufacturer-part-detail" part.pk %}', { - fields: { - part: {}, - manufacturer: {}, - MPN: { - icon: 'fa-hashtag', - }, - description: {}, - link: { - icon: 'fa-link', - }, - }, - title: '{% trans "Edit Manufacturer Part" %}', - reload: true, - }); -}); - -$('#delete-part').click(function() { - - constructForm('{% url "api-manufacturer-part-detail" part.pk %}', { - method: 'DELETE', - title: '{% trans "Delete Manufacturer Part" %}', - redirect: "{% url 'company-detail' part.manufacturer.id %}", - }); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/manufacturer_part_detail.html b/InvenTree/company/templates/company/manufacturer_part_detail.html deleted file mode 100644 index e25fb9dca3..0000000000 --- a/InvenTree/company/templates/company/manufacturer_part_detail.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "company/manufacturer_part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "company/manufacturer_part_navbar.html" with tab='details' %} -{% endblock %} - -{% block heading %} -{% trans "Manufacturer Part Details" %} -{% endblock %} - - -{% block details %} - - - - - - - - -{% if part.link %} - -{% endif %} -
    {% trans "Internal Part" %} - {% if part.part %} - {{ part.part.full_name }} - {% endif %} -
    {% trans "Manufacturer" %}{{ part.manufacturer.name }}
    {% trans "MPN" %}{{ part.MPN }}
    {% trans "External Link" %}{{ part.link }}
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/manufacturer_part_navbar.html b/InvenTree/company/templates/company/manufacturer_part_navbar.html index 3eae30afaf..893374858f 100644 --- a/InvenTree/company/templates/company/manufacturer_part_navbar.html +++ b/InvenTree/company/templates/company/manufacturer_part_navbar.html @@ -8,8 +8,15 @@
  • -
  • - +
  • + + + {% trans "Parameters" %} + +
  • + +
  • + {% trans "Suppliers" %} @@ -22,7 +29,7 @@ {% trans "Stock" %}
  • - +
  • diff --git a/InvenTree/company/templates/company/manufacturer_part_suppliers.html b/InvenTree/company/templates/company/manufacturer_part_suppliers.html deleted file mode 100644 index f706ca90ba..0000000000 --- a/InvenTree/company/templates/company/manufacturer_part_suppliers.html +++ /dev/null @@ -1,187 +0,0 @@ -{% extends "company/manufacturer_part_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "company/manufacturer_part_navbar.html" with tab='suppliers' %} -{% endblock %} - -{% block heading %} -{% trans "Suppliers" %} -{% endblock %} - -{% block details %} - - - -
    - -{% endblock %} - -{% block post_content_panels %} - -
    -
    -

    {% trans "Parameters" %}

    -
    -
    -
    -
    - -
    - - -
    -
    -
    - -
    -
    -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -function reloadParameters() { - $("#parameter-table").bootstrapTable("refresh"); -} - -$('#parameter-create').click(function() { - - constructForm('{% url "api-manufacturer-part-parameter-list" %}', { - method: 'POST', - fields: { - name: {}, - value: {}, - units: {}, - manufacturer_part: { - value: {{ part.pk }}, - hidden: true, - } - }, - title: '{% trans "Add Parameter" %}', - onSuccess: reloadParameters - }); -}); - -$('#supplier-create').click(function () { - launchModalForm( - "{% url 'supplier-part-create' %}", - { - reload: true, - data: { - manufacturer_part: {{ part.id }} - }, - secondary: [ - { - field: 'supplier', - label: '{% trans "New Supplier" %}', - title: '{% trans "Create new supplier" %}', - }, - ] - }); -}); - -$("#supplier-part-delete").click(function() { - - var selections = $("#supplier-table").bootstrapTable("getSelections"); - - var parts = []; - - selections.forEach(function(item) { - parts.push(item.pk); - }); - - launchModalForm("{% url 'supplier-part-delete' %}", { - data: { - parts: parts, - }, - reload: true, - }); -}); - -$("#multi-parameter-delete").click(function() { - - var selections = $("#parameter-table").bootstrapTable("getSelections"); - - var text = ` -
    -

    {% trans "Selected parameters will be deleted" %}:

    -
      `; - - selections.forEach(function(item) { - text += `
    • ${item.name} - ${item.value}
    • `; - }); - - text += ` -
    -
    `; - - showQuestionDialog( - '{% trans "Delete Parameters" %}', - text, - { - accept_text: '{% trans "Delete" %}', - accept: function() { - // Delete each parameter via the API - var requests = []; - - selections.forEach(function(item) { - var url = `/api/company/part/manufacturer/parameter/${item.pk}/`; - - requests.push(inventreeDelete(url)); - }); - - $.when.apply($, requests).then(function() { - $('#parameter-table').bootstrapTable('refresh'); - }); - } - } - ); -}); - -loadSupplierPartTable( - "#supplier-table", - "{% url 'api-supplier-part-list' %}", - { - params: { - part: {{ part.part.id }}, - manufacturer_part: {{ part.id }}, - part_detail: false, - supplier_detail: true, - manufacturer_detail: false, - }, - } -); - -loadManufacturerPartParameterTable( - "#parameter-table", - "{% url 'api-manufacturer-part-parameter-list' %}", - { - params: { - manufacturer_part: {{ part.id }}, - } - } -); - -linkButtonsToSelection($("#supplier-table"), ['#supplier-part-options']) -linkButtonsToSelection($("#parameter-table"), ['#parameter-options']) -{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index 817ee27988..7d2b6fb609 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -31,8 +31,7 @@ company_urls = [ manufacturer_part_urls = [ url(r'^(?P\d+)/', include([ - url(r'^suppliers/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part_suppliers.html'), name='manufacturer-part-suppliers'), - url('^.*$', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part_suppliers.html'), name='manufacturer-part-detail'), + url('^.*$', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'), ])), ] From b1640fcc2308c42fa625d0a07f2fdd95736bd80b Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 21:38:05 +1000 Subject: [PATCH 28/35] Refactor StockLocation pages --- InvenTree/stock/templates/stock/location.html | 66 ++++++++++++++++- .../templates/stock/location_navbar.html | 14 +--- .../stock/templates/stock/sublocation.html | 74 ------------------- InvenTree/stock/urls.py | 4 +- 4 files changed, 68 insertions(+), 90 deletions(-) delete mode 100644 InvenTree/stock/templates/stock/sublocation.html diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html index d70d9a44be..229ad9cfd1 100644 --- a/InvenTree/stock/templates/stock/location.html +++ b/InvenTree/stock/templates/stock/location.html @@ -4,7 +4,7 @@ {% load i18n %} {% block menubar %} -{% include "stock/location_navbar.html" with tab="stock" %} +{% include "stock/location_navbar.html" %} {% endblock %} {% block content %} @@ -143,13 +143,39 @@ {% block location_content %} -
    +

    {% trans "Stock Items" %}

    {% include "stock_table.html" %}
    +
    +
    +

    {% trans "Sublocations" %}

    +
    +
    +
    +
    + + +
    + +
    +
    +
    + +
    +
    +
    + {% endblock %}
    @@ -164,6 +190,36 @@ toggleId: '#location-menu-toggle' }); + loadStockLocationTable($('#sublocation-table'), { + params: { + {% if location %} + parent: {{ location.pk }}, + {% else %} + parent: 'null', + {% endif %} + } + }); + + linkButtonsToSelection( + $('#sublocation-table'), + [ + '#location-print-options', + ] + ); + + $('#multi-location-print-label').click(function() { + + var selections = $('#sublocation-table').bootstrapTable('getSelections'); + + var locations = []; + + selections.forEach(function(loc) { + locations.push(loc.pk); + }); + + printStockLocationLabels(locations); + }); + {% if location %} $("#barcode-check-in").click(function() { barcodeCheckIn({{ location.id }}); @@ -301,4 +357,10 @@ }, url: "{% url 'api-stock-list' %}", }); + + attachNavCallbacks({ + name: 'stocklocation', + default: 'stock' + }); + {% endblock %} diff --git a/InvenTree/stock/templates/stock/location_navbar.html b/InvenTree/stock/templates/stock/location_navbar.html index a4974d0d37..d03761e460 100644 --- a/InvenTree/stock/templates/stock/location_navbar.html +++ b/InvenTree/stock/templates/stock/location_navbar.html @@ -8,23 +8,15 @@
  • -
  • - {% if location %} - - {% else %} - - {% endif %} +
  • + {% trans "Sublocations" %}
  • - {% if location %} - - {% else %} - - {% endif %} + {% trans "Stock Items" %} diff --git a/InvenTree/stock/templates/stock/sublocation.html b/InvenTree/stock/templates/stock/sublocation.html deleted file mode 100644 index be9390df3b..0000000000 --- a/InvenTree/stock/templates/stock/sublocation.html +++ /dev/null @@ -1,74 +0,0 @@ -{% extends "stock/location.html" %} - -{% load static %} -{% load i18n %} -{% load inventree_extras %} - -{% block menubar %} -{% include "stock/location_navbar.html" with tab="sublocations" %} -{% endblock %} - - -{% block location_content %} - -
    -
    -

    {% trans "Sublocations" %}

    -
    - -
    -
    - - -
    - -
    -
    -
    - -
    -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadStockLocationTable($('#sublocation-table'), { - params: { - {% if location %} - parent: {{ location.pk }}, - {% else %} - parent: 'null', - {% endif %} - } -}); - -linkButtonsToSelection( - $('#sublocation-table'), - [ - '#location-print-options', - ] -); - -$('#multi-location-print-label').click(function() { - - var selections = $('#sublocation-table').bootstrapTable('getSelections'); - - var locations = []; - - selections.forEach(function(loc) { - locations.push(loc.pk); - }); - - printStockLocationLabels(locations); -}) - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py index 67101c1f3b..adae836d92 100644 --- a/InvenTree/stock/urls.py +++ b/InvenTree/stock/urls.py @@ -14,9 +14,7 @@ location_urls = [ url(r'^edit/?', views.StockLocationEdit.as_view(), name='stock-location-edit'), url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'), url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'), - - url(r'sublocation/', views.StockLocationDetail.as_view(template_name='stock/sublocation.html'), name='stock-location-sublocation'), - + # Anything else url('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'), ])), From 533a3aa3680c82817faef443719aab1ab578e243 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 22:19:13 +1000 Subject: [PATCH 29/35] Refactor StockItem pages --- InvenTree/stock/templates/stock/item.html | 360 ++++++++++++++++-- .../templates/stock/item_attachments.html | 86 ----- .../stock/templates/stock/item_base.html | 6 + .../stock/templates/stock/item_childs.html | 45 --- .../stock/templates/stock/item_installed.html | 53 --- .../stock/templates/stock/item_notes.html | 51 --- .../stock/templates/stock/item_tests.html | 150 -------- InvenTree/stock/templates/stock/navbar.html | 24 +- InvenTree/stock/urls.py | 6 - InvenTree/templates/stock_table.html | 4 +- 10 files changed, 358 insertions(+), 427 deletions(-) delete mode 100644 InvenTree/stock/templates/stock/item_attachments.html delete mode 100644 InvenTree/stock/templates/stock/item_childs.html delete mode 100644 InvenTree/stock/templates/stock/item_installed.html delete mode 100644 InvenTree/stock/templates/stock/item_notes.html delete mode 100644 InvenTree/stock/templates/stock/item_tests.html diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html index 7564e7864e..8a00c1c5e6 100644 --- a/InvenTree/stock/templates/stock/item.html +++ b/InvenTree/stock/templates/stock/item.html @@ -3,44 +3,360 @@ {% load static %} {% load inventree_extras %} {% load i18n %} +{% load markdownify %} {% block menubar %} -{% include "stock/navbar.html" with tab="tracking" %} +{% include "stock/navbar.html" %} {% endblock %} -{% block heading %} -{% trans "Stock Tracking Information" %} -{% endblock %} +{% block page_content %} -{% block details %} +
    +
    +

    {% trans "Stock Tracking Information" %}

    +
    +
    + {% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} + {% if owner_control.value == "True" %} + {% authorized_owners item.owner as owners %} + {% endif %} + + {% if owner_control.value == "False" or owner_control.value == "True" and user in owners %} + {% if roles.stock.change and not item.is_building %} +
    +
    + +
    +
    + {% endif %} + {% endif %} + +
    +
    +
    -{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} -{% if owner_control.value == "True" %} - {% authorized_owners item.owner as owners %} -{% endif %} +
    +
    +

    {% trans "Child Stock Items" %}

    +
    +
    + {% if item.child_count > 0 %} + {% include "stock_table.html" with prefix="childs-" %} + {% else %} +
    + {% trans "This stock item does not have any child items" %} +
    + {% endif %} +
    +
    -
    +
    +
    +

    {% trans "Test Data" %}

    +
    +
    +
    +
    +
    + {% if user.is_staff %} + + {% endif %} + + +
    +
    + +
    +
    +
    + +
    +
    +
    - -{% if owner_control.value == "False" or owner_control.value == "True" and user in owners %} - {% if roles.stock.change and not item.is_building %} -
    -
    - +
    +
    +

    {% trans "Attachments" %}

    +
    +
    + {% include "attachment_table.html" %} +
    +
    + +
    +
    +
    +
    +

    {% trans "Stock Item Notes" %}

    +
    +
    +
    + +
    +
    - {% endif %} -{% endif %} - -
    +
    + {% if item.notes %} + {{ item.notes | markdownify }} + {% endif %} +
    +
    + +
    +
    +

    {% trans "Installed Stock Items" %}

    +
    +
    +
    +
    +
    {% endblock %} {% block js_ready %} {{ block.super }} + loadInstalledInTable( + $('#installed-table'), + { + stock_item: {{ item.pk }}, + part: {{ item.part.pk }}, + quantity: {{ item.quantity }}, + } + ); + + $('#multi-item-uninstall').click(function() { + + var selections = $('#installed-table').bootstrapTable('getSelections'); + + var items = []; + + selections.forEach(function(item) { + items.push(item.pk); + }); + + launchModalForm( + "{% url 'stock-item-uninstall' %}", + { + data: { + 'items[]': items, + }, + reload: true, + } + ); + }); + + $('#edit-notes').click(function() { + constructForm('{% url "api-stock-detail" item.pk %}', { + fields: { + notes: { + multiline: true, + } + }, + title: '{% trans "Edit Notes" %}', + reload: true, + }); + }); + + enableDragAndDrop( + '#attachment-dropzone', + "{% url 'api-stock-attachment-list' %}", + { + data: { + stock_item: {{ item.id }}, + }, + label: 'attachment', + success: function(data, status, xhr) { + reloadAttachmentTable(); + } + } + ); + + loadAttachmentTable( + '{% url "api-stock-attachment-list" %}', + { + filters: { + stock_item: {{ item.pk }}, + }, + onEdit: function(pk) { + var url = `/api/stock/attachment/${pk}/`; + + constructForm(url, { + fields: { + comment: {}, + }, + title: '{% trans "Edit Attachment" %}', + onSuccess: reloadAttachmentTable + }); + }, + onDelete: function(pk) { + var url = `/api/stock/attachment/${pk}/`; + + constructForm(url, { + method: 'DELETE', + confirmMessage: '{% trans "Confirm Delete Operation" %}', + title: '{% trans "Delete Attachment" %}', + onSuccess: reloadAttachmentTable, + }); + } + } + ); + + $("#new-attachment").click(function() { + + constructForm( + '{% url "api-stock-attachment-list" %}', + { + method: 'POST', + fields: { + attachment: {}, + comment: {}, + stock_item: { + value: {{ item.pk }}, + hidden: true, + }, + }, + reload: true, + title: '{% trans "Add Attachment" %}', + } + ); + }); + + loadStockTestResultsTable( + $("#test-result-table"), { + part: {{ item.part.id }}, + stock_item: {{ item.id }}, + } + ); + + function reloadTable() { + $("#test-result-table").bootstrapTable("refresh"); + } + + {% if item.has_test_reports %} + $("#test-report").click(function() { + printTestReports([{{ item.pk }}]); + }); + {% endif %} + + {% if user.is_staff %} + $("#delete-test-results").click(function() { + launchModalForm( + "{% url 'stock-item-delete-test-data' item.id %}", + { + success: reloadTable, + } + ); + }); + {% endif %} + + $("#add-test-result").click(function() { + + constructForm('{% url "api-stock-test-result-list" %}', { + method: 'POST', + fields: { + test: {}, + result: {}, + value: {}, + attachment: {}, + notes: {}, + stock_item: { + value: {{ item.pk }}, + hidden: true, + } + }, + title: '{% trans "Add Test Result" %}', + onSuccess: reloadTable, + }); + }); + + $("#test-result-table").on('click', '.button-test-add', function() { + var button = $(this); + + var test_name = button.attr('pk'); + + constructForm('{% url "api-stock-test-result-list" %}', { + method: 'POST', + fields: { + test: { + value: test_name, + }, + result: {}, + value: {}, + attachment: {}, + notes: {}, + stock_item: { + value: {{ item.pk }}, + hidden: true, + } + }, + title: '{% trans "Add Test Result" %}', + onSuccess: reloadTable, + }); + }); + + $("#test-result-table").on('click', '.button-test-edit', function() { + var button = $(this); + + var pk = button.attr('pk'); + + var url = `/api/stock/test/${pk}/`; + + constructForm(url, { + fields: { + test: {}, + result: {}, + value: {}, + attachment: {}, + notes: {}, + }, + title: '{% trans "Edit Test Result" %}', + onSuccess: reloadTable, + }); + }); + + $("#test-result-table").on('click', '.button-test-delete', function() { + var button = $(this); + + var pk = button.attr('pk'); + + var url = `/api/stock/test/${pk}/`; + + constructForm(url, { + method: 'DELETE', + title: '{% trans "Delete Test Result" %}', + onSuccess: reloadTable, + }); + }); + + {% if item.child_count > 0 %} + loadStockTable($("#childs-stock-table"), { + params: { + location_detail: true, + part_detail: false, + ancestor: {{ item.id }}, + }, + name: 'item-childs', + groupByField: 'location', + buttons: [ + '#stock-options', + ], + url: "{% url 'api-stock-list' %}", + }); + {% endif %} + $("#new-entry").click(function() { launchModalForm( "{% url 'stock-tracking-create' item.id %}", diff --git a/InvenTree/stock/templates/stock/item_attachments.html b/InvenTree/stock/templates/stock/item_attachments.html deleted file mode 100644 index 5f9cfdee19..0000000000 --- a/InvenTree/stock/templates/stock/item_attachments.html +++ /dev/null @@ -1,86 +0,0 @@ -{% extends "stock/item_base.html" %} - -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "stock/navbar.html" with tab='attachments' %} -{% endblock %} - -{% block heading %} -{% trans "Stock Item Attachments" %} -{% endblock %} - -{% block details %} -{% include "attachment_table.html" with attachments=item.attachments.all %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -enableDragAndDrop( - '#attachment-dropzone', - "{% url 'api-stock-attachment-list' %}", - { - data: { - stock_item: {{ item.id }}, - }, - label: 'attachment', - success: function(data, status, xhr) { - reloadAttachmentTable(); - } - } - ); - -loadAttachmentTable( - '{% url "api-stock-attachment-list" %}', - { - filters: { - stock_item: {{ item.pk }}, - }, - onEdit: function(pk) { - var url = `/api/stock/attachment/${pk}/`; - - constructForm(url, { - fields: { - comment: {}, - }, - title: '{% trans "Edit Attachment" %}', - onSuccess: reloadAttachmentTable - }); - }, - onDelete: function(pk) { - var url = `/api/stock/attachment/${pk}/`; - - constructForm(url, { - method: 'DELETE', - confirmMessage: '{% trans "Confirm Delete Operation" %}', - title: '{% trans "Delete Attachment" %}', - onSuccess: reloadAttachmentTable, - }); - } - } -); - -$("#new-attachment").click(function() { - - constructForm( - '{% url "api-stock-attachment-list" %}', - { - method: 'POST', - fields: { - attachment: {}, - comment: {}, - stock_item: { - value: {{ item.pk }}, - hidden: true, - }, - }, - reload: true, - title: '{% trans "Add Attachment" %}', - } - ); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index ea57b981d8..547806e256 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -428,6 +428,7 @@ {% endif %} + {% endblock %} {% block js_ready %} @@ -610,4 +611,9 @@ $("#stock-return-from-customer").click(function() { {% endif %} +attachNavCallbacks({ + name: 'stockitem', + default: 'history' +}); + {% endblock %} diff --git a/InvenTree/stock/templates/stock/item_childs.html b/InvenTree/stock/templates/stock/item_childs.html deleted file mode 100644 index f5d80e5ad1..0000000000 --- a/InvenTree/stock/templates/stock/item_childs.html +++ /dev/null @@ -1,45 +0,0 @@ -{% extends "stock/item_base.html" %} - -{% load static %} -{% load i18n %} - - -{% block menubar %} -{% include "stock/navbar.html" with tab='children' %} -{% endblock %} - -{% block heading %} -{% trans "Child Stock Items" %} -{% endblock %} - -{% block details %} -{% if item.child_count > 0 %} -{% include "stock_table.html" %} -{% else %} -
    - {% trans "This stock item does not have any child items" %} -
    -{% endif %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -{% if item.child_count > 0 %} -loadStockTable($("#stock-table"), { - params: { - location_detail: true, - part_detail: false, - ancestor: {{ item.id }}, - }, - name: 'item-childs', - groupByField: 'location', - buttons: [ - '#stock-options', - ], - url: "{% url 'api-stock-list' %}", -}); -{% endif %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/stock/templates/stock/item_installed.html b/InvenTree/stock/templates/stock/item_installed.html deleted file mode 100644 index 8902fe00ef..0000000000 --- a/InvenTree/stock/templates/stock/item_installed.html +++ /dev/null @@ -1,53 +0,0 @@ -{% extends "stock/item_base.html" %} - -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "stock/navbar.html" with tab='installed' %} -{% endblock %} - -{% block heading %} -{% trans "Installed Stock Items" %} -{% endblock %} - -{% block details %} -
    - -{% endblock %} - -{% block js_ready %} - -{{ block.super }} - -loadInstalledInTable( - $('#installed-table'), - { - stock_item: {{ item.pk }}, - part: {{ item.part.pk }}, - quantity: {{ item.quantity }}, - } -); - -$('#multi-item-uninstall').click(function() { - - var selections = $('#installed-table').bootstrapTable('getSelections'); - - var items = []; - - selections.forEach(function(item) { - items.push(item.pk); - }); - - launchModalForm( - "{% url 'stock-item-uninstall' %}", - { - data: { - 'items[]': items, - }, - reload: true, - } - ); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/stock/templates/stock/item_notes.html b/InvenTree/stock/templates/stock/item_notes.html deleted file mode 100644 index 788f7fb3bd..0000000000 --- a/InvenTree/stock/templates/stock/item_notes.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends "stock/item_base.html" %} - -{% load static %} -{% load inventree_extras %} -{% load i18n %} -{% load markdownify %} - -{% block menubar %} -{% include "stock/navbar.html" with tab="notes" %} -{% endblock %} - -{% block heading %} -{% trans "Stock Item Notes" %} -{% if roles.stock.change and not editing %} - -{% endif %} -{% endblock %} - -{% block details %} -{% if editing %} -
    - {% csrf_token %} - - {{ form }} -
    - -
    - -{{ form.media }} - -{% else %} -{% if item.notes %} -{{ item.notes | markdownify }} -{% endif %} - -{% endif %} - -{% endblock %} - -{% block js_ready %} - -{{ block.super }} - -{% if editing %} -{% else %} -$("#edit-notes").click(function() { - location.href = "{% url 'stock-item-notes' item.id %}?edit=1"; -}); -{% endif %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/stock/templates/stock/item_tests.html b/InvenTree/stock/templates/stock/item_tests.html deleted file mode 100644 index d7d26fcbba..0000000000 --- a/InvenTree/stock/templates/stock/item_tests.html +++ /dev/null @@ -1,150 +0,0 @@ -{% extends "stock/item_base.html" %} - -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "stock/navbar.html" with tab='tests' %} -{% endblock %} - -{% block heading %} -{% trans "Test Data" %} -{% endblock %} - -{% block details %} -
    -
    -
    - {% if user.is_staff %} - - {% endif %} - - -
    -
    - -
    -
    -
    - -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -loadStockTestResultsTable( - $("#test-result-table"), { - part: {{ item.part.id }}, - stock_item: {{ item.id }}, - } -); - -function reloadTable() { - $("#test-result-table").bootstrapTable("refresh"); -} - -{% if item.has_test_reports %} -$("#test-report").click(function() { - printTestReports([{{ item.pk }}]); -}); -{% endif %} - -{% if user.is_staff %} -$("#delete-test-results").click(function() { - launchModalForm( - "{% url 'stock-item-delete-test-data' item.id %}", - { - success: reloadTable, - } - ); -}); -{% endif %} - -$("#add-test-result").click(function() { - - constructForm('{% url "api-stock-test-result-list" %}', { - method: 'POST', - fields: { - test: {}, - result: {}, - value: {}, - attachment: {}, - notes: {}, - stock_item: { - value: {{ item.pk }}, - hidden: true, - } - }, - title: '{% trans "Add Test Result" %}', - onSuccess: reloadTable, - }); -}); - -$("#test-result-table").on('click', '.button-test-add', function() { - var button = $(this); - - var test_name = button.attr('pk'); - - constructForm('{% url "api-stock-test-result-list" %}', { - method: 'POST', - fields: { - test: { - value: test_name, - }, - result: {}, - value: {}, - attachment: {}, - notes: {}, - stock_item: { - value: {{ item.pk }}, - hidden: true, - } - }, - title: '{% trans "Add Test Result" %}', - onSuccess: reloadTable, - }); -}); - -$("#test-result-table").on('click', '.button-test-edit', function() { - var button = $(this); - - var pk = button.attr('pk'); - - var url = `/api/stock/test/${pk}/`; - - constructForm(url, { - fields: { - test: {}, - result: {}, - value: {}, - attachment: {}, - notes: {}, - }, - title: '{% trans "Edit Test Result" %}', - onSuccess: reloadTable, - }); -}); - -$("#test-result-table").on('click', '.button-test-delete', function() { - var button = $(this); - - var pk = button.attr('pk'); - - var url = `/api/stock/test/${pk}/`; - - constructForm(url, { - method: 'DELETE', - title: '{% trans "Delete Test Result" %}', - onSuccess: reloadTable, - }); -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/stock/templates/stock/navbar.html b/InvenTree/stock/templates/stock/navbar.html index 7c7d197a1a..90c0075ba0 100644 --- a/InvenTree/stock/templates/stock/navbar.html +++ b/InvenTree/stock/templates/stock/navbar.html @@ -8,24 +8,24 @@
  • -
  • - +
  • + {% trans "History" %}
  • {% if item.part.trackable %} -
  • - +
  • + {% trans "Test Data" %}
  • {% if item.part.assembly %} -
  • - +
  • + {% trans "Installed Items" %} @@ -35,8 +35,8 @@ {% endif %} {% if item.child_count > 0 %} -
  • - +
  • + {% trans "Children" %} @@ -44,15 +44,15 @@ {% endif %} -
  • - +
  • + {% trans "Attachments" %}
  • -
  • - +
  • + {% trans "Notes" %} diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py index adae836d92..bcf180b700 100644 --- a/InvenTree/stock/urls.py +++ b/InvenTree/stock/urls.py @@ -34,12 +34,6 @@ stock_item_detail_urls = [ url(r'^add_tracking/', views.StockItemTrackingCreate.as_view(), name='stock-tracking-create'), - url(r'^test/', views.StockItemDetail.as_view(template_name='stock/item_tests.html'), name='stock-item-test-results'), - url(r'^children/', views.StockItemDetail.as_view(template_name='stock/item_childs.html'), name='stock-item-children'), - url(r'^attachments/', views.StockItemDetail.as_view(template_name='stock/item_attachments.html'), name='stock-item-attachments'), - url(r'^installed/', views.StockItemDetail.as_view(template_name='stock/item_installed.html'), name='stock-item-installed'), - url(r'^notes/', views.StockItemNotes.as_view(), name='stock-item-notes'), - url('^.*$', views.StockItemDetail.as_view(), name='stock-item-detail'), ] diff --git a/InvenTree/templates/stock_table.html b/InvenTree/templates/stock_table.html index d917bac72a..583f4db893 100644 --- a/InvenTree/templates/stock_table.html +++ b/InvenTree/templates/stock_table.html @@ -8,7 +8,7 @@ {% authorized_owners location.owner as owners %} {% endif %} -
    +
    - +
    From 0fc558068fad936f3a80b9e8ad74c9b11d2aa8bf Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 22:40:14 +1000 Subject: [PATCH 30/35] Refactor BuildOrder pages --- InvenTree/build/templates/build/allocate.html | 101 ---- .../build/templates/build/attachments.html | 84 --- .../build/templates/build/build_base.html | 6 + .../build/templates/build/build_children.html | 40 -- .../build/templates/build/build_output.html | 103 ---- InvenTree/build/templates/build/detail.html | 558 ++++++++++++++---- InvenTree/build/templates/build/navbar.html | 25 +- InvenTree/build/templates/build/notes.html | 51 -- InvenTree/build/urls.py | 15 +- InvenTree/build/views.py | 56 +- InvenTree/templates/js/nav.js | 1 - 11 files changed, 458 insertions(+), 582 deletions(-) delete mode 100644 InvenTree/build/templates/build/allocate.html delete mode 100644 InvenTree/build/templates/build/attachments.html delete mode 100644 InvenTree/build/templates/build/build_children.html delete mode 100644 InvenTree/build/templates/build/build_output.html delete mode 100644 InvenTree/build/templates/build/notes.html diff --git a/InvenTree/build/templates/build/allocate.html b/InvenTree/build/templates/build/allocate.html deleted file mode 100644 index de07614c8e..0000000000 --- a/InvenTree/build/templates/build/allocate.html +++ /dev/null @@ -1,101 +0,0 @@ -{% extends "build/build_base.html" %} -{% load static %} -{% load i18n %} -{% load inventree_extras %} - -{% block page_title %} -{% inventree_title %} | {% trans "Allocate Parts" %} -{% endblock %} - -{% block menubar %} -{% include "build/navbar.html" with tab='allocate' %} -{% endblock %} - -{% block heading %} -{% trans "Allocate Stock to Build" %} -{% endblock %} - -{% block details %} -{% if build.has_untracked_bom_items %} -{% if build.active %} -
    - - - -
    -{% if build.areUntrackedPartsFullyAllocated %} -
    - {% trans "Untracked stock has been fully allocated for this Build Order" %} -
    -{% else %} -
    - {% trans "Untracked stock has not been fully allocated for this Build Order" %} -
    -{% endif %} -{% endif %} -
    -{% else %} -
    - {% trans "This Build Order does not have any associated untracked BOM items" %} -
    -{% endif %} -{% endblock %} - -{% block js_ready %} -{{ block.super }} - - var buildInfo = { - pk: {{ build.pk }}, - quantity: {{ build.quantity }}, - completed: {{ build.completed }}, - part: {{ build.part.pk }}, - }; - - {% if build.has_untracked_bom_items %} - // Load allocation table for un-tracked parts - loadBuildOutputAllocationTable(buildInfo, null); - {% endif %} - - function reloadTable() { - $('#allocation-table-untracked').bootstrapTable('refresh'); - } - - {% if build.active %} - $("#btn-auto-allocate").on('click', function() { - launchModalForm( - "{% url 'build-auto-allocate' build.id %}", - { - success: reloadTable, - } - ); - }); - - $('#btn-unallocate').on('click', function() { - launchModalForm( - "{% url 'build-unallocate' build.id %}", - { - success: reloadTable, - } - ); - }); - - $("#btn-order-parts").click(function() { - launchModalForm("/order/purchase-order/order-parts/", { - data: { - build: {{ build.id }}, - }, - }); - }); - - {% endif %} - -{% endblock %} - \ No newline at end of file diff --git a/InvenTree/build/templates/build/attachments.html b/InvenTree/build/templates/build/attachments.html deleted file mode 100644 index e969756b81..0000000000 --- a/InvenTree/build/templates/build/attachments.html +++ /dev/null @@ -1,84 +0,0 @@ -{% extends "build/build_base.html" %} - -{% load static %} -{% load i18n %} -{% load markdownify %} - -{% block menubar %} -{% include "build/navbar.html" with tab='attachments' %} -{% endblock %} - -{% block heading %} -{% trans "Attachments" %} -{% endblock %} - -{% block details %} -{% include "attachment_table.html" with attachments=build.attachments.all %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -enableDragAndDrop( - '#attachment-dropzone', - '{% url "api-build-attachment-list" %}', - { - data: { - build: {{ build.id }}, - }, - label: 'attachment', - success: function(data, status, xhr) { - location.reload(); - } - } -); - -// Callback for creating a new attachment -$('#new-attachment').click(function() { - - constructForm('{% url "api-build-attachment-list" %}', { - fields: { - attachment: {}, - comment: {}, - build: { - value: {{ build.pk }}, - hidden: true, - } - }, - method: 'POST', - onSuccess: reloadAttachmentTable, - title: '{% trans "Add Attachment" %}', - }); -}); - -loadAttachmentTable( - '{% url "api-build-attachment-list" %}', - { - filters: { - build: {{ build.pk }}, - }, - onEdit: function(pk) { - var url = `/api/build/attachment/${pk}/`; - - constructForm(url, { - fields: { - comment: {}, - }, - onSuccess: reloadAttachmentTable, - title: '{% trans "Edit Attachment" %}', - }); - }, - onDelete: function(pk) { - - constructForm(`/api/build/attachment/${pk}/`, { - method: 'DELETE', - confirmMessage: '{% trans "Confirm Delete Operation" %}', - title: '{% trans "Delete Attachment" %}', - onSuccess: reloadAttachmentTable, - }); - } - } -); - -{% endblock %} diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html index 7100e82838..5770777d28 100644 --- a/InvenTree/build/templates/build/build_base.html +++ b/InvenTree/build/templates/build/build_base.html @@ -238,4 +238,10 @@ src="{% static 'img/blank_image.png' %}" ); }); + attachNavCallbacks({ + name: 'buildorder', + default: 'details' + }); + + {% endblock %} \ No newline at end of file diff --git a/InvenTree/build/templates/build/build_children.html b/InvenTree/build/templates/build/build_children.html deleted file mode 100644 index 3bab257d81..0000000000 --- a/InvenTree/build/templates/build/build_children.html +++ /dev/null @@ -1,40 +0,0 @@ -{% extends "build/build_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "build/navbar.html" with tab="children" %} -{% endblock %} - -{% block heading %} -{% trans "Child Build Orders" %} -{% endblock %} - - -{% block details %} -
    -
    -
    - -
    -
    - -
    - -
    - -{% endblock %} - -{% block js_ready %} - -{{ block.super }} - -loadBuildTable($('#sub-build-table'), { - url: '{% url "api-build-list" %}', - filterTarget: "#filter-list-sub-build", - params: { - ancestor: {{ build.pk }}, - } -}); - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/build/templates/build/build_output.html b/InvenTree/build/templates/build/build_output.html deleted file mode 100644 index 00d7c5d5d2..0000000000 --- a/InvenTree/build/templates/build/build_output.html +++ /dev/null @@ -1,103 +0,0 @@ -{% extends "build/build_base.html" %} -{% load static %} -{% load i18n %} - -{% block menubar %} -{% include "build/navbar.html" with tab='output' %} -{% endblock %} - -{% block content_panels %} - -{% if not build.is_complete %} -
    -
    -

    - {% trans "Incomplete Build Outputs" %} -

    -
    - -
    -
    - {% if build.active %} - - {% endif %} -
    - - {% if build.incomplete_outputs %} -
    - {% for item in build.incomplete_outputs %} - {% include "build/allocation_card.html" with item=item tracked_items=build.has_tracked_bom_items %} - {% endfor %} -
    - {% else %} -
    - {% trans "Create a new build output" %}
    - {% trans "No incomplete build outputs remain." %}
    - {% trans "Create a new build output using the button above" %} -
    - {% endif %} - -
    -
    -{% endif %} - -
    -
    -

    - {% trans "Completed Build Outputs" %} -

    -
    - -
    - {% include "stock_table.html" with read_only=True %} -
    -
    - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -$('#btn-create-output').click(function() { - launchModalForm('{% url "build-output-create" build.id %}', - { - reload: true, - } - ); -}); - -loadStockTable($("#stock-table"), { - params: { - location_detail: true, - part_detail: true, - build: {{ build.id }}, - }, - groupByField: 'location', - buttons: [ - '#stock-options', - ], - url: "{% url 'api-stock-list' %}", -}); - -var buildInfo = { - pk: {{ build.pk }}, - quantity: {{ build.quantity }}, - completed: {{ build.completed }}, - part: {{ build.part.pk }}, -}; - -{% for item in build.incomplete_outputs %} -// Get the build output as a javascript object -inventreeGet('{% url 'api-stock-detail' item.pk %}', {}, - { - success: function(response) { - loadBuildOutputAllocationTable(buildInfo, response); - } - } -); -{% endfor %} - - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/build/templates/build/detail.html b/InvenTree/build/templates/build/detail.html index 63c04f7590..fe716b87f2 100644 --- a/InvenTree/build/templates/build/detail.html +++ b/InvenTree/build/templates/build/detail.html @@ -2,142 +2,446 @@ {% load static %} {% load i18n %} {% load status_codes %} +{% load markdownify %} {% block menubar %} -{% include "build/navbar.html" with tab='details' %} +{% include "build/navbar.html" %} {% endblock %} -{% block heading %} -{% trans "Build Details" %} -{% endblock %} +{% block page_content %} -{% block details %} -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {% if build.batch %} - - - - - - {% endif %} - {% if build.parent %} - - - - - - {% endif %} - {% if build.sales_order %} - - - - - - {% endif %} - {% if build.link %} - - - - - - {% endif %} - {% if build.issued_by %} - - - - - - {% endif %} - {% if build.responsible %} - - - - - - {% endif %} -
    {% trans "Description" %}{{ build.title }}{% include "clip.html"%}
    {% trans "Part" %}{{ build.part.full_name }}{% include "clip.html"%}
    {% trans "Quantity" %}{{ build.quantity }}
    {% trans "Stock Source" %} - {% if build.take_from %} - {{ build.take_from }}{% include "clip.html"%} - {% else %} - {% trans "Stock can be taken from any available location." %} - {% endif %} -
    {% trans "Destination" %} - {% if build.destination %} - - {{ build.destination }} - {% include "clip.html"%} - {% else %} - {% trans "Destination location not specified" %} - {% endif %} -
    {% trans "Status" %}{% build_status_label build.status %}
    {% trans "Progress" %}{{ build.completed }} / {{ build.quantity }}
    {% trans "Batch" %}{{ build.batch }}{% include "clip.html"%}
    {% trans "Parent Build" %}{{ build.parent }}{% include "clip.html"%}
    {% trans "Sales Order" %}{{ build.sales_order }}{% include "clip.html"%}
    {% trans "External Link" %}{{ build.link }}{% include "clip.html"%}
    {% trans "Issued By" %}{{ build.issued_by }}
    {% trans "Responsible" %}{{ build.responsible }}
    +
    +
    +

    {% trans "Build Details" %}

    -
    - - - - - - - - - - - {% if build.target_date %} - - {% else %} - +
    +
    +
    +
    {% trans "Created" %}{{ build.creation_date }}
    {% trans "Target Date" %} - {{ build.target_date }}{% if build.is_overdue %} {% endif %} - {% trans "No target date set" %}
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% if build.batch %} + + + + + {% endif %} - - - - - {% if build.completion_date %} - - {% else %} - + {% if build.parent %} + + + + + {% endif %} - -
    {% trans "Description" %}{{ build.title }}{% include "clip.html"%}
    {% trans "Part" %}{{ build.part.full_name }}{% include "clip.html"%}
    {% trans "Quantity" %}{{ build.quantity }}
    {% trans "Stock Source" %} + {% if build.take_from %} + {{ build.take_from }}{% include "clip.html"%} + {% else %} + {% trans "Stock can be taken from any available location." %} + {% endif %} +
    {% trans "Destination" %} + {% if build.destination %} + + {{ build.destination }} + {% include "clip.html"%} + {% else %} + {% trans "Destination location not specified" %} + {% endif %} +
    {% trans "Status" %}{% build_status_label build.status %}
    {% trans "Progress" %}{{ build.completed }} / {{ build.quantity }}
    {% trans "Batch" %}{{ build.batch }}{% include "clip.html"%}
    {% trans "Completed" %}{{ build.completion_date }}{% if build.completed_by %}{{ build.completed_by }}{% endif %}{% trans "Build not complete" %}
    {% trans "Parent Build" %}{{ build.parent }}{% include "clip.html"%}
    + {% if build.sales_order %} + + + {% trans "Sales Order" %} + {{ build.sales_order }}{% include "clip.html"%} + + {% endif %} + {% if build.link %} + + + {% trans "External Link" %} + {{ build.link }}{% include "clip.html"%} + + {% endif %} + {% if build.issued_by %} + + + {% trans "Issued By" %} + {{ build.issued_by }} + + {% endif %} + {% if build.responsible %} + + + {% trans "Responsible" %} + {{ build.responsible }} + + {% endif %} + +
    +
    + + + + + + + + + + + {% if build.target_date %} + + {% else %} + + {% endif %} + + + + + {% if build.completion_date %} + + {% else %} + + {% endif %} + +
    {% trans "Created" %}{{ build.creation_date }}
    {% trans "Target Date" %} + {{ build.target_date }}{% if build.is_overdue %} {% endif %} + {% trans "No target date set" %}
    {% trans "Completed" %}{{ build.completion_date }}{% if build.completed_by %}{{ build.completed_by }}{% endif %}{% trans "Build not complete" %}
    +
    +
    +
    +
    +

    {% trans "Child Build Orders" %}

    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +

    {% trans "Allocate Stock to Build" %}

    +
    +
    + {% if build.has_untracked_bom_items %} + {% if build.active %} +
    + + + +
    + {% if build.areUntrackedPartsFullyAllocated %} +
    + {% trans "Untracked stock has been fully allocated for this Build Order" %} +
    + {% else %} +
    + {% trans "Untracked stock has not been fully allocated for this Build Order" %} +
    + {% endif %} + {% endif %} +
    + {% else %} +
    + {% trans "This Build Order does not have any associated untracked BOM items" %} +
    + {% endif %} +
    +
    + +
    + {% if not build.is_complete %} +
    +

    {% trans "Incomplete Build Outputs" %}

    +
    +
    +
    + {% if build.active %} + + {% endif %} +
    + + {% if build.incomplete_outputs %} +
    + {% for item in build.incomplete_outputs %} + {% include "build/allocation_card.html" with item=item tracked_items=build.has_tracked_bom_items %} + {% endfor %} +
    + {% else %} +
    + {% trans "Create a new build output" %}
    + {% trans "No incomplete build outputs remain." %}
    + {% trans "Create a new build output using the button above" %} +
    + {% endif %} +
    + {% endif %} + +
    +

    + {% trans "Completed Build Outputs" %} +

    +
    + +
    + {% include "stock_table.html" with read_only=True prefix="build-" %} +
    +
    + +
    +
    +

    {% trans "Attachments" %}

    +
    +
    + {% include "attachment_table.html" %} +
    +
    + +
    +
    +
    +
    +

    {% trans "Build Notes" %}

    +
    +
    +
    + +
    +
    +
    +
    +
    + {% if build.notes %} + {{ build.notes | markdownify }} + {% endif %} +
    +
    + + {% endblock %} + +{% block js_ready %} +{{ block.super }} + +$('#btn-create-output').click(function() { + launchModalForm('{% url "build-output-create" build.id %}', + { + reload: true, + } + ); +}); + +loadStockTable($("#build-stock-table"), { + params: { + location_detail: true, + part_detail: true, + build: {{ build.id }}, + }, + groupByField: 'location', + buttons: [ + '#stock-options', + ], + url: "{% url 'api-stock-list' %}", +}); + +var buildInfo = { + pk: {{ build.pk }}, + quantity: {{ build.quantity }}, + completed: {{ build.completed }}, + part: {{ build.part.pk }}, +}; + +{% for item in build.incomplete_outputs %} +// Get the build output as a javascript object +inventreeGet('{% url 'api-stock-detail' item.pk %}', {}, + { + success: function(response) { + loadBuildOutputAllocationTable(buildInfo, response); + } + } +); +{% endfor %} + +loadBuildTable($('#sub-build-table'), { + url: '{% url "api-build-list" %}', + filterTarget: "#filter-list-sub-build", + params: { + ancestor: {{ build.pk }}, + } +}); + +enableDragAndDrop( + '#attachment-dropzone', + '{% url "api-build-attachment-list" %}', + { + data: { + build: {{ build.id }}, + }, + label: 'attachment', + success: function(data, status, xhr) { + location.reload(); + } + } +); + +// Callback for creating a new attachment +$('#new-attachment').click(function() { + + constructForm('{% url "api-build-attachment-list" %}', { + fields: { + attachment: {}, + comment: {}, + build: { + value: {{ build.pk }}, + hidden: true, + } + }, + method: 'POST', + onSuccess: reloadAttachmentTable, + title: '{% trans "Add Attachment" %}', + }); +}); + +loadAttachmentTable( + '{% url "api-build-attachment-list" %}', + { + filters: { + build: {{ build.pk }}, + }, + onEdit: function(pk) { + var url = `/api/build/attachment/${pk}/`; + + constructForm(url, { + fields: { + comment: {}, + }, + onSuccess: reloadAttachmentTable, + title: '{% trans "Edit Attachment" %}', + }); + }, + onDelete: function(pk) { + + constructForm(`/api/build/attachment/${pk}/`, { + method: 'DELETE', + confirmMessage: '{% trans "Confirm Delete Operation" %}', + title: '{% trans "Delete Attachment" %}', + onSuccess: reloadAttachmentTable, + }); + } + } +); + +$('#edit-notes').click(function() { + constructForm('{% url "api-build-detail" build.pk %}', { + fields: { + notes: { + multiline: true, + } + }, + title: '{% trans "Edit Notes" %}', + reload: true, + }); +}); + +var buildInfo = { + pk: {{ build.pk }}, + quantity: {{ build.quantity }}, + completed: {{ build.completed }}, + part: {{ build.part.pk }}, +}; + +{% if build.has_untracked_bom_items %} +// Load allocation table for un-tracked parts +loadBuildOutputAllocationTable(buildInfo, null); +{% endif %} + +function reloadTable() { + $('#allocation-table-untracked').bootstrapTable('refresh'); +} + +{% if build.active %} +$("#btn-auto-allocate").on('click', function() { + launchModalForm( + "{% url 'build-auto-allocate' build.id %}", + { + success: reloadTable, + } + ); +}); + +$('#btn-unallocate').on('click', function() { + launchModalForm( + "{% url 'build-unallocate' build.id %}", + { + success: reloadTable, + } + ); +}); + +$("#btn-order-parts").click(function() { + launchModalForm("/order/purchase-order/order-parts/", { + data: { + build: {{ build.id }}, + }, + }); +}); + +{% endif %} + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/build/templates/build/navbar.html b/InvenTree/build/templates/build/navbar.html index e6d2e644ce..e4c4fe4e50 100644 --- a/InvenTree/build/templates/build/navbar.html +++ b/InvenTree/build/templates/build/navbar.html @@ -9,46 +9,45 @@
  • -
  • - +
  • + {% trans "Details" %}
  • {% if build.active %} - -
  • - +
  • + {% trans "Allocate Stock" %}
  • {% endif %} -
  • - +
  • + {% trans "Build Outputs" %}
  • -
  • - +
  • + {% trans "Child Builds" %}
  • -
  • - +
  • + {% trans "Attachments" %}
  • -
  • - +
  • + {% trans "Notes" %} diff --git a/InvenTree/build/templates/build/notes.html b/InvenTree/build/templates/build/notes.html deleted file mode 100644 index 2bdbf07970..0000000000 --- a/InvenTree/build/templates/build/notes.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends "build/build_base.html" %} - -{% load static %} -{% load i18n %} -{% load markdownify %} - -{% block menubar %} -{% include "build/navbar.html" with tab='notes' %} -{% endblock %} - -{% block heading %} -{% trans "Build Notes" %} -{% if roles.build.change and not editing %} - -{% endif %} -{% endblock %} - -{% block details %} -{% if editing %} -
    -
    - {% csrf_token %} - - {{ form }} -
    - - -
    - -{{ form.media }} - -{% else %} - -{% if build.notes %} -{{ build.notes | markdownify }} -{% endif %} -{% endif %} - -{% endblock %} - -{% block js_ready %} -{{ block.super }} - -{% if editing %} -{% else %} -$("#edit-notes").click(function() { - location.href = "{% url 'build-notes' build.id %}?edit=1"; -}); -{% endif %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/build/urls.py b/InvenTree/build/urls.py index c354a17ac7..9814dc83f7 100644 --- a/InvenTree/build/urls.py +++ b/InvenTree/build/urls.py @@ -7,30 +7,23 @@ from django.conf.urls import url, include from . import views build_detail_urls = [ - url(r'^allocate/', views.BuildAllocate.as_view(), name='build-allocate'), url(r'^cancel/', views.BuildCancel.as_view(), name='build-cancel'), url(r'^delete/', views.BuildDelete.as_view(), name='build-delete'), url(r'^create-output/', views.BuildOutputCreate.as_view(), name='build-output-create'), url(r'^delete-output/', views.BuildOutputDelete.as_view(), name='build-output-delete'), - url(r'^complete-output/?', views.BuildOutputComplete.as_view(), name='build-output-complete'), - url(r'^auto-allocate/?', views.BuildAutoAllocate.as_view(), name='build-auto-allocate'), + url(r'^complete-output/', views.BuildOutputComplete.as_view(), name='build-output-complete'), + url(r'^auto-allocate/', views.BuildAutoAllocate.as_view(), name='build-auto-allocate'), url(r'^unallocate/', views.BuildUnallocate.as_view(), name='build-unallocate'), url(r'^complete/', views.BuildComplete.as_view(), name='build-complete'), - url(r'^notes/', views.BuildNotes.as_view(), name='build-notes'), - - url(r'^children/', views.BuildDetail.as_view(template_name='build/build_children.html'), name='build-children'), - url(r'^attachments/', views.BuildDetail.as_view(template_name='build/attachments.html'), name='build-attachments'), - url(r'^output/', views.BuildDetail.as_view(template_name='build/build_output.html'), name='build-output'), - url(r'^.*$', views.BuildDetail.as_view(), name='build-detail'), ] build_urls = [ url(r'item/', include([ url(r'^(?P\d+)/', include([ - url('^edit/?', views.BuildItemEdit.as_view(), name='build-item-edit'), - url('^delete/?', views.BuildItemDelete.as_view(), name='build-item-delete'), + url('^edit/', views.BuildItemEdit.as_view(), name='build-item-edit'), + url('^delete/', views.BuildItemDelete.as_view(), name='build-item-delete'), ])), url('^new/', views.BuildItemCreate.as_view(), name='build-item-create'), ])), diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 2bae825b0f..8d2a8bff80 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -593,31 +593,6 @@ class BuildOutputComplete(AjaxUpdateView): } -class BuildNotes(InvenTreeRoleMixin, UpdateView): - """ View for editing the 'notes' field of a Build object. - """ - - context_object_name = 'build' - template_name = 'build/notes.html' - model = Build - - # Override the default permission role for this View - role_required = 'build.view' - - fields = ['notes'] - - def get_success_url(self): - return reverse('build-notes', kwargs={'pk': self.get_object().id}) - - def get_context_data(self, **kwargs): - - ctx = super().get_context_data(**kwargs) - - ctx['editing'] = str2bool(self.request.GET.get('edit', '')) - - return ctx - - class BuildDetail(InvenTreeRoleMixin, DetailView): """ Detail view of a single Build object. """ @@ -635,36 +610,15 @@ class BuildDetail(InvenTreeRoleMixin, DetailView): ctx['BuildStatus'] = BuildStatus ctx['sub_build_count'] = build.sub_build_count() - return ctx - - -class BuildAllocate(InvenTreeRoleMixin, DetailView): - """ View for allocating parts to a Build """ - model = Build - context_object_name = 'build' - template_name = 'build/allocate.html' - - def get_context_data(self, **kwargs): - """ Provide extra context information for the Build allocation page """ - - context = super(DetailView, self).get_context_data(**kwargs) - - build = self.get_object() part = build.part bom_items = build.bom_items - context['part'] = part - context['bom_items'] = bom_items - context['has_tracked_bom_items'] = build.has_tracked_bom_items() - context['has_untracked_bom_items'] = build.has_untracked_bom_items() - context['BuildStatus'] = BuildStatus + ctx['part'] = part + ctx['bom_items'] = bom_items + ctx['has_tracked_bom_items'] = build.has_tracked_bom_items() + ctx['has_untracked_bom_items'] = build.has_untracked_bom_items() - context['bom_price'] = build.part.get_price_info(build.quantity, buy=False) - - if str2bool(self.request.GET.get('edit', None)): - context['editing'] = True - - return context + return ctx class BuildDelete(AjaxDeleteView): diff --git a/InvenTree/templates/js/nav.js b/InvenTree/templates/js/nav.js index f33571d584..aff3435b21 100644 --- a/InvenTree/templates/js/nav.js +++ b/InvenTree/templates/js/nav.js @@ -20,7 +20,6 @@ function attachNavCallbacks(options={}) { activatePanel(panelName, options); }); - var panelClass = options.name || 'unknown'; /* Look for a default panel to initialize From c61fc7c1dfda38023d3380c0226918941a0304ca Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 23:06:37 +1000 Subject: [PATCH 31/35] Refactor part pricing page --- InvenTree/build/views.py | 3 +- InvenTree/part/templates/part/detail.html | 152 ++++++ InvenTree/part/templates/part/navbar.html | 2 +- InvenTree/part/templates/part/prices.html | 618 ++++++++-------------- InvenTree/part/urls.py | 2 - InvenTree/part/views.py | 18 +- InvenTree/templates/js/build.js | 2 +- InvenTree/templates/js/part.js | 2 +- InvenTree/templates/js/stock.js | 2 +- 9 files changed, 366 insertions(+), 435 deletions(-) diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 8d2a8bff80..dfa655f9a4 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -7,9 +7,8 @@ from __future__ import unicode_literals from django.utils.translation import ugettext_lazy as _ from django.core.exceptions import ValidationError -from django.views.generic import DetailView, ListView, UpdateView +from django.views.generic import DetailView, ListView from django.forms import HiddenInput -from django.urls import reverse from part.models import Part from .models import Build, BuildItem diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 2cb430ccf8..d9ef212fae 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -1,6 +1,8 @@ {% extends "part/part_base.html" %} {% load static %} {% load i18n %} +{% load inventree_extras %} +{% load crispy_forms_tags %} {% load markdownify %} {% block menubar %} @@ -92,6 +94,10 @@
  • +
    + {% include "part/prices.html" %} +
    +
    @@ -893,6 +899,152 @@ }); }); + {% default_currency as currency %} + + // history graphs + {% if price_history %} + var purchasepricedata = { + labels: [ + {% for line in price_history %}'{{ line.date }}',{% endfor %} + ], + datasets: [{ + label: '{% blocktrans %}Single Price - {{currency}}{% endblocktrans %}', + backgroundColor: 'rgba(255, 99, 132, 0.2)', + borderColor: 'rgb(255, 99, 132)', + yAxisID: 'y', + data: [ + {% for line in price_history %}{{ line.price|stringformat:".2f" }},{% endfor %} + ], + borderWidth: 1, + type: 'line' + }, + {% if 'price_diff' in price_history.0 %} + { + label: '{% blocktrans %}Single Price Difference - {{currency}}{% endblocktrans %}', + backgroundColor: 'rgba(68, 157, 68, 0.2)', + borderColor: 'rgb(68, 157, 68)', + yAxisID: 'y2', + data: [ + {% for line in price_history %}{{ line.price_diff|stringformat:".2f" }},{% endfor %} + ], + borderWidth: 1, + type: 'line', + hidden: true, + }, + { + label: '{% blocktrans %}Part Single Price - {{currency}}{% endblocktrans %}', + backgroundColor: 'rgba(70, 127, 155, 0.2)', + borderColor: 'rgb(70, 127, 155)', + yAxisID: 'y', + data: [ + {% for line in price_history %}{{ line.price_part|stringformat:".2f" }},{% endfor %} + ], + borderWidth: 1, + type: 'line', + hidden: true, + }, + {% endif %} + { + label: '{% trans "Quantity" %}', + backgroundColor: 'rgba(255, 206, 86, 0.2)', + borderColor: 'rgb(255, 206, 86)', + yAxisID: 'y1', + data: [ + {% for line in price_history %}{{ line.qty|stringformat:"f" }},{% endfor %} + ], + borderWidth: 1 + }] + } + var StockPriceChart = loadStockPricingChart($('#StockPriceChart'), purchasepricedata) + {% endif %} + + {% if bom_parts %} + var bom_colors = randomColor({hue: 'green', count: {{ bom_parts|length }} }) + var bomdata = { + labels: [{% for line in bom_parts %}'{{ line.name }}',{% endfor %}], + datasets: [ + { + label: 'Price', + data: [{% for line in bom_parts %}{{ line.min_price }},{% endfor %}], + backgroundColor: bom_colors, + }, + {% if bom_pie_max %} + { + label: 'Max Price', + data: [{% for line in bom_parts %}{{ line.max_price }},{% endfor %}], + backgroundColor: bom_colors, + }, + {% endif %} + ] + }; + var BomChart = loadBomChart(document.getElementById('BomChart'), bomdata) + {% endif %} + + + // Internal pricebreaks + {% settings_value "PART_INTERNAL_PRICE" as show_internal_price %} + {% if show_internal_price and roles.sales_order.view %} + initPriceBreakSet( + $('#internal-price-break-table'), + { + part_id: {{part.id}}, + pb_human_name: 'internal price break', + pb_url_slug: 'internal-price', + pb_url: '{% url 'api-part-internal-price-list' %}', + pb_new_btn: $('#new-internal-price-break'), + pb_new_url: '{% url 'internal-price-break-create' %}', + linkedGraph: $('#InternalPriceBreakChart'), + }, + ); + {% endif %} + + // Sales pricebreaks + {% if part.salable and roles.sales_order.view %} + initPriceBreakSet( + $('#price-break-table'), + { + part_id: {{part.id}}, + pb_human_name: 'sale price break', + pb_url_slug: 'sale-price', + pb_url: "{% url 'api-part-sale-price-list' %}", + pb_new_btn: $('#new-price-break'), + pb_new_url: '{% url 'sale-price-break-create' %}', + linkedGraph: $('#SalePriceBreakChart'), + }, + ); + {% endif %} + + // Sale price history + {% if sale_history %} + var salepricedata = { + labels: [ + {% for line in sale_history %}'{{ line.date }}',{% endfor %} + ], + datasets: [{ + label: '{% blocktrans %}Unit Price - {{currency}}{% endblocktrans %}', + backgroundColor: 'rgba(255, 99, 132, 0.2)', + borderColor: 'rgb(255, 99, 132)', + yAxisID: 'y', + data: [ + {% for line in sale_history %}{{ line.price|stringformat:".2f" }},{% endfor %} + ], + borderWidth: 1, + }, + { + label: '{% trans "Quantity" %}', + backgroundColor: 'rgba(255, 206, 86, 0.2)', + borderColor: 'rgb(255, 206, 86)', + yAxisID: 'y1', + data: [ + {% for line in sale_history %}{{ line.qty|stringformat:"f" }},{% endfor %} + ], + borderWidth: 1, + type: 'bar', + }] + } + var SalePriceChart = loadSellPricingChart($('#SalePriceChart'), salepricedata) + {% endif %} + attachNavCallbacks({ name: 'part', default: 'part-stock' diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index 4f0e92a80d..8ea1204bc8 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -56,7 +56,7 @@ {% endif %}
  • - + {% trans "Prices" %} diff --git a/InvenTree/part/templates/part/prices.html b/InvenTree/part/templates/part/prices.html index 6e234d3dba..65d36e005a 100644 --- a/InvenTree/part/templates/part/prices.html +++ b/InvenTree/part/templates/part/prices.html @@ -1,176 +1,168 @@ -{% extends "part/part_base.html" %} {% load static %} {% load i18n %} {% load crispy_forms_tags %} {% load inventree_extras %} -{% block menubar %} -{% include 'part/navbar.html' with tab='prices' %} -{% endblock %} +
    +

    {% trans "Pricing Information" %}

    +
    -{% block heading %} -{% trans "General Price Information" %} -{% endblock %} - - -{% block details %} {% default_currency as currency %} +
    -
    - -
    -

    {% trans "Pricing ranges" %}

    - - {% if part.supplier_count > 0 %} - {% if min_total_buy_price %} - - - - - - - {% if quantity > 1 %} - - - - - - - {% endif %} - {% else %} - - - - {% endif %} - {% endif %} - - {% if part.bom_count > 0 %} - {% if min_total_bom_price %} - - - - - - - {% if quantity > 1 %} +
    + +
    +

    {% trans "Pricing ranges" %}

    +
    {% trans 'Supplier Pricing' %} - - - {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_buy_price %}Max: {% include "price.html" with price=max_unit_buy_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_buy_price %}Max: {% include "price.html" with price=max_total_buy_price %}
    - {% trans 'No supplier pricing available' %} -
    {% trans 'BOM Pricing' %} - - {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_bom_price %}Max: {% include "price.html" with price=max_unit_bom_price %}
    + {% if part.supplier_count > 0 %} + {% if min_total_buy_price %} + + + + + + + {% if quantity > 1 %} - - + + - {% endif %} - {% if part.has_complete_bom_pricing == False %} + {% endif %} + {% else %} {% endif %} - {% else %} + {% endif %} + + {% if part.bom_count > 0 %} + {% if min_total_bom_price %} + + + + + + + {% if quantity > 1 %} + + + + + + + {% endif %} + {% if part.has_complete_bom_pricing == False %} + + + + {% endif %} + {% else %} + + + + {% endif %} + {% endif %} + + {% if show_internal_price and roles.sales_order.view %} + {% if total_internal_part_price %} - + + + + + + + + {% endif %} - {% endif %} - - {% if show_internal_price and roles.sales_order.view %} - {% if total_internal_part_price %} - - - - - - - - - - - {% endif %} - {% endif %} - - {% if total_part_price %} - - - - - - - - - - - {% endif %} -
    {% trans 'Supplier Pricing' %} + + + {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_buy_price %}Max: {% include "price.html" with price=max_unit_buy_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_bom_price %}Max: {% include "price.html" with price=max_total_bom_price %}Min: {% include "price.html" with price=min_total_buy_price %}Max: {% include "price.html" with price=max_total_buy_price %}
    - {% trans 'Note: BOM pricing is incomplete for this part' %} + {% trans 'No supplier pricing available' %}
    {% trans 'BOM Pricing' %} + + {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_bom_price %}Max: {% include "price.html" with price=max_unit_bom_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_bom_price %}Max: {% include "price.html" with price=max_total_bom_price %}
    + {% trans 'Note: BOM pricing is incomplete for this part' %} +
    + {% trans 'No BOM pricing available' %} +
    - {% trans 'No BOM pricing available' %} - {% trans 'Internal Price' %}{% trans 'Unit Cost' %}{% include "price.html" with price=unit_internal_part_price %}
    {% trans 'Total Cost' %}{% include "price.html" with price=total_internal_part_price %}
    {% trans 'Internal Price' %}{% trans 'Unit Cost' %}{% include "price.html" with price=unit_internal_part_price %}
    {% trans 'Total Cost' %}{% include "price.html" with price=total_internal_part_price %}
    {% trans 'Sale Price' %} - - - {% trans 'Unit Cost' %}{% include "price.html" with price=unit_part_price %}
    {% trans 'Total Cost' %}{% include "price.html" with price=total_part_price %}
    + {% endif %} + + {% if total_part_price %} + + {% trans 'Sale Price' %} + + + + {% trans 'Unit Cost' %} + {% include "price.html" with price=unit_part_price %} + + + + {% trans 'Total Cost' %} + {% include "price.html" with price=total_part_price %} + + {% endif %} + - {% if min_unit_buy_price or min_unit_bom_price %} - {% else %} -
    - {% trans 'No pricing information is available for this part.' %} -
    - {% endif %} -
    + {% if min_unit_buy_price or min_unit_bom_price %} + {% else %} +
    + {% trans 'No pricing information is available for this part.' %} +
    + {% endif %} +
    -
    -

    {% trans "Calculation parameters" %}

    -
    - {% csrf_token %} - {{ form|crispy }} - -
    +
    +

    {% trans "Calculation parameters" %}

    +
    + {% csrf_token %} + {{ form|crispy }} + +
    +
    -{% endblock %} -{% block post_content_panel %} -{% default_currency as currency %} {% settings_value "PART_INTERNAL_PRICE" as show_internal_price %} - {% if part.purchaseable and roles.purchase_order.view %} -
    - -
    -

    {% trans "Supplier Cost" %} - -

    -
    + +
    +

    {% trans "Supplier Cost" %} + +

    +
    -
    -
    -

    {% trans "Suppliers" %}

    -
    -
    -
    -

    {% trans "Manufacturers" %}

    -
    -
    -
    +
    +
    +
    +

    {% trans "Suppliers" %}

    +
    +
    +
    +

    {% trans "Manufacturers" %}

    +
    +
    +
    -
    - -
    -

    {% trans "Purchase Price" %} - -

    -
    - - {% if price_history %} -

    {% trans 'Stock Pricing' %}

    +{% if price_history %} + +
    +

    {% trans "Purchase Price" %} + +

    +
    +
    +

    {% trans 'Stock Pricing' %} + +

    {% if price_history|length > 0 %}
    @@ -180,52 +172,50 @@ {% trans 'No stock pricing history is available for this part.' %}
    {% endif %} - {% endif %}
    {% endif %} - +{% endif %} {% if show_internal_price and roles.sales_order.view %} -
    - -
    -

    {% trans "Internal Cost" %} - -

    -
    + +
    +

    {% trans "Internal Cost" %} + +

    +
    -
    -
    -
    - -
    +
    +
    +
    +
    +
    -
    -
    - -
    - - -
    +
    +
    +
    +
    -
    + + +
    +
    +
    {% endif %} - {% if part.has_bom and roles.sales_order.view %} -
    - -
    -

    {% trans "BOM Cost" %} - -

    -
    + +
    +

    {% trans "BOM Cost" %} + +

    +
    -
    +
    +
    @@ -238,251 +228,55 @@
    {% endif %} -
    +
    {% endif %} - {% if part.salable and roles.sales_order.view %} -
    - -
    -

    {% trans "Sale Cost" %} - -

    -
    + +
    +

    {% trans "Sale Cost" %} + +

    +
    -
    -
    -
    - -
    +
    +
    +
    +
    +
    -
    -
    - -
    - - -
    +
    +
    +
    +
    -
    + + +
    +
    +
    -
    - -
    -

    {% trans "Sale Price" %} - -

    -
    + +
    +

    {% trans "Sale Price" %} + +

    +
    -
    - {% if sale_history|length > 0 %} -
    - -
    - {% else %} -
    - {% trans 'No sale pice history available for this part.' %} -
    - {% endif %} +
    + {% if sale_history|length > 0 %} +
    +
    -
    + {% else %} +
    + {% trans 'No sale pice history available for this part.' %} +
    + {% endif %} +
    {% endif %} - -{% endblock %} - - - -{% block js_ready %} - {{ block.super }} - - {% default_currency as currency %} - - - loadSupplierPartTable( - "#supplier-table", - "{% url 'api-supplier-part-list' %}", - { - params: { - part: {{ part.id }}, - part_detail: false, - supplier_detail: true, - manufacturer_detail: true, - }, - } - ); - - loadManufacturerPartTable( - "#manufacturer-table", - "{% url 'api-manufacturer-part-list' %}", - { - params: { - part: {{ part.id }}, - part_detail: false, - manufacturer_detail: true, - }, - } - ); - - - // history graphs - {% if price_history %} - var purchasepricedata = { - labels: [ - {% for line in price_history %}'{{ line.date }}',{% endfor %} - ], - datasets: [{ - label: '{% blocktrans %}Single Price - {{currency}}{% endblocktrans %}', - backgroundColor: 'rgba(255, 99, 132, 0.2)', - borderColor: 'rgb(255, 99, 132)', - yAxisID: 'y', - data: [ - {% for line in price_history %}{{ line.price|stringformat:".2f" }},{% endfor %} - ], - borderWidth: 1, - type: 'line' - }, - {% if 'price_diff' in price_history.0 %} - { - label: '{% blocktrans %}Single Price Difference - {{currency}}{% endblocktrans %}', - backgroundColor: 'rgba(68, 157, 68, 0.2)', - borderColor: 'rgb(68, 157, 68)', - yAxisID: 'y2', - data: [ - {% for line in price_history %}{{ line.price_diff|stringformat:".2f" }},{% endfor %} - ], - borderWidth: 1, - type: 'line', - hidden: true, - }, - { - label: '{% blocktrans %}Part Single Price - {{currency}}{% endblocktrans %}', - backgroundColor: 'rgba(70, 127, 155, 0.2)', - borderColor: 'rgb(70, 127, 155)', - yAxisID: 'y', - data: [ - {% for line in price_history %}{{ line.price_part|stringformat:".2f" }},{% endfor %} - ], - borderWidth: 1, - type: 'line', - hidden: true, - }, - {% endif %} - { - label: '{% trans "Quantity" %}', - backgroundColor: 'rgba(255, 206, 86, 0.2)', - borderColor: 'rgb(255, 206, 86)', - yAxisID: 'y1', - data: [ - {% for line in price_history %}{{ line.qty|stringformat:"f" }},{% endfor %} - ], - borderWidth: 1 - }] - } - var StockPriceChart = loadStockPricingChart($('#StockPriceChart'), purchasepricedata) - {% endif %} - - {% if bom_parts %} - var bom_colors = randomColor({hue: 'green', count: {{ bom_parts|length }} }) - var bomdata = { - labels: [{% for line in bom_parts %}'{{ line.name }}',{% endfor %}], - datasets: [ - { - label: 'Price', - data: [{% for line in bom_parts %}{{ line.min_price }},{% endfor %}], - backgroundColor: bom_colors, - }, - {% if bom_pie_max %} - { - label: 'Max Price', - data: [{% for line in bom_parts %}{{ line.max_price }},{% endfor %}], - backgroundColor: bom_colors, - }, - {% endif %} - ] - }; - var BomChart = loadBomChart(document.getElementById('BomChart'), bomdata) - {% endif %} - - - // Internal pricebreaks - {% settings_value "PART_INTERNAL_PRICE" as show_internal_price %} - {% if show_internal_price and roles.sales_order.view %} - initPriceBreakSet( - $('#internal-price-break-table'), - { - part_id: {{part.id}}, - pb_human_name: 'internal price break', - pb_url_slug: 'internal-price', - pb_url: '{% url 'api-part-internal-price-list' %}', - pb_new_btn: $('#new-internal-price-break'), - pb_new_url: '{% url 'internal-price-break-create' %}', - linkedGraph: $('#InternalPriceBreakChart'), - }, - ); - {% endif %} - - - // Load the BOM table data - loadBomTable($("#bom-table"), { - editable: {{ editing_enabled }}, - bom_url: "{% url 'api-bom-list' %}", - part_url: "{% url 'api-part-list' %}", - parent_id: {{ part.id }} , - sub_part_detail: true, - }); - - - // Sales pricebreaks - {% if part.salable and roles.sales_order.view %} - initPriceBreakSet( - $('#price-break-table'), - { - part_id: {{part.id}}, - pb_human_name: 'sale price break', - pb_url_slug: 'sale-price', - pb_url: "{% url 'api-part-sale-price-list' %}", - pb_new_btn: $('#new-price-break'), - pb_new_url: '{% url 'sale-price-break-create' %}', - linkedGraph: $('#SalePriceBreakChart'), - }, - ); - {% endif %} - - // Sale price history - {% if sale_history %} - var salepricedata = { - labels: [ - {% for line in sale_history %}'{{ line.date }}',{% endfor %} - ], - datasets: [{ - label: '{% blocktrans %}Unit Price - {{currency}}{% endblocktrans %}', - backgroundColor: 'rgba(255, 99, 132, 0.2)', - borderColor: 'rgb(255, 99, 132)', - yAxisID: 'y', - data: [ - {% for line in sale_history %}{{ line.price|stringformat:".2f" }},{% endfor %} - ], - borderWidth: 1, - }, - { - label: '{% trans "Quantity" %}', - backgroundColor: 'rgba(255, 206, 86, 0.2)', - borderColor: 'rgb(255, 206, 86)', - yAxisID: 'y1', - data: [ - {% for line in sale_history %}{{ line.qty|stringformat:"f" }},{% endfor %} - ], - borderWidth: 1, - type: 'bar', - }] - } - var SalePriceChart = loadSellPricingChart($('#SalePriceChart'), salepricedata) - {% endif %} - -{% endblock %} diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index e59ea88a05..2215e14785 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -47,8 +47,6 @@ part_detail_urls = [ url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'), url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'), - url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'), - url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'), # Normal thumbnail with form diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index cbaa7f3d72..7919b7d412 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -754,6 +754,7 @@ class PartDetail(InvenTreeRoleMixin, DetailView): context_object_name = 'part' queryset = Part.objects.all().select_related('category') template_name = 'part/detail.html' + form_class = part_forms.PartPriceForm # Add in some extra context information based on query params def get_context_data(self, **kwargs): @@ -774,25 +775,12 @@ class PartDetail(InvenTreeRoleMixin, DetailView): ctx = part.get_context_data(self.request) context.update(**ctx) - return context - - -class PartPricingView(PartDetail): - """ Detail view for Part object - """ - context_object_name = 'part' - template_name = 'part/order_prices.html' - form_class = part_forms.PartPriceForm - - # Add in some extra context information based on query params - def get_context_data(self, **kwargs): - """ Provide extra context data to template """ - context = super().get_context_data(**kwargs) - + # Pricing information ctx = self.get_pricing(self.get_quantity()) ctx['form'] = self.form_class(initial=self.get_initials()) context.update(ctx) + return context def get_quantity(self): diff --git a/InvenTree/templates/js/build.js b/InvenTree/templates/js/build.js index e284a0e8c8..f43de6ec2b 100644 --- a/InvenTree/templates/js/build.js +++ b/InvenTree/templates/js/build.js @@ -921,7 +921,7 @@ function loadBuildTable(table, options) { } else { - return '{% trans "No user information" %}'; + return `{% trans "No user information" %}`; } } }, diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index 7f034682de..169c722d79 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -714,7 +714,7 @@ function loadPartTable(table, url, options={}) { var html = ''; - html = `
    `; + html = `
    `; data.forEach(function(row, index) { diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index f173f868f7..754d3d5b59 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -1495,7 +1495,7 @@ function loadStockTrackingTable(table, options) { } else { - return '{% trans "No user information" %}'; + return `{% trans "No user information" %}`; } } }); From 09d175f7cfc52976f4ceaa192ffe0b1850bd30a2 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 23:11:59 +1000 Subject: [PATCH 32/35] Fix purchase order import form --- InvenTree/common/files.py | 7 ++++++- InvenTree/order/templates/order/order_base.html | 4 ---- .../order/templates/order/order_wizard/po_upload.html | 4 ---- InvenTree/order/templates/order/purchase_order_detail.html | 5 +++++ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/InvenTree/common/files.py b/InvenTree/common/files.py index f805ceaace..45b6c80050 100644 --- a/InvenTree/common/files.py +++ b/InvenTree/common/files.py @@ -99,13 +99,18 @@ class FileManager: self.update_headers() def guess_header(self, header, threshold=80): - """ Try to match a header (from the file) to a list of known headers + """ + Try to match a header (from the file) to a list of known headers Args: header - Header name to look for threshold - Match threshold for fuzzy search """ + # Replace null values with empty string + if header is None: + header = '' + # Try for an exact match for h in self.HEADERS: if h == header: diff --git a/InvenTree/order/templates/order/order_base.html b/InvenTree/order/templates/order/order_base.html index 85d8fd5c51..f1146d8b01 100644 --- a/InvenTree/order/templates/order/order_base.html +++ b/InvenTree/order/templates/order/order_base.html @@ -145,10 +145,6 @@ src="{% static 'img/blank_image.png' %}" {% block js_ready %} {{ block.super }} -enableNavbar({ - label: 'po', - toggleId: '#po-menu-toggle', -}); {% if order.status == PurchaseOrderStatus.PENDING and order.lines.count > 0 %} $("#place-order").click(function() { diff --git a/InvenTree/order/templates/order/order_wizard/po_upload.html b/InvenTree/order/templates/order/order_wizard/po_upload.html index a281725173..4357bce2c6 100644 --- a/InvenTree/order/templates/order/order_wizard/po_upload.html +++ b/InvenTree/order/templates/order/order_wizard/po_upload.html @@ -3,10 +3,6 @@ {% load i18n %} {% load static %} -{% block menubar %} -{% include 'order/po_navbar.html' with tab='upload' %} -{% endblock %} - {% block heading %} {% trans "Upload File for Purchase Order" %} {{ wizard.form.media }} diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index cbff1b2d1c..97a4ffb78e 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -77,6 +77,11 @@ {{ block.super }} + enableNavbar({ + label: 'po', + toggleId: '#po-menu-toggle', + }); + $('#edit-notes').click(function() { constructForm('{% url "api-po-detail" order.pk %}', { fields: { From e116ef9a8b2d8d6cef7ea28d455dd49b80adae66 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 23:14:40 +1000 Subject: [PATCH 33/35] Fix BOM upload form --- InvenTree/part/templates/part/bom_upload/upload_file.html | 8 +++----- InvenTree/part/templates/part/detail.html | 6 ++++++ InvenTree/part/templates/part/part_base.html | 5 ----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/InvenTree/part/templates/part/bom_upload/upload_file.html b/InvenTree/part/templates/part/bom_upload/upload_file.html index 88592c5ffc..e31cfbaf56 100644 --- a/InvenTree/part/templates/part/bom_upload/upload_file.html +++ b/InvenTree/part/templates/part/bom_upload/upload_file.html @@ -3,15 +3,13 @@ {% load i18n %} {% load inventree_extras %} -{% block menubar %} -{% include "part/navbar.html" with tab='bom' %} -{% endblock %} - {% block heading %} {% trans "Upload BOM File" %} {% endblock %} -{% block details %} +{% block page_content %} + +

    {% trans "Upload Bill of Materials" %}

    {% block form_alert %}
    diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index d9ef212fae..b92ce4fbeb 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -335,6 +335,12 @@ {% block js_ready %} {{ block.super }} + enableNavbar({ + label: 'part', + toggleId: '#part-menu-toggle', + }); + + loadBuildOrderAllocationTable("#build-order-allocation-table", { params: { part: {{ part.id }}, diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index 2437662cba..9fe6c7b486 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -253,11 +253,6 @@ {% block js_ready %} {{ block.super }} - enableNavbar({ - label: 'part', - toggleId: '#part-menu-toggle', - }); - {% if part.image %} $('#part-thumb').click(function() { showModalImage('{{ part.image.url }}'); From e86e15df99b9c1baec03351a8be7445d29f294d1 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 23:18:41 +1000 Subject: [PATCH 34/35] Fix part import form --- InvenTree/part/templates/part/category_navbar.html | 2 +- .../part/templates/part/import_wizard/part_upload.html | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/InvenTree/part/templates/part/category_navbar.html b/InvenTree/part/templates/part/category_navbar.html index 8e5e085f93..aa3a491160 100644 --- a/InvenTree/part/templates/part/category_navbar.html +++ b/InvenTree/part/templates/part/category_navbar.html @@ -27,7 +27,7 @@ {% if show_import and user.is_staff and roles.part.add %}
  • - + {% trans "Import Parts" %} diff --git a/InvenTree/part/templates/part/import_wizard/part_upload.html b/InvenTree/part/templates/part/import_wizard/part_upload.html index 87809603bb..676053bbe5 100644 --- a/InvenTree/part/templates/part/import_wizard/part_upload.html +++ b/InvenTree/part/templates/part/import_wizard/part_upload.html @@ -1,13 +1,9 @@ -{% extends "part/category.html" %} +{% extends "base.html" %} {% load inventree_extras %} {% load i18n %} {% load static %} -{% block menubar %} -{% include 'part/category_navbar.html' with tab='import' %} -{% endblock %} - -{% block category_content %} +{% block content %}

    From 28b3432afe8c9a95c41c22fe06f3adf32634d401 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 15 Jul 2021 23:19:47 +1000 Subject: [PATCH 35/35] Delete outdated unit test --- InvenTree/build/tests.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/InvenTree/build/tests.py b/InvenTree/build/tests.py index 9c5134cc66..b5e5406f69 100644 --- a/InvenTree/build/tests.py +++ b/InvenTree/build/tests.py @@ -252,19 +252,6 @@ class TestBuildViews(TestCase): self.assertIn(build.title, content) - def test_build_allocate(self): - """ Test the part allocation view for a Build """ - - url = reverse('build-allocate', args=(1,)) - - # Get the page normally - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - - # Get the page in editing mode - response = self.client.get(url, {'edit': 1}) - self.assertEqual(response.status_code, 200) - def test_build_item_create(self): """ Test the BuildItem creation view (ajax form) """