diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index fa6be1fdd6f..6d96cb92d59 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -856,57 +856,107 @@ $.extend(erpnext.item, { } frm.toggle_display("prices_html", true); - const requested_item = frm.doc.name; - const container = frm.fields_dict["prices_html"].$wrapper; + frappe.require("embedded_list.bundle.js", () => erpnext.item.build_prices_list(frm)); + }, - container.html( - `
${__("Loading...")}
` - ); + build_prices_list: function (frm) { + const item_code = frm.doc.name; + const container = frm.fields_dict["prices_html"].$wrapper.empty(); - frappe.call({ - method: "erpnext.stock.doctype.item.item.get_item_prices", - args: { item_code: requested_item }, - - callback: function (r) { - if (requested_item !== frm.doc.name) return; - - if (!r.message) return; - - const { prices, has_more } = r.message; - - const html = frappe.render_template("item_prices", { - prices, - has_more, - item_code: requested_item, - stock_uom: frm.doc.stock_uom, - }); - - container.html(html); - - container.find(".add-price-btn").on("click", () => { - const filters = {}; - if (frm.doc.is_sales_item && !frm.doc.is_purchase_item) { - filters.selling = 1; - } else if (frm.doc.is_purchase_item && !frm.doc.is_sales_item) { - filters.buying = 1; - } - frappe.new_doc( - "Item Price", - { item_code: requested_item, uom: frm.doc.stock_uom }, - (dialog) => { - if (Object.keys(filters).length) { - dialog.fields_dict.price_list.get_query = () => ({ filters }); - } - } - ); - }); - - container.find(".price-row").on("click", function (e) { - if ($(e.target).is("a")) return; - - frappe.set_route("Form", "Item Price", $(this).data("name")); + const list = new frappe.ui.EmbeddedList({ + wrapper: $("
").appendTo(container), + description: __("All active prices for this item across buying and selling price lists."), + show_index: true, + show_search: false, + empty_icon: "tag", + empty_message: __("No active item prices found."), + add_button: { + label: __("Add Price"), + action: () => erpnext.item.new_item_price(frm), + }, + on_row_click: (row) => frappe.set_route("Form", "Item Price", row.name), + get_data() { + return frappe + .xcall("erpnext.stock.doctype.item.item.get_item_prices", { item_code }) + .then((r) => { + this._has_more = r.has_more; + return r.prices; + }); + }, + before_render() { + this._all_data.forEach((row) => { + row.price_type = + row.buying && row.selling + ? __("Buy & Sell") + : row.buying + ? __("Buying") + : __("Selling"); }); }, + columns: [ + { label: __("Price List"), fieldname: "price_list" }, + { + label: __("Type"), + type: "badge", + fieldname: "price_type", + }, + { + label: __("Party"), + type: "link", + text: (row) => row.customer || row.supplier || "", + route: (row) => [ + "Form", + row.customer ? "Customer" : "Supplier", + row.customer || row.supplier, + ], + }, + { + label: __("Rate"), + fieldname: "price_list_rate", + render: (row) => format_currency(row.price_list_rate, row.currency), + }, + { + label: __("UOM"), + fieldname: "uom", + render: (row) => frappe.utils.escape_html(row.uom || frm.doc.stock_uom || ""), + }, + { + label: __("Valid Upto"), + fieldname: "valid_upto", + render: (row) => (row.valid_upto ? frappe.datetime.str_to_user(row.valid_upto) : ""), + }, + ], + }); + + list.refresh().then(() => { + if (!list._has_more) return; + frappe.ui + .button({ + label: __("View All Prices"), + variant: "subtle", + size: "sm", + onclick: () => { + frappe.route_options = { item_code }; + frappe.set_route("List", "Item Price"); + }, + }) + .appendTo( + $('
').appendTo(container) + ); + }); + }, + + new_item_price: function (frm) { + const filters = {}; + if (frm.doc.is_sales_item && !frm.doc.is_purchase_item) { + filters.selling = 1; + } else if (frm.doc.is_purchase_item && !frm.doc.is_sales_item) { + filters.buying = 1; + } + frappe.new_doc("Item Price", { item_code: frm.doc.name, uom: frm.doc.stock_uom }, (dialog) => { + if (Object.keys(filters).length) { + dialog.fields_dict.price_list.get_query = () => ({ filters }); + } }); }, diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 0d3b549e5f4..836244d9ada 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -1594,6 +1594,9 @@ def get_child_warehouses(warehouse): return get_child_warehouses(warehouse) +ITEM_PRICES_LIMIT = 10 + + @frappe.whitelist() def get_item_prices(item_code: str): """Fetch valid item prices for the item prices tab.""" @@ -1621,14 +1624,13 @@ def get_item_prices(item_code: str): .where(ItemPrice.docstatus != 2) .where((ItemPrice.valid_upto.isnull()) | (ItemPrice.valid_upto >= today)) .orderby(ItemPrice.price_list) - .limit(11) + .limit(ITEM_PRICES_LIMIT + 1) .run(as_dict=True) ) - has_more = len(prices) == 11 return { - "prices": prices[:10], - "has_more": has_more, + "prices": prices[:ITEM_PRICES_LIMIT], + "has_more": len(prices) > ITEM_PRICES_LIMIT, } diff --git a/erpnext/stock/doctype/item/item_prices.html b/erpnext/stock/doctype/item/item_prices.html deleted file mode 100644 index 277afaa4dea..00000000000 --- a/erpnext/stock/doctype/item/item_prices.html +++ /dev/null @@ -1,139 +0,0 @@ - - -
-
{{ __("All active prices for this item across buying and selling price lists.") }}
-
-{% if (prices && prices.length) { %} - -
- - - - - - - - - - - - - - {% for (var i=0; i < prices.length; i++) { var p = prices[i]; %} - - - - - - - - - - {% } %} - -
{{ __("No.") }}{{ __("Price List") }}{{ __("Type") }}{{ __("Party") }}{{ __("Rate") }}{{ __("UOM") }}{{ __("Valid Upto") }}
{{ i + 1 }}{{ p.price_list }} - {% if (p.buying && p.selling) { %} - {{ __("Buy & Sell") }} - {% } else if (p.buying) { %} - {{ __("Buying") }} - {% } else if (p.selling) { %} - {{ __("Selling") }} - {% } %} - - {% if (p.customer) { %} - {{ p.customer }} - {% } else if (p.supplier) { %} - {{ p.supplier }} - {% } %} - {{ format_currency(p.price_list_rate, p.currency) }}{{ p.uom || stock_uom }}{{ p.valid_upto ? frappe.datetime.str_to_user(p.valid_upto) : "" }}
-
- - - -{% } else { %} - -
-

{{ __("No active item prices found.") }}

- -
- -{% } %} \ No newline at end of file