From 069f28feeb3df3c3278ed813968f2831b706b27f Mon Sep 17 00:00:00 2001 From: diptanilsaha Date: Tue, 6 Jan 2026 00:29:07 +0530 Subject: [PATCH] fix(pos): item selector section ui/ux --- erpnext/public/scss/point-of-sale.scss | 7 +++ .../page/point_of_sale/point_of_sale.py | 12 ++-- .../page/point_of_sale/pos_item_selector.js | 59 +++++++++++++------ 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/erpnext/public/scss/point-of-sale.scss b/erpnext/public/scss/point-of-sale.scss index d86d2038adf..6eb6b56c570 100644 --- a/erpnext/public/scss/point-of-sale.scss +++ b/erpnext/public/scss/point-of-sale.scss @@ -117,6 +117,13 @@ overflow-y: scroll; overflow-x: hidden; + &.items-not-found { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + } + &.show-item-image { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--margin-lg); diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 50ab2404078..35d22e40fb7 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -122,11 +122,13 @@ def filter_result_items(result, pos_profile): @frappe.whitelist() -def get_parent_item_group(): - # Using get_all to ignore user permission - item_group = frappe.get_all("Item Group", {"lft": 1, "is_group": 1}, pluck="name") - if item_group: - return item_group[0] +def get_parent_item_group(pos_profile): + item_groups = get_item_groups(pos_profile) + + if not item_groups: + item_groups = frappe.get_all("Item Group", {"lft": 1, "is_group": 1}, pluck="name") + + return item_groups[0] if item_groups else None @frappe.whitelist() diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js index 835fd65f846..c40dfcfde5e 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_selector.js +++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js @@ -7,12 +7,14 @@ erpnext.PointOfSale.ItemSelector = class { this.events = events; this.pos_profile = pos_profile; this.hide_images = settings.hide_images; + this.item_display_class = this.hide_images ? "hide-item-image" : "show-item-image"; this.auto_add_item = settings.auto_add_item_to_cart; + this.get_parent_item_group(); this.inti_component(); } - inti_component() { + async inti_component() { this.prepare_dom(); this.make_search_bar(); this.load_items_data(); @@ -35,20 +37,20 @@ erpnext.PointOfSale.ItemSelector = class { this.$component = this.wrapper.find(".items-selector"); this.$items_container = this.$component.find(".items-container"); - const show_hide_images = this.hide_images ? "hide-item-image" : "show-item-image"; - this.$items_container.addClass(show_hide_images); + this.$items_container.addClass(this.item_display_class); + } + + async get_parent_item_group() { + const r = await frappe.call({ + method: "erpnext.selling.page.point_of_sale.point_of_sale.get_parent_item_group", + args: { + pos_profile: this.pos_profile, + }, + }); + if (r.message) this.item_group = this.parent_item_group = r.message; } async load_items_data() { - if (!this.item_group) { - frappe.call({ - method: "erpnext.selling.page.point_of_sale.point_of_sale.get_parent_item_group", - async: false, - callback: (r) => { - if (r.message) this.parent_item_group = r.message; - }, - }); - } if (!this.price_list) { const res = await frappe.db.get_value("POS Profile", this.pos_profile, "selling_price_list"); this.price_list = res.message.selling_price_list; @@ -64,8 +66,6 @@ erpnext.PointOfSale.ItemSelector = class { const price_list = (doc && doc.selling_price_list) || this.price_list; let { item_group, pos_profile } = this; - !item_group && (item_group = this.parent_item_group); - return frappe.call({ method: "erpnext.selling.page.point_of_sale.point_of_sale.get_items", freeze: true, @@ -76,16 +76,32 @@ erpnext.PointOfSale.ItemSelector = class { render_item_list(items) { this.$items_container.html(""); + if (!items?.length) { + this.set_items_not_found_banner(); + return; + } + + if (this.$items_container.hasClass("items-not-found")) { + this.$items_container.removeClass("items-not-found"); + this.$items_container.addClass(this.item_display_class); + } + if (this.hide_images) { this.$items_container.append(this.render_item_list_column_header()); } - items.forEach((item) => { + items?.forEach((item) => { const item_html = this.get_item_html(item); this.$items_container.append(item_html); }); } + set_items_not_found_banner() { + this.$items_container.removeClass(this.item_display_class); + this.$items_container.addClass("items-not-found"); + this.$items_container.html(__("Items not found.")); + } + render_item_list_column_header() { return `
Name
@@ -189,17 +205,18 @@ erpnext.PointOfSale.ItemSelector = class { fieldtype: "Link", options: "Item Group", placeholder: __("Select item group"), + only_select: true, onchange: function () { me.item_group = this.value; !me.item_group && (me.item_group = me.parent_item_group); me.filter_items(); + me.set_item_selector_filter_label(this.value); }, get_query: function () { - const doc = me.events.get_frm().doc; return { query: "erpnext.selling.page.point_of_sale.point_of_sale.item_group_query", filters: { - pos_profile: doc ? doc.pos_profile : "", + pos_profile: me.pos_profile, }, }; }, @@ -210,9 +227,17 @@ erpnext.PointOfSale.ItemSelector = class { this.search_field.toggle_label(false); this.item_group_field.toggle_label(false); + $(this.item_group_field.awesomplete.ul).css("min-width", "unset"); + this.attach_clear_btn(); } + set_item_selector_filter_label(value) { + const $filter_label = this.$component.find(".label"); + + $filter_label.html(value ? __(value) : __("All Items")); + } + attach_clear_btn() { this.search_field.$wrapper.find(".control-input").append( `