Merge pull request #592 from SchrodingersGat/order-filters

Various bug fixes
This commit is contained in:
Oliver 2019-12-09 22:24:09 +11:00 committed by GitHub
commit 89e60d28b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 361 additions and 194 deletions

View File

@ -98,4 +98,96 @@ function removePurchaseOrderLineItem(e) {
launchModalForm(url, { launchModalForm(url, {
reload: true, 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 = "<span class='label";
switch (code) {
case 10: // pending
html += " label-info";
break;
case 20: // placed
html += " label-primary";
break;
case 30: // complete
html += " label-success";
break;
case 40: // cancelled
case 50: // lost
html += " label-warning";
break;
case 60: // returned
html += " label-danger";
break;
default:
break;
}
html += "'>";
html += label;
html += "</span>";
console.log(html);
return html;
} }

View File

@ -12,6 +12,15 @@ class StatusCode:
""" Return the status code label associated with the provided value """ """ Return the status code label associated with the provided value """
return cls.options.get(value, 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): class OrderStatus(StatusCode):

View File

@ -31,6 +31,7 @@ class CompanyList(generics.ListCreateAPIView):
serializer_class = CompanySerializer serializer_class = CompanySerializer
queryset = Company.objects.all() queryset = Company.objects.all()
permission_classes = [ permission_classes = [
permissions.IsAuthenticated, permissions.IsAuthenticated,
] ]

View File

@ -17,7 +17,6 @@ from django.db.models import Sum
from django.apps import apps from django.apps import apps
from django.urls import reverse from django.urls import reverse
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static
from InvenTree.fields import InvenTreeURLField from InvenTree.fields import InvenTreeURLField
from InvenTree.status_codes import OrderStatus from InvenTree.status_codes import OrderStatus
@ -110,7 +109,7 @@ class Company(models.Model):
if self.image: if self.image:
return os.path.join(settings.MEDIA_URL, str(self.image.url)) return os.path.join(settings.MEDIA_URL, str(self.image.url))
else: else:
return static('/img/blank_image.png') return os.path.join(settings.STATIC_URL, 'img/blank_image.png')
@property @property
def part_count(self): def part_count(self):

View File

@ -13,17 +13,19 @@
</div> </div>
</div> </div>
{% include "order/po_table.html" with orders=company.outstanding_purchase_orders.all toolbar='#button-bar' %} <table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
</table>
{% 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 %} {% endblock %}
{% block js_ready %} {% block js_ready %}
{{ block.super }} {{ block.super }}
loadPurchaseOrderTable($("#purchase-order-table"), {
url: "{% url 'api-po-list' %}?supplier={{ company.id }}",
});
function newOrder() { function newOrder() {
launchModalForm("{% url 'purchase-order-create' %}", launchModalForm("{% url 'purchase-order-create' %}",
{ {

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -62,47 +62,47 @@ msgstr ""
msgid "Polish" msgid "Polish"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82 #: InvenTree/status_codes.py:36 InvenTree/status_codes.py:91
msgid "Pending" msgid "Pending"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:28 #: InvenTree/status_codes.py:37
msgid "Placed" msgid "Placed"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85 #: InvenTree/status_codes.py:38 InvenTree/status_codes.py:94
msgid "Complete" msgid "Complete"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84 #: InvenTree/status_codes.py:39 InvenTree/status_codes.py:93
msgid "Cancelled" msgid "Cancelled"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62 #: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71
msgid "Lost" msgid "Lost"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:32 #: InvenTree/status_codes.py:41
msgid "Returned" msgid "Returned"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:58 #: InvenTree/status_codes.py:67
msgid "OK" msgid "OK"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:59 #: InvenTree/status_codes.py:68
msgid "Attention needed" msgid "Attention needed"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:60 #: InvenTree/status_codes.py:69
msgid "Damaged" msgid "Damaged"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:61 #: InvenTree/status_codes.py:70
msgid "Destroyed" msgid "Destroyed"
msgstr "" 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 #: build/templates/build/allocate_view.html:21
#: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21 #: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21
msgid "Allocated" msgid "Allocated"
@ -481,175 +481,175 @@ msgstr ""
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "" msgstr ""
#: part/models.py:56 #: part/models.py:55
msgid "Default location for parts in this category" msgid "Default location for parts in this category"
msgstr "" msgstr ""
#: part/models.py:59 #: part/models.py:58
msgid "Default keywords for parts in this category" msgid "Default keywords for parts in this category"
msgstr "" msgstr ""
#: part/models.py:308 #: part/models.py:307
msgid "Part must be unique for name, IPN and revision" msgid "Part must be unique for name, IPN and revision"
msgstr "" msgstr ""
#: part/models.py:322 #: part/models.py:321
msgid "Part cannot be a template part if it is a variant of another part" msgid "Part cannot be a template part if it is a variant of another part"
msgstr "" msgstr ""
#: part/models.py:323 #: part/models.py:322
msgid "Part cannot be a variant of another part if it is already a template" msgid "Part cannot be a variant of another part if it is already a template"
msgstr "" msgstr ""
#: part/models.py:327 part/templates/part/detail.html:17 #: part/models.py:326 part/templates/part/detail.html:17
msgid "Part name" msgid "Part name"
msgstr "" msgstr ""
#: part/models.py:331 #: part/models.py:330
msgid "Is this part a template part?" msgid "Is this part a template part?"
msgstr "" msgstr ""
#: part/models.py:340 #: part/models.py:339
msgid "Is this part a variant of another part?" msgid "Is this part a variant of another part?"
msgstr "" msgstr ""
#: part/models.py:342 #: part/models.py:341
msgid "Part description" msgid "Part description"
msgstr "" msgstr ""
#: part/models.py:344 #: part/models.py:343
msgid "Part keywords to improve visibility in search results" msgid "Part keywords to improve visibility in search results"
msgstr "" msgstr ""
#: part/models.py:349 #: part/models.py:348
msgid "Part category" msgid "Part category"
msgstr "" msgstr ""
#: part/models.py:351 #: part/models.py:350
msgid "Internal Part Number" msgid "Internal Part Number"
msgstr "" msgstr ""
#: part/models.py:353 #: part/models.py:352
msgid "Part revision or version number" msgid "Part revision or version number"
msgstr "" msgstr ""
#: part/models.py:355 #: part/models.py:354
msgid "Link to extenal URL" msgid "Link to extenal URL"
msgstr "" msgstr ""
#: part/models.py:361 #: part/models.py:360
msgid "Where is this item normally stored?" msgid "Where is this item normally stored?"
msgstr "" msgstr ""
#: part/models.py:405 #: part/models.py:404
msgid "Default supplier part" msgid "Default supplier part"
msgstr "" msgstr ""
#: part/models.py:408 #: part/models.py:407
msgid "Minimum allowed stock level" msgid "Minimum allowed stock level"
msgstr "" msgstr ""
#: part/models.py:410 #: part/models.py:409
msgid "Stock keeping units for this part" msgid "Stock keeping units for this part"
msgstr "" msgstr ""
#: part/models.py:412 #: part/models.py:411
msgid "Can this part be built from other parts?" msgid "Can this part be built from other parts?"
msgstr "" msgstr ""
#: part/models.py:414 #: part/models.py:413
msgid "Can this part be used to build other parts?" msgid "Can this part be used to build other parts?"
msgstr "" msgstr ""
#: part/models.py:416 #: part/models.py:415
msgid "Does this part have tracking for unique items?" msgid "Does this part have tracking for unique items?"
msgstr "" msgstr ""
#: part/models.py:418 #: part/models.py:417
msgid "Can this part be purchased from external suppliers?" msgid "Can this part be purchased from external suppliers?"
msgstr "" msgstr ""
#: part/models.py:420 #: part/models.py:419
msgid "Can this part be sold to customers?" msgid "Can this part be sold to customers?"
msgstr "" msgstr ""
#: part/models.py:422 #: part/models.py:421
msgid "Is this part active?" msgid "Is this part active?"
msgstr "" msgstr ""
#: part/models.py:424 #: part/models.py:423
msgid "Is this a virtual part, such as a software product or license?" msgid "Is this a virtual part, such as a software product or license?"
msgstr "" msgstr ""
#: part/models.py:428 #: part/models.py:427
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "" msgstr ""
#: part/models.py:935 #: part/models.py:934
msgid "Select file to attach" msgid "Select file to attach"
msgstr "" msgstr ""
#: part/models.py:937 #: part/models.py:936
msgid "File comment" msgid "File comment"
msgstr "" msgstr ""
#: part/models.py:992 #: part/models.py:991
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "" msgstr ""
#: part/models.py:997 #: part/models.py:996
msgid "Parameter Name" msgid "Parameter Name"
msgstr "" msgstr ""
#: part/models.py:999 #: part/models.py:998
msgid "Parameter Units" msgid "Parameter Units"
msgstr "" msgstr ""
#: part/models.py:1025 #: part/models.py:1024
msgid "Parent Part" msgid "Parent Part"
msgstr "" msgstr ""
#: part/models.py:1027 #: part/models.py:1026
msgid "Parameter Template" msgid "Parameter Template"
msgstr "" msgstr ""
#: part/models.py:1029 #: part/models.py:1028
msgid "Parameter Value" msgid "Parameter Value"
msgstr "" msgstr ""
#: part/models.py:1053 #: part/models.py:1052
msgid "Select parent part" msgid "Select parent part"
msgstr "" msgstr ""
#: part/models.py:1061 #: part/models.py:1060
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "" msgstr ""
#: part/models.py:1067 #: part/models.py:1066
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "" msgstr ""
#: part/models.py:1070 #: part/models.py:1069
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "" msgstr ""
#: part/models.py:1073 #: part/models.py:1072
msgid "BOM item reference" msgid "BOM item reference"
msgstr "" msgstr ""
#: part/models.py:1076 #: part/models.py:1075
msgid "BOM item notes" msgid "BOM item notes"
msgstr "" msgstr ""
#: part/models.py:1078 #: part/models.py:1077
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "" msgstr ""
#: part/models.py:1141 #: part/models.py:1140
msgid "Part cannot be added to its own Bill of Materials" msgid "Part cannot be added to its own Bill of Materials"
msgstr "" msgstr ""
#: part/models.py:1148 #: part/models.py:1147
#, python-brace-format #, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -62,47 +62,47 @@ msgstr ""
msgid "Polish" msgid "Polish"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82 #: InvenTree/status_codes.py:36 InvenTree/status_codes.py:91
msgid "Pending" msgid "Pending"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:28 #: InvenTree/status_codes.py:37
msgid "Placed" msgid "Placed"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85 #: InvenTree/status_codes.py:38 InvenTree/status_codes.py:94
msgid "Complete" msgid "Complete"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84 #: InvenTree/status_codes.py:39 InvenTree/status_codes.py:93
msgid "Cancelled" msgid "Cancelled"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62 #: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71
msgid "Lost" msgid "Lost"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:32 #: InvenTree/status_codes.py:41
msgid "Returned" msgid "Returned"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:58 #: InvenTree/status_codes.py:67
msgid "OK" msgid "OK"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:59 #: InvenTree/status_codes.py:68
msgid "Attention needed" msgid "Attention needed"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:60 #: InvenTree/status_codes.py:69
msgid "Damaged" msgid "Damaged"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:61 #: InvenTree/status_codes.py:70
msgid "Destroyed" msgid "Destroyed"
msgstr "" 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 #: build/templates/build/allocate_view.html:21
#: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21 #: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21
msgid "Allocated" msgid "Allocated"
@ -481,175 +481,175 @@ msgstr ""
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "" msgstr ""
#: part/models.py:56 #: part/models.py:55
msgid "Default location for parts in this category" msgid "Default location for parts in this category"
msgstr "" msgstr ""
#: part/models.py:59 #: part/models.py:58
msgid "Default keywords for parts in this category" msgid "Default keywords for parts in this category"
msgstr "" msgstr ""
#: part/models.py:308 #: part/models.py:307
msgid "Part must be unique for name, IPN and revision" msgid "Part must be unique for name, IPN and revision"
msgstr "" msgstr ""
#: part/models.py:322 #: part/models.py:321
msgid "Part cannot be a template part if it is a variant of another part" msgid "Part cannot be a template part if it is a variant of another part"
msgstr "" msgstr ""
#: part/models.py:323 #: part/models.py:322
msgid "Part cannot be a variant of another part if it is already a template" msgid "Part cannot be a variant of another part if it is already a template"
msgstr "" msgstr ""
#: part/models.py:327 part/templates/part/detail.html:17 #: part/models.py:326 part/templates/part/detail.html:17
msgid "Part name" msgid "Part name"
msgstr "" msgstr ""
#: part/models.py:331 #: part/models.py:330
msgid "Is this part a template part?" msgid "Is this part a template part?"
msgstr "" msgstr ""
#: part/models.py:340 #: part/models.py:339
msgid "Is this part a variant of another part?" msgid "Is this part a variant of another part?"
msgstr "" msgstr ""
#: part/models.py:342 #: part/models.py:341
msgid "Part description" msgid "Part description"
msgstr "" msgstr ""
#: part/models.py:344 #: part/models.py:343
msgid "Part keywords to improve visibility in search results" msgid "Part keywords to improve visibility in search results"
msgstr "" msgstr ""
#: part/models.py:349 #: part/models.py:348
msgid "Part category" msgid "Part category"
msgstr "" msgstr ""
#: part/models.py:351 #: part/models.py:350
msgid "Internal Part Number" msgid "Internal Part Number"
msgstr "" msgstr ""
#: part/models.py:353 #: part/models.py:352
msgid "Part revision or version number" msgid "Part revision or version number"
msgstr "" msgstr ""
#: part/models.py:355 #: part/models.py:354
msgid "Link to extenal URL" msgid "Link to extenal URL"
msgstr "" msgstr ""
#: part/models.py:361 #: part/models.py:360
msgid "Where is this item normally stored?" msgid "Where is this item normally stored?"
msgstr "" msgstr ""
#: part/models.py:405 #: part/models.py:404
msgid "Default supplier part" msgid "Default supplier part"
msgstr "" msgstr ""
#: part/models.py:408 #: part/models.py:407
msgid "Minimum allowed stock level" msgid "Minimum allowed stock level"
msgstr "" msgstr ""
#: part/models.py:410 #: part/models.py:409
msgid "Stock keeping units for this part" msgid "Stock keeping units for this part"
msgstr "" msgstr ""
#: part/models.py:412 #: part/models.py:411
msgid "Can this part be built from other parts?" msgid "Can this part be built from other parts?"
msgstr "" msgstr ""
#: part/models.py:414 #: part/models.py:413
msgid "Can this part be used to build other parts?" msgid "Can this part be used to build other parts?"
msgstr "" msgstr ""
#: part/models.py:416 #: part/models.py:415
msgid "Does this part have tracking for unique items?" msgid "Does this part have tracking for unique items?"
msgstr "" msgstr ""
#: part/models.py:418 #: part/models.py:417
msgid "Can this part be purchased from external suppliers?" msgid "Can this part be purchased from external suppliers?"
msgstr "" msgstr ""
#: part/models.py:420 #: part/models.py:419
msgid "Can this part be sold to customers?" msgid "Can this part be sold to customers?"
msgstr "" msgstr ""
#: part/models.py:422 #: part/models.py:421
msgid "Is this part active?" msgid "Is this part active?"
msgstr "" msgstr ""
#: part/models.py:424 #: part/models.py:423
msgid "Is this a virtual part, such as a software product or license?" msgid "Is this a virtual part, such as a software product or license?"
msgstr "" msgstr ""
#: part/models.py:428 #: part/models.py:427
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "" msgstr ""
#: part/models.py:935 #: part/models.py:934
msgid "Select file to attach" msgid "Select file to attach"
msgstr "" msgstr ""
#: part/models.py:937 #: part/models.py:936
msgid "File comment" msgid "File comment"
msgstr "" msgstr ""
#: part/models.py:992 #: part/models.py:991
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "" msgstr ""
#: part/models.py:997 #: part/models.py:996
msgid "Parameter Name" msgid "Parameter Name"
msgstr "" msgstr ""
#: part/models.py:999 #: part/models.py:998
msgid "Parameter Units" msgid "Parameter Units"
msgstr "" msgstr ""
#: part/models.py:1025 #: part/models.py:1024
msgid "Parent Part" msgid "Parent Part"
msgstr "" msgstr ""
#: part/models.py:1027 #: part/models.py:1026
msgid "Parameter Template" msgid "Parameter Template"
msgstr "" msgstr ""
#: part/models.py:1029 #: part/models.py:1028
msgid "Parameter Value" msgid "Parameter Value"
msgstr "" msgstr ""
#: part/models.py:1053 #: part/models.py:1052
msgid "Select parent part" msgid "Select parent part"
msgstr "" msgstr ""
#: part/models.py:1061 #: part/models.py:1060
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "" msgstr ""
#: part/models.py:1067 #: part/models.py:1066
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "" msgstr ""
#: part/models.py:1070 #: part/models.py:1069
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "" msgstr ""
#: part/models.py:1073 #: part/models.py:1072
msgid "BOM item reference" msgid "BOM item reference"
msgstr "" msgstr ""
#: part/models.py:1076 #: part/models.py:1075
msgid "BOM item notes" msgid "BOM item notes"
msgstr "" msgstr ""
#: part/models.py:1078 #: part/models.py:1077
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "" msgstr ""
#: part/models.py:1141 #: part/models.py:1140
msgid "Part cannot be added to its own Bill of Materials" msgid "Part cannot be added to its own Bill of Materials"
msgstr "" msgstr ""
#: part/models.py:1148 #: part/models.py:1147
#, python-brace-format #, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -62,47 +62,47 @@ msgstr ""
msgid "Polish" msgid "Polish"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82 #: InvenTree/status_codes.py:36 InvenTree/status_codes.py:91
msgid "Pending" msgid "Pending"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:28 #: InvenTree/status_codes.py:37
msgid "Placed" msgid "Placed"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85 #: InvenTree/status_codes.py:38 InvenTree/status_codes.py:94
msgid "Complete" msgid "Complete"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84 #: InvenTree/status_codes.py:39 InvenTree/status_codes.py:93
msgid "Cancelled" msgid "Cancelled"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62 #: InvenTree/status_codes.py:40 InvenTree/status_codes.py:71
msgid "Lost" msgid "Lost"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:32 #: InvenTree/status_codes.py:41
msgid "Returned" msgid "Returned"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:58 #: InvenTree/status_codes.py:67
msgid "OK" msgid "OK"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:59 #: InvenTree/status_codes.py:68
msgid "Attention needed" msgid "Attention needed"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:60 #: InvenTree/status_codes.py:69
msgid "Damaged" msgid "Damaged"
msgstr "" msgstr ""
#: InvenTree/status_codes.py:61 #: InvenTree/status_codes.py:70
msgid "Destroyed" msgid "Destroyed"
msgstr "" 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 #: build/templates/build/allocate_view.html:21
#: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21 #: part/templates/part/part_base.html:116 part/templates/part/tabs.html:21
msgid "Allocated" msgid "Allocated"
@ -481,175 +481,175 @@ msgstr ""
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "" msgstr ""
#: part/models.py:56 #: part/models.py:55
msgid "Default location for parts in this category" msgid "Default location for parts in this category"
msgstr "" msgstr ""
#: part/models.py:59 #: part/models.py:58
msgid "Default keywords for parts in this category" msgid "Default keywords for parts in this category"
msgstr "" msgstr ""
#: part/models.py:308 #: part/models.py:307
msgid "Part must be unique for name, IPN and revision" msgid "Part must be unique for name, IPN and revision"
msgstr "" msgstr ""
#: part/models.py:322 #: part/models.py:321
msgid "Part cannot be a template part if it is a variant of another part" msgid "Part cannot be a template part if it is a variant of another part"
msgstr "" msgstr ""
#: part/models.py:323 #: part/models.py:322
msgid "Part cannot be a variant of another part if it is already a template" msgid "Part cannot be a variant of another part if it is already a template"
msgstr "" msgstr ""
#: part/models.py:327 part/templates/part/detail.html:17 #: part/models.py:326 part/templates/part/detail.html:17
msgid "Part name" msgid "Part name"
msgstr "" msgstr ""
#: part/models.py:331 #: part/models.py:330
msgid "Is this part a template part?" msgid "Is this part a template part?"
msgstr "" msgstr ""
#: part/models.py:340 #: part/models.py:339
msgid "Is this part a variant of another part?" msgid "Is this part a variant of another part?"
msgstr "" msgstr ""
#: part/models.py:342 #: part/models.py:341
msgid "Part description" msgid "Part description"
msgstr "" msgstr ""
#: part/models.py:344 #: part/models.py:343
msgid "Part keywords to improve visibility in search results" msgid "Part keywords to improve visibility in search results"
msgstr "" msgstr ""
#: part/models.py:349 #: part/models.py:348
msgid "Part category" msgid "Part category"
msgstr "" msgstr ""
#: part/models.py:351 #: part/models.py:350
msgid "Internal Part Number" msgid "Internal Part Number"
msgstr "" msgstr ""
#: part/models.py:353 #: part/models.py:352
msgid "Part revision or version number" msgid "Part revision or version number"
msgstr "" msgstr ""
#: part/models.py:355 #: part/models.py:354
msgid "Link to extenal URL" msgid "Link to extenal URL"
msgstr "" msgstr ""
#: part/models.py:361 #: part/models.py:360
msgid "Where is this item normally stored?" msgid "Where is this item normally stored?"
msgstr "" msgstr ""
#: part/models.py:405 #: part/models.py:404
msgid "Default supplier part" msgid "Default supplier part"
msgstr "" msgstr ""
#: part/models.py:408 #: part/models.py:407
msgid "Minimum allowed stock level" msgid "Minimum allowed stock level"
msgstr "" msgstr ""
#: part/models.py:410 #: part/models.py:409
msgid "Stock keeping units for this part" msgid "Stock keeping units for this part"
msgstr "" msgstr ""
#: part/models.py:412 #: part/models.py:411
msgid "Can this part be built from other parts?" msgid "Can this part be built from other parts?"
msgstr "" msgstr ""
#: part/models.py:414 #: part/models.py:413
msgid "Can this part be used to build other parts?" msgid "Can this part be used to build other parts?"
msgstr "" msgstr ""
#: part/models.py:416 #: part/models.py:415
msgid "Does this part have tracking for unique items?" msgid "Does this part have tracking for unique items?"
msgstr "" msgstr ""
#: part/models.py:418 #: part/models.py:417
msgid "Can this part be purchased from external suppliers?" msgid "Can this part be purchased from external suppliers?"
msgstr "" msgstr ""
#: part/models.py:420 #: part/models.py:419
msgid "Can this part be sold to customers?" msgid "Can this part be sold to customers?"
msgstr "" msgstr ""
#: part/models.py:422 #: part/models.py:421
msgid "Is this part active?" msgid "Is this part active?"
msgstr "" msgstr ""
#: part/models.py:424 #: part/models.py:423
msgid "Is this a virtual part, such as a software product or license?" msgid "Is this a virtual part, such as a software product or license?"
msgstr "" msgstr ""
#: part/models.py:428 #: part/models.py:427
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "" msgstr ""
#: part/models.py:935 #: part/models.py:934
msgid "Select file to attach" msgid "Select file to attach"
msgstr "" msgstr ""
#: part/models.py:937 #: part/models.py:936
msgid "File comment" msgid "File comment"
msgstr "" msgstr ""
#: part/models.py:992 #: part/models.py:991
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "" msgstr ""
#: part/models.py:997 #: part/models.py:996
msgid "Parameter Name" msgid "Parameter Name"
msgstr "" msgstr ""
#: part/models.py:999 #: part/models.py:998
msgid "Parameter Units" msgid "Parameter Units"
msgstr "" msgstr ""
#: part/models.py:1025 #: part/models.py:1024
msgid "Parent Part" msgid "Parent Part"
msgstr "" msgstr ""
#: part/models.py:1027 #: part/models.py:1026
msgid "Parameter Template" msgid "Parameter Template"
msgstr "" msgstr ""
#: part/models.py:1029 #: part/models.py:1028
msgid "Parameter Value" msgid "Parameter Value"
msgstr "" msgstr ""
#: part/models.py:1053 #: part/models.py:1052
msgid "Select parent part" msgid "Select parent part"
msgstr "" msgstr ""
#: part/models.py:1061 #: part/models.py:1060
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "" msgstr ""
#: part/models.py:1067 #: part/models.py:1066
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "" msgstr ""
#: part/models.py:1070 #: part/models.py:1069
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "" msgstr ""
#: part/models.py:1073 #: part/models.py:1072
msgid "BOM item reference" msgid "BOM item reference"
msgstr "" msgstr ""
#: part/models.py:1076 #: part/models.py:1075
msgid "BOM item notes" msgid "BOM item notes"
msgstr "" msgstr ""
#: part/models.py:1078 #: part/models.py:1077
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "" msgstr ""
#: part/models.py:1141 #: part/models.py:1140
msgid "Part cannot be added to its own Bill of Materials" msgid "Part cannot be added to its own Bill of Materials"
msgstr "" msgstr ""
#: part/models.py:1148 #: part/models.py:1147
#, python-brace-format #, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr "" msgstr ""

View File

@ -7,9 +7,18 @@ from __future__ import unicode_literals
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import generics, permissions 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 django.conf.urls import url
from InvenTree.status_codes import OrderStatus
import os
from part.models import Part
from .models import PurchaseOrder, PurchaseOrderLineItem from .models import PurchaseOrder, PurchaseOrderLineItem
from .serializers import POSerializer, POLineItemSerializer from .serializers import POSerializer, POLineItemSerializer
@ -24,18 +33,79 @@ class POList(generics.ListCreateAPIView):
queryset = PurchaseOrder.objects.all() queryset = PurchaseOrder.objects.all()
serializer_class = POSerializer 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 = [ permission_classes = [
permissions.IsAuthenticated, permissions.IsAuthenticated,
] ]
filter_backends = [ filter_backends = [
DjangoFilterBackend, DjangoFilterBackend,
filters.SearchFilter,
filters.OrderingFilter,
] ]
filter_fields = [ filter_fields = [
'supplier', 'supplier',
] ]
ordering_fields = [
'creation_date',
'reference',
]
ordering = '-creation_date'
class PODetail(generics.RetrieveUpdateAPIView): class PODetail(generics.RetrieveUpdateAPIView):
""" API endpoint for detail view of a PurchaseOrder object """ """ API endpoint for detail view of a PurchaseOrder object """

View File

@ -1,11 +0,0 @@
{% extends "collapse.html" %}
{% load static %}
{% block collapse_title %}
<h4>{{ title }}</h4>
{% endblock %}
{% block collapse_content %}
{% include "order/po_table.html" %}
{% endblock %}

View File

@ -1,6 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block page_title %} {% block page_title %}
InvenTree | Purchase Orders InvenTree | Purchase Orders
@ -17,7 +18,8 @@ InvenTree | Purchase Orders
</div> </div>
</div> </div>
{% include "order/po_table.html" with toolbar='#table-buttons' %} <table class='table table-striped table-condensed po-table' id='purchase-order-table'>
</table>
{% endblock %} {% endblock %}
@ -35,4 +37,8 @@ $("#po-create").click(function() {
$("#po-table").inventreeTable({ $("#po-table").inventreeTable({
}); });
loadPurchaseOrderTable($("#purchase-order-table"), {
url: "{% url 'api-po-list' %}",
});
{% endblock %} {% endblock %}

View File

@ -18,7 +18,6 @@ from django.db.models import Sum
from django.db.models import prefetch_related_objects from django.db.models import prefetch_related_objects
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from django.conf.urls.static import static
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db.models.signals import pre_delete from django.db.models.signals import pre_delete
from django.dispatch import receiver from django.dispatch import receiver
@ -281,7 +280,7 @@ class Part(models.Model):
if self.image: if self.image:
return os.path.join(settings.MEDIA_URL, str(self.image.url)) return os.path.join(settings.MEDIA_URL, str(self.image.url))
else: else:
return static('/img/blank_image.png') return os.path.join(settings.STATIC_URL, 'img/blank_image.png')
def validate_unique(self, exclude=None): def validate_unique(self, exclude=None):
""" Validate that a part is 'unique'. """ Validate that a part is 'unique'.

View File

@ -14,19 +14,17 @@
</div> </div>
</div> </div>
{% include "order/po_table.html" with orders=part.open_purchase_orders toolbar='#button-bar' %} <table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
</table>
{% if part.closed_purchase_orders|length > 0 %}
<h4>Closed Orders</h4>
{% include "order/po_table.html" with orders=part.closed_purchase_orders %}
{% endif %}
{% endblock %} {% endblock %}
{% block js_ready %} {% block js_ready %}
{{ block.super }} {{ block.super }}
$("#po-table").inventreeTable({ loadPurchaseOrderTable($("#purchase-order-table"), {
url: "{% url 'api-po-list' %}?part={{ part.id }}",
}); });
$("#part-order2").click(function() { $("#part-order2").click(function() {

View File

@ -31,12 +31,14 @@ To configure Inventree inside a virtual environment, ``cd`` into the inventree b
``apt-get install python3-venv`` ``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. This will place the current shell session inside a virtual environment - the terminal should display the ``(inventree)`` prefix.
.. note:: .. 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 Installation