diff --git a/InvenTree/InvenTree/static/script/inventree/bom.js b/InvenTree/InvenTree/static/script/inventree/bom.js index e62c8c22f4..8d0accb83b 100644 --- a/InvenTree/InvenTree/static/script/inventree/bom.js +++ b/InvenTree/InvenTree/static/script/inventree/bom.js @@ -282,7 +282,6 @@ function loadBomTable(table, options) { }, formatNoMatches: function() { return "No BOM items found"; }, clickToSelect: true, - showFooter: true, queryParams: function(p) { return params; }, diff --git a/InvenTree/InvenTree/static/script/inventree/order.js b/InvenTree/InvenTree/static/script/inventree/order.js index 818596f7c9..d811cc5ea1 100644 --- a/InvenTree/InvenTree/static/script/inventree/order.js +++ b/InvenTree/InvenTree/static/script/inventree/order.js @@ -98,4 +98,96 @@ function removePurchaseOrderLineItem(e) { launchModalForm(url, { reload: true, }); +} + + +function loadPurchaseOrderTable(table, options) { + /* Create a purchase-order table */ + + table.inventreeTable({ + url: options.url, + formatNoMatches: function() { return "No purchase orders found"; }, + columns: [ + { + field: 'pk', + title: 'ID', + visible: false, + }, + { + sortable: true, + field: 'supplier', + title: 'Supplier', + formatter: function(value, row, index, field) { + return imageHoverIcon(row.supplier__image) + renderLink(row.supplier__name, '/company/' + value + '/purchase-orders/'); + } + }, + { + sortable: true, + field: 'reference', + title: 'Reference', + formatter: function(value, row, index, field) { + return renderLink(value, "/order/purchase-order/" + row.pk + "/"); + } + }, + { + sortable: true, + field: 'creation_date', + title: 'Date', + }, + { + sortable: true, + field: 'description', + title: 'Description', + }, + { + sortable: true, + field: 'status', + title: 'Status', + formatter: function(value, row, index, field) { + return orderStatusLabel(row.status, row.status_text); + } + }, + { + sortable: true, + field: 'lines', + title: 'Items' + }, + ], + }); +} + + +function orderStatusLabel(code, label) { + /* Render a purchase-order status label. */ + + var html = ""; + html += label; + html += ""; + + console.log(html); + + return html; } \ No newline at end of file diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index f772943ef0..e49f9a9824 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -12,6 +12,15 @@ class StatusCode: """ Return the status code label associated with the provided value """ return cls.options.get(value, value) + @classmethod + def value(cls, label): + """ Return the value associated with the provided label """ + for k in cls.options.keys(): + if cls.options[k].lower() == label.lower(): + return k + + raise ValueError("Label not found") + class OrderStatus(StatusCode): diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py index e1b02a76fa..8b777dd947 100644 --- a/InvenTree/company/api.py +++ b/InvenTree/company/api.py @@ -31,6 +31,7 @@ class CompanyList(generics.ListCreateAPIView): serializer_class = CompanySerializer queryset = Company.objects.all() + permission_classes = [ permissions.IsAuthenticated, ] diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index 2df314fb27..c072abab1c 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -17,7 +17,6 @@ from django.db.models import Sum from django.apps import apps from django.urls import reverse from django.conf import settings -from django.conf.urls.static import static from InvenTree.fields import InvenTreeURLField from InvenTree.status_codes import OrderStatus @@ -110,7 +109,7 @@ class Company(models.Model): if self.image: return os.path.join(settings.MEDIA_URL, str(self.image.url)) else: - return static('/img/blank_image.png') + return os.path.join(settings.STATIC_URL, 'img/blank_image.png') @property def part_count(self): diff --git a/InvenTree/company/templates/company/detail_purchase_orders.html b/InvenTree/company/templates/company/detail_purchase_orders.html index 8c299cbd4e..b2eabc129d 100644 --- a/InvenTree/company/templates/company/detail_purchase_orders.html +++ b/InvenTree/company/templates/company/detail_purchase_orders.html @@ -13,17 +13,19 @@ -{% include "order/po_table.html" with orders=company.outstanding_purchase_orders.all toolbar='#button-bar' %} - -{% if company.closed_purchase_orders.count > 0 %} -{% include "order/po_table_collapse.html" with title="Closed Orders" orders=company.closed_purchase_orders.all %} -{% endif %} + +
{% endblock %} {% block js_ready %} {{ block.super }} + loadPurchaseOrderTable($("#purchase-order-table"), { + url: "{% url 'api-po-list' %}?supplier={{ company.id }}", + }); + + function newOrder() { launchModalForm("{% url 'purchase-order-create' %}", { diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index 0128f4edb9..7ed7357117 100644 --- a/InvenTree/locale/de/LC_MESSAGES/django.po +++ b/InvenTree/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-12-04 23:28+0000\n" +"POT-Creation-Date: 2019-12-09 11:16+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -62,47 +62,47 @@ msgstr "" msgid "Polish" msgstr "" -#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82 +#: InvenTree/status_codes.py:36 InvenTree/status_codes.py:91 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:28 +#: InvenTree/status_codes.py:37 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85 +#: InvenTree/status_codes.py:38 InvenTree/status_codes.py:94 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84 +#: InvenTree/status_codes.py:39 InvenTree/status_codes.py:93 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62 +#: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:32 +#: InvenTree/status_codes.py:41 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:58 +#: InvenTree/status_codes.py:67 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:59 +#: InvenTree/status_codes.py:68 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:60 +#: InvenTree/status_codes.py:69 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:61 +#: InvenTree/status_codes.py:70 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:83 build/templates/build/allocate_edit.html:28 +#: InvenTree/status_codes.py:92 build/templates/build/allocate_edit.html:28 #: build/templates/build/allocate_view.html:21 #: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21 msgid "Allocated" @@ -481,175 +481,175 @@ msgstr "" msgid "Select currency for price calculation" msgstr "" -#: part/models.py:56 +#: part/models.py:55 msgid "Default location for parts in this category" msgstr "" -#: part/models.py:59 +#: part/models.py:58 msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:308 +#: part/models.py:307 msgid "Part must be unique for name, IPN and revision" msgstr "" -#: part/models.py:322 +#: part/models.py:321 msgid "Part cannot be a template part if it is a variant of another part" msgstr "" -#: part/models.py:323 +#: part/models.py:322 msgid "Part cannot be a variant of another part if it is already a template" msgstr "" -#: part/models.py:327 part/templates/part/detail.html:17 +#: part/models.py:326 part/templates/part/detail.html:17 msgid "Part name" msgstr "" -#: part/models.py:331 +#: part/models.py:330 msgid "Is this part a template part?" msgstr "" -#: part/models.py:340 +#: part/models.py:339 msgid "Is this part a variant of another part?" msgstr "" -#: part/models.py:342 +#: part/models.py:341 msgid "Part description" msgstr "" -#: part/models.py:344 +#: part/models.py:343 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:349 +#: part/models.py:348 msgid "Part category" msgstr "" -#: part/models.py:351 +#: part/models.py:350 msgid "Internal Part Number" msgstr "" -#: part/models.py:353 +#: part/models.py:352 msgid "Part revision or version number" msgstr "" -#: part/models.py:355 +#: part/models.py:354 msgid "Link to extenal URL" msgstr "" -#: part/models.py:361 +#: part/models.py:360 msgid "Where is this item normally stored?" msgstr "" -#: part/models.py:405 +#: part/models.py:404 msgid "Default supplier part" msgstr "" -#: part/models.py:408 +#: part/models.py:407 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:410 +#: part/models.py:409 msgid "Stock keeping units for this part" msgstr "" -#: part/models.py:412 +#: part/models.py:411 msgid "Can this part be built from other parts?" msgstr "" -#: part/models.py:414 +#: part/models.py:413 msgid "Can this part be used to build other parts?" msgstr "" -#: part/models.py:416 +#: part/models.py:415 msgid "Does this part have tracking for unique items?" msgstr "" -#: part/models.py:418 +#: part/models.py:417 msgid "Can this part be purchased from external suppliers?" msgstr "" -#: part/models.py:420 +#: part/models.py:419 msgid "Can this part be sold to customers?" msgstr "" -#: part/models.py:422 +#: part/models.py:421 msgid "Is this part active?" msgstr "" -#: part/models.py:424 +#: part/models.py:423 msgid "Is this a virtual part, such as a software product or license?" msgstr "" -#: part/models.py:428 +#: part/models.py:427 msgid "Stored BOM checksum" msgstr "" -#: part/models.py:935 +#: part/models.py:934 msgid "Select file to attach" msgstr "" -#: part/models.py:937 +#: part/models.py:936 msgid "File comment" msgstr "" -#: part/models.py:992 +#: part/models.py:991 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:997 +#: part/models.py:996 msgid "Parameter Name" msgstr "" -#: part/models.py:999 +#: part/models.py:998 msgid "Parameter Units" msgstr "" -#: part/models.py:1025 +#: part/models.py:1024 msgid "Parent Part" msgstr "" -#: part/models.py:1027 +#: part/models.py:1026 msgid "Parameter Template" msgstr "" -#: part/models.py:1029 +#: part/models.py:1028 msgid "Parameter Value" msgstr "" -#: part/models.py:1053 +#: part/models.py:1052 msgid "Select parent part" msgstr "" -#: part/models.py:1061 +#: part/models.py:1060 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1067 +#: part/models.py:1066 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1070 +#: part/models.py:1069 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1073 +#: part/models.py:1072 msgid "BOM item reference" msgstr "" -#: part/models.py:1076 +#: part/models.py:1075 msgid "BOM item notes" msgstr "" -#: part/models.py:1078 +#: part/models.py:1077 msgid "BOM line checksum" msgstr "" -#: part/models.py:1141 +#: part/models.py:1140 msgid "Part cannot be added to its own Bill of Materials" msgstr "" -#: part/models.py:1148 +#: part/models.py:1147 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index 0128f4edb9..7ed7357117 100644 --- a/InvenTree/locale/en/LC_MESSAGES/django.po +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-12-04 23:28+0000\n" +"POT-Creation-Date: 2019-12-09 11:16+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -62,47 +62,47 @@ msgstr "" msgid "Polish" msgstr "" -#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82 +#: InvenTree/status_codes.py:36 InvenTree/status_codes.py:91 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:28 +#: InvenTree/status_codes.py:37 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85 +#: InvenTree/status_codes.py:38 InvenTree/status_codes.py:94 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84 +#: InvenTree/status_codes.py:39 InvenTree/status_codes.py:93 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62 +#: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:32 +#: InvenTree/status_codes.py:41 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:58 +#: InvenTree/status_codes.py:67 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:59 +#: InvenTree/status_codes.py:68 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:60 +#: InvenTree/status_codes.py:69 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:61 +#: InvenTree/status_codes.py:70 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:83 build/templates/build/allocate_edit.html:28 +#: InvenTree/status_codes.py:92 build/templates/build/allocate_edit.html:28 #: build/templates/build/allocate_view.html:21 #: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21 msgid "Allocated" @@ -481,175 +481,175 @@ msgstr "" msgid "Select currency for price calculation" msgstr "" -#: part/models.py:56 +#: part/models.py:55 msgid "Default location for parts in this category" msgstr "" -#: part/models.py:59 +#: part/models.py:58 msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:308 +#: part/models.py:307 msgid "Part must be unique for name, IPN and revision" msgstr "" -#: part/models.py:322 +#: part/models.py:321 msgid "Part cannot be a template part if it is a variant of another part" msgstr "" -#: part/models.py:323 +#: part/models.py:322 msgid "Part cannot be a variant of another part if it is already a template" msgstr "" -#: part/models.py:327 part/templates/part/detail.html:17 +#: part/models.py:326 part/templates/part/detail.html:17 msgid "Part name" msgstr "" -#: part/models.py:331 +#: part/models.py:330 msgid "Is this part a template part?" msgstr "" -#: part/models.py:340 +#: part/models.py:339 msgid "Is this part a variant of another part?" msgstr "" -#: part/models.py:342 +#: part/models.py:341 msgid "Part description" msgstr "" -#: part/models.py:344 +#: part/models.py:343 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:349 +#: part/models.py:348 msgid "Part category" msgstr "" -#: part/models.py:351 +#: part/models.py:350 msgid "Internal Part Number" msgstr "" -#: part/models.py:353 +#: part/models.py:352 msgid "Part revision or version number" msgstr "" -#: part/models.py:355 +#: part/models.py:354 msgid "Link to extenal URL" msgstr "" -#: part/models.py:361 +#: part/models.py:360 msgid "Where is this item normally stored?" msgstr "" -#: part/models.py:405 +#: part/models.py:404 msgid "Default supplier part" msgstr "" -#: part/models.py:408 +#: part/models.py:407 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:410 +#: part/models.py:409 msgid "Stock keeping units for this part" msgstr "" -#: part/models.py:412 +#: part/models.py:411 msgid "Can this part be built from other parts?" msgstr "" -#: part/models.py:414 +#: part/models.py:413 msgid "Can this part be used to build other parts?" msgstr "" -#: part/models.py:416 +#: part/models.py:415 msgid "Does this part have tracking for unique items?" msgstr "" -#: part/models.py:418 +#: part/models.py:417 msgid "Can this part be purchased from external suppliers?" msgstr "" -#: part/models.py:420 +#: part/models.py:419 msgid "Can this part be sold to customers?" msgstr "" -#: part/models.py:422 +#: part/models.py:421 msgid "Is this part active?" msgstr "" -#: part/models.py:424 +#: part/models.py:423 msgid "Is this a virtual part, such as a software product or license?" msgstr "" -#: part/models.py:428 +#: part/models.py:427 msgid "Stored BOM checksum" msgstr "" -#: part/models.py:935 +#: part/models.py:934 msgid "Select file to attach" msgstr "" -#: part/models.py:937 +#: part/models.py:936 msgid "File comment" msgstr "" -#: part/models.py:992 +#: part/models.py:991 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:997 +#: part/models.py:996 msgid "Parameter Name" msgstr "" -#: part/models.py:999 +#: part/models.py:998 msgid "Parameter Units" msgstr "" -#: part/models.py:1025 +#: part/models.py:1024 msgid "Parent Part" msgstr "" -#: part/models.py:1027 +#: part/models.py:1026 msgid "Parameter Template" msgstr "" -#: part/models.py:1029 +#: part/models.py:1028 msgid "Parameter Value" msgstr "" -#: part/models.py:1053 +#: part/models.py:1052 msgid "Select parent part" msgstr "" -#: part/models.py:1061 +#: part/models.py:1060 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1067 +#: part/models.py:1066 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1070 +#: part/models.py:1069 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1073 +#: part/models.py:1072 msgid "BOM item reference" msgstr "" -#: part/models.py:1076 +#: part/models.py:1075 msgid "BOM item notes" msgstr "" -#: part/models.py:1078 +#: part/models.py:1077 msgid "BOM line checksum" msgstr "" -#: part/models.py:1141 +#: part/models.py:1140 msgid "Part cannot be added to its own Bill of Materials" msgstr "" -#: part/models.py:1148 +#: part/models.py:1147 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index 0128f4edb9..7ed7357117 100644 --- a/InvenTree/locale/es/LC_MESSAGES/django.po +++ b/InvenTree/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-12-04 23:28+0000\n" +"POT-Creation-Date: 2019-12-09 11:16+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -62,47 +62,47 @@ msgstr "" msgid "Polish" msgstr "" -#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82 +#: InvenTree/status_codes.py:36 InvenTree/status_codes.py:91 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:28 +#: InvenTree/status_codes.py:37 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85 +#: InvenTree/status_codes.py:38 InvenTree/status_codes.py:94 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84 +#: InvenTree/status_codes.py:39 InvenTree/status_codes.py:93 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62 +#: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:32 +#: InvenTree/status_codes.py:41 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:58 +#: InvenTree/status_codes.py:67 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:59 +#: InvenTree/status_codes.py:68 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:60 +#: InvenTree/status_codes.py:69 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:61 +#: InvenTree/status_codes.py:70 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:83 build/templates/build/allocate_edit.html:28 +#: InvenTree/status_codes.py:92 build/templates/build/allocate_edit.html:28 #: build/templates/build/allocate_view.html:21 #: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21 msgid "Allocated" @@ -481,175 +481,175 @@ msgstr "" msgid "Select currency for price calculation" msgstr "" -#: part/models.py:56 +#: part/models.py:55 msgid "Default location for parts in this category" msgstr "" -#: part/models.py:59 +#: part/models.py:58 msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:308 +#: part/models.py:307 msgid "Part must be unique for name, IPN and revision" msgstr "" -#: part/models.py:322 +#: part/models.py:321 msgid "Part cannot be a template part if it is a variant of another part" msgstr "" -#: part/models.py:323 +#: part/models.py:322 msgid "Part cannot be a variant of another part if it is already a template" msgstr "" -#: part/models.py:327 part/templates/part/detail.html:17 +#: part/models.py:326 part/templates/part/detail.html:17 msgid "Part name" msgstr "" -#: part/models.py:331 +#: part/models.py:330 msgid "Is this part a template part?" msgstr "" -#: part/models.py:340 +#: part/models.py:339 msgid "Is this part a variant of another part?" msgstr "" -#: part/models.py:342 +#: part/models.py:341 msgid "Part description" msgstr "" -#: part/models.py:344 +#: part/models.py:343 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:349 +#: part/models.py:348 msgid "Part category" msgstr "" -#: part/models.py:351 +#: part/models.py:350 msgid "Internal Part Number" msgstr "" -#: part/models.py:353 +#: part/models.py:352 msgid "Part revision or version number" msgstr "" -#: part/models.py:355 +#: part/models.py:354 msgid "Link to extenal URL" msgstr "" -#: part/models.py:361 +#: part/models.py:360 msgid "Where is this item normally stored?" msgstr "" -#: part/models.py:405 +#: part/models.py:404 msgid "Default supplier part" msgstr "" -#: part/models.py:408 +#: part/models.py:407 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:410 +#: part/models.py:409 msgid "Stock keeping units for this part" msgstr "" -#: part/models.py:412 +#: part/models.py:411 msgid "Can this part be built from other parts?" msgstr "" -#: part/models.py:414 +#: part/models.py:413 msgid "Can this part be used to build other parts?" msgstr "" -#: part/models.py:416 +#: part/models.py:415 msgid "Does this part have tracking for unique items?" msgstr "" -#: part/models.py:418 +#: part/models.py:417 msgid "Can this part be purchased from external suppliers?" msgstr "" -#: part/models.py:420 +#: part/models.py:419 msgid "Can this part be sold to customers?" msgstr "" -#: part/models.py:422 +#: part/models.py:421 msgid "Is this part active?" msgstr "" -#: part/models.py:424 +#: part/models.py:423 msgid "Is this a virtual part, such as a software product or license?" msgstr "" -#: part/models.py:428 +#: part/models.py:427 msgid "Stored BOM checksum" msgstr "" -#: part/models.py:935 +#: part/models.py:934 msgid "Select file to attach" msgstr "" -#: part/models.py:937 +#: part/models.py:936 msgid "File comment" msgstr "" -#: part/models.py:992 +#: part/models.py:991 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:997 +#: part/models.py:996 msgid "Parameter Name" msgstr "" -#: part/models.py:999 +#: part/models.py:998 msgid "Parameter Units" msgstr "" -#: part/models.py:1025 +#: part/models.py:1024 msgid "Parent Part" msgstr "" -#: part/models.py:1027 +#: part/models.py:1026 msgid "Parameter Template" msgstr "" -#: part/models.py:1029 +#: part/models.py:1028 msgid "Parameter Value" msgstr "" -#: part/models.py:1053 +#: part/models.py:1052 msgid "Select parent part" msgstr "" -#: part/models.py:1061 +#: part/models.py:1060 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1067 +#: part/models.py:1066 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1070 +#: part/models.py:1069 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1073 +#: part/models.py:1072 msgid "BOM item reference" msgstr "" -#: part/models.py:1076 +#: part/models.py:1075 msgid "BOM item notes" msgstr "" -#: part/models.py:1078 +#: part/models.py:1077 msgid "BOM line checksum" msgstr "" -#: part/models.py:1141 +#: part/models.py:1140 msgid "Part cannot be added to its own Bill of Materials" msgstr "" -#: part/models.py:1148 +#: part/models.py:1147 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "" diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index e1396cb54c..69580c3bb2 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -7,9 +7,18 @@ from __future__ import unicode_literals from django_filters.rest_framework import DjangoFilterBackend from rest_framework import generics, permissions +from rest_framework import filters +from rest_framework.response import Response +from django.conf import settings from django.conf.urls import url +from InvenTree.status_codes import OrderStatus + +import os + +from part.models import Part + from .models import PurchaseOrder, PurchaseOrderLineItem from .serializers import POSerializer, POLineItemSerializer @@ -24,18 +33,79 @@ class POList(generics.ListCreateAPIView): queryset = PurchaseOrder.objects.all() serializer_class = POSerializer + def list(self, request, *args, **kwargs): + + queryset = self.get_queryset().prefetch_related('supplier', 'lines') + + queryset = self.filter_queryset(queryset) + + # Special filtering for 'status' field + if 'status' in request.GET: + status = request.GET['status'] + + # First attempt to filter by integer value + try: + status = int(status) + queryset = queryset.filter(status=status) + except ValueError: + try: + value = OrderStatus.value(status) + queryset = queryset.filter(status=value) + except ValueError: + pass + + # Attempt to filter by part + if 'part' in request.GET: + try: + part = Part.objects.get(pk=request.GET['part']) + queryset = queryset.filter(id__in=[p.id for p in part.purchase_orders()]) + except (Part.DoesNotExist, ValueError): + pass + + data = queryset.values( + 'pk', + 'supplier', + 'supplier__name', + 'supplier__image', + 'reference', + 'description', + 'URL', + 'status', + 'notes', + 'creation_date', + ) + + for item in data: + + order = queryset.get(pk=item['pk']) + + item['supplier__image'] = os.path.join(settings.MEDIA_URL, item['supplier__image']) + item['status_text'] = OrderStatus.label(item['status']) + item['lines'] = order.lines.count() + + return Response(data) + permission_classes = [ permissions.IsAuthenticated, ] filter_backends = [ DjangoFilterBackend, + filters.SearchFilter, + filters.OrderingFilter, ] filter_fields = [ 'supplier', ] + ordering_fields = [ + 'creation_date', + 'reference', + ] + + ordering = '-creation_date' + class PODetail(generics.RetrieveUpdateAPIView): """ API endpoint for detail view of a PurchaseOrder object """ diff --git a/InvenTree/order/templates/order/po_table_collapse.html b/InvenTree/order/templates/order/po_table_collapse.html deleted file mode 100644 index 886e14ce97..0000000000 --- a/InvenTree/order/templates/order/po_table_collapse.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "collapse.html" %} - -{% load static %} - -{% block collapse_title %} -

{{ title }}

-{% endblock %} - -{% block collapse_content %} -{% include "order/po_table.html" %} -{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/purchase_orders.html b/InvenTree/order/templates/order/purchase_orders.html index 6e6e45cdfd..17f3115c75 100644 --- a/InvenTree/order/templates/order/purchase_orders.html +++ b/InvenTree/order/templates/order/purchase_orders.html @@ -1,6 +1,7 @@ {% extends "base.html" %} {% load static %} +{% load i18n %} {% block page_title %} InvenTree | Purchase Orders @@ -17,7 +18,8 @@ InvenTree | Purchase Orders -{% include "order/po_table.html" with toolbar='#table-buttons' %} + +
{% endblock %} @@ -35,4 +37,8 @@ $("#po-create").click(function() { $("#po-table").inventreeTable({ }); +loadPurchaseOrderTable($("#purchase-order-table"), { + url: "{% url 'api-po-list' %}", +}); + {% endblock %} \ No newline at end of file diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index e265755778..386bf3e2c9 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -18,7 +18,6 @@ from django.db.models import Sum from django.db.models import prefetch_related_objects from django.core.validators import MinValueValidator -from django.conf.urls.static import static from django.contrib.auth.models import User from django.db.models.signals import pre_delete from django.dispatch import receiver @@ -281,7 +280,7 @@ class Part(models.Model): if self.image: return os.path.join(settings.MEDIA_URL, str(self.image.url)) else: - return static('/img/blank_image.png') + return os.path.join(settings.STATIC_URL, 'img/blank_image.png') def validate_unique(self, exclude=None): """ Validate that a part is 'unique'. @@ -1230,6 +1229,10 @@ class BomItem(models.Model): pmin, pmax = prange + # remove trailing zeros + pmin = pmin.normalize() + pmax = pmax.normalize() + if pmin == pmax: return str(pmin) diff --git a/InvenTree/part/templates/part/orders.html b/InvenTree/part/templates/part/orders.html index b3f84735f3..fbb0413e34 100644 --- a/InvenTree/part/templates/part/orders.html +++ b/InvenTree/part/templates/part/orders.html @@ -14,19 +14,17 @@ -{% include "order/po_table.html" with orders=part.open_purchase_orders toolbar='#button-bar' %} + +
-{% if part.closed_purchase_orders|length > 0 %} -

Closed Orders

-{% include "order/po_table.html" with orders=part.closed_purchase_orders %} -{% endif %} {% endblock %} {% block js_ready %} {{ block.super }} -$("#po-table").inventreeTable({ +loadPurchaseOrderTable($("#purchase-order-table"), { + url: "{% url 'api-po-list' %}?part={{ part.id }}", }); $("#part-order2").click(function() { diff --git a/docs/start.rst b/docs/start.rst index 65fbf7b1ec..2cac8c6a95 100644 --- a/docs/start.rst +++ b/docs/start.rst @@ -31,12 +31,14 @@ To configure Inventree inside a virtual environment, ``cd`` into the inventree b ``apt-get install python3-venv`` -``source inventree/bin/activate`` +``python3 -m venv inventree-env`` + +``source inventree-env/bin/activate`` This will place the current shell session inside a virtual environment - the terminal should display the ``(inventree)`` prefix. .. note:: - Remember to run ``source inventree/bin/activate`` when starting each shell session, before running Inventree commands. This will ensure that the correct environment is being used. + Remember to run ``source inventree-env/bin/activate`` when starting each shell session, before running Inventree commands. This will ensure that the correct environment is being used. Installation