diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html
index ce78e445e1..de1d46596a 100644
--- a/InvenTree/part/templates/part/detail.html
+++ b/InvenTree/part/templates/part/detail.html
@@ -73,7 +73,7 @@
@@ -703,12 +703,10 @@
});
onPanelLoad("purchase-orders", function() {
- loadPurchaseOrderTable($("#purchase-order-table"), {
- url: "{% url 'api-po-list' %}",
- params: {
- part: {{ part.id }},
- },
- });
+ loadPartPurchaseOrderTable(
+ "#purchase-order-table",
+ {{ part.pk }},
+ );
});
onPanelLoad("sales-orders", function() {
diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js
index a471182399..b75ad8e42d 100644
--- a/InvenTree/templates/js/translated/order.js
+++ b/InvenTree/templates/js/translated/order.js
@@ -648,6 +648,13 @@ function loadPurchaseOrderTable(table, options) {
var html = renderLink(value, `/order/purchase-order/${row.pk}/`);
+ html += purchaseOrderStatusDisplay(
+ row.status,
+ {
+ classes: 'float-right',
+ }
+ );
+
if (row.overdue) {
html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}');
}
@@ -672,14 +679,6 @@ function loadPurchaseOrderTable(table, options) {
field: 'description',
title: '{% trans "Description" %}',
},
- {
- field: 'status',
- title: '{% trans "Status" %}',
- sortable: true,
- formatter: function(value, row) {
- return purchaseOrderStatusDisplay(row.status, row.status_text);
- }
- },
{
field: 'creation_date',
title: '{% trans "Date" %}',
diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js
index 0a27f2ba2f..011cde0def 100644
--- a/InvenTree/templates/js/translated/part.js
+++ b/InvenTree/templates/js/translated/part.js
@@ -29,6 +29,7 @@
loadParametricPartTable,
loadPartCategoryTable,
loadPartParameterTable,
+ loadPartPurchaseOrderTable,
loadPartTable,
loadPartTestTemplateTable,
loadPartVariantTable,
@@ -712,6 +713,135 @@ function loadPartParameterTable(table, url, options) {
}
+/*
+ * Construct a table showing a list of purchase orders for a given part.
+ *
+ * This requests API data from the PurchaseOrderLineItem endpoint
+ */
+function loadPartPurchaseOrderTable(table, part_id, options={}) {
+
+ options.params = options.params || {};
+
+ // Construct API filterset
+ options.params.base_part = part_id;
+ options.params.part_detail = true;
+ options.params.order_detail = true;
+
+ var filters = loadTableFilters('partpurchaseorders');
+
+ for (var key in options.params) {
+ filters[key] = options.params[key];
+ }
+
+ setupFilterList('partpurchaseorders', $(table));
+
+ $(table).inventreeTable({
+ url: '{% url "api-po-line-list" %}',
+ queryParams: filters,
+ name: 'partpurchaseorders',
+ original: options.params,
+ showColumns: true,
+ formatNoMatches: function() {
+ return '{% trans "No purchase orders found" %}';
+ },
+ columns: [
+ {
+ field: 'order',
+ title: '{% trans "Purchase Order" %}',
+ switchable: false,
+ formatter: function(value, row) {
+ var order = row.order_detail;
+
+ if (!order) {
+ return '-';
+ }
+
+ var ref = global_settings.PURCHASEORDER_REFERENCE_PREFIX + order.reference;
+
+ var html = renderLink(ref, `/order/po/${order.pk}/`);
+
+ html += purchaseOrderStatusDisplay(
+ order.status,
+ {
+ classes: 'float-right',
+ }
+ );
+
+ return html;
+ },
+ },
+ {
+ field: 'supplier',
+ title: '{% trans "Supplier" %}',
+ switchable: true,
+ formatter: function(value, row) {
+
+ if (row.supplier_part_detail && row.supplier_part_detail.supplier_detail) {
+ var supp = row.supplier_part_detail.supplier_detail;
+ var html = imageHoverIcon(supp.thumbnail || supp.image);
+
+ html += ' ' + renderLink(supp.name, `/company/${supp.pk}/`);
+
+ return html;
+ } else {
+ return '-';
+ }
+ }
+ },
+ {
+ field: 'sku',
+ title: '{% trans "SKU" %}',
+ switchable: true,
+ formatter: function(value, row) {
+ if (row.supplier_part_detail) {
+ var supp = row.supplier_part_detail;
+
+ return renderLink(supp.SKU, `/supplier-part/${supp.pk}/`);
+ } else {
+ return '-';
+ }
+ },
+ },
+ {
+ field: 'mpn',
+ title: '{% trans "MPN" %}',
+ switchable: true,
+ formatter: function(value, row) {
+ if (row.supplier_part_detail && row.supplier_part_detail.manufacturer_part_detail) {
+ var manu = row.supplier_part_detail.manufacturer_part_detail;
+ return renderLink(manu.MPN, `/manufacturer-part/${manu.pk}/`);
+ }
+ }
+ },
+ {
+ field: 'quantity',
+ title: '{% trans "Quantity" %}',
+ },
+ {
+ field: 'received',
+ title: '{% trans "Received" %}',
+ switchable: true,
+ },
+ {
+ field: 'purchase_price',
+ title: '{% trans "Price" %}',
+ formatter: function(value, row) {
+ var formatter = new Intl.NumberFormat(
+ 'en-US',
+ {
+ style: 'currency',
+ currency: row.purchase_price_currency,
+ }
+ );
+
+ return formatter.format(row.purchase_price);
+ }
+ }
+ ]
+ });
+}
+
+
function loadRelatedPartsTable(table, part_id, options={}) {
/*
* Load table of "related" parts