diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 4f4f1b2240..ae3f9e3c9d 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -241,10 +241,8 @@ erpnext.PointOfSale.Controller = class { events: { get_frm: () => this.frm, - cart_item_clicked: (item_code, batch_no, uom) => { - const search_field = batch_no ? 'batch_no' : 'item_code'; - const search_value = batch_no || item_code; - const item_row = this.frm.doc.items.find(i => i[search_field] === search_value && i.uom === uom); + cart_item_clicked: (item_code, batch_no, uom, rate) => { + const item_row = this.get_item_from_frm(item_code, batch_no, uom, rate); this.item_details.toggle_item_details_section(item_row); }, @@ -275,18 +273,25 @@ erpnext.PointOfSale.Controller = class { this.cart.toggle_numpad(minimize); }, - form_updated: async (cdt, cdn, fieldname, value) => { + form_updated: (cdt, cdn, fieldname, value) => { const item_row = frappe.model.get_doc(cdt, cdn); if (item_row && item_row[fieldname] != value) { - const { item_code, batch_no, uom } = this.item_details.current_item; + const { item_code, batch_no, uom, rate } = this.item_details.current_item; const event = { field: fieldname, value, - item: { item_code, batch_no, uom } + item: { item_code, batch_no, uom, rate } } return this.on_cart_update(event) } + + return Promise.resolve(); + }, + + highlight_cart_item: (item) => { + const cart_item = this.cart.get_cart_item(item); + this.cart.toggle_item_highlight(cart_item); }, item_field_focused: (fieldname) => { @@ -501,8 +506,8 @@ erpnext.PointOfSale.Controller = class { let item_row = undefined; try { let { field, value, item } = args; - const { item_code, batch_no, serial_no, uom } = item; - item_row = this.get_item_from_frm(item_code, batch_no, uom); + const { item_code, batch_no, serial_no, uom, rate } = item; + item_row = this.get_item_from_frm(item_code, batch_no, uom, rate); const item_selected_from_selector = field === 'qty' && value === "+1" @@ -535,7 +540,7 @@ erpnext.PointOfSale.Controller = class { item_selected_from_selector && (value = flt(value)) - const args = { item_code, batch_no, [field]: value }; + const args = { item_code, batch_no, rate, [field]: value }; if (serial_no) { await this.check_serial_no_availablilty(item_code, this.frm.doc.set_warehouse, serial_no); @@ -550,9 +555,11 @@ erpnext.PointOfSale.Controller = class { await this.check_stock_availability(item_row, value, this.frm.doc.set_warehouse); await this.trigger_new_item_events(item_row); - - this.check_serial_batch_selection_needed(item_row) && this.edit_item_details_of(item_row); + this.update_cart_html(item_row); + + this.item_details.$component.is(':visible') && this.edit_item_details_of(item_row); + this.check_serial_batch_selection_needed(item_row) && this.edit_item_details_of(item_row); } } catch (error) { @@ -563,12 +570,13 @@ erpnext.PointOfSale.Controller = class { } } - get_item_from_frm(item_code, batch_no, uom) { + get_item_from_frm(item_code, batch_no, uom, rate) { const has_batch_no = batch_no; return this.frm.doc.items.find( i => i.item_code === item_code && (!has_batch_no || (has_batch_no && i.batch_no === batch_no)) && (i.uom === uom) + && (i.rate == rate) ); } diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js index 8a989731cc..f5019f5083 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_cart.js +++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js @@ -184,7 +184,8 @@ erpnext.PointOfSale.ItemCart = class { const item_code = unescape($cart_item.attr('data-item-code')); const batch_no = unescape($cart_item.attr('data-batch-no')); const uom = unescape($cart_item.attr('data-uom')); - me.events.cart_item_clicked(item_code, batch_no, uom); + const rate = unescape($cart_item.attr('data-rate')); + me.events.cart_item_clicked(item_code, batch_no, uom, rate); this.numpad_value = ''; }); @@ -520,28 +521,34 @@ erpnext.PointOfSale.ItemCart = class { } } - get_cart_item({ item_code, batch_no, uom }) { + get_cart_item({ item_code, batch_no, uom, rate }) { const batch_attr = `[data-batch-no="${escape(batch_no)}"]`; const item_code_attr = `[data-item-code="${escape(item_code)}"]`; const uom_attr = `[data-uom="${escape(uom)}"]`; + const rate_attr = `[data-rate="${escape(rate)}"]`; const item_selector = batch_no ? - `.cart-item-wrapper${batch_attr}${uom_attr}` : `.cart-item-wrapper${item_code_attr}${uom_attr}`; + `.cart-item-wrapper${batch_attr}${uom_attr}${rate_attr}` : `.cart-item-wrapper${item_code_attr}${uom_attr}${rate_attr}`; return this.$cart_items_wrapper.find(item_selector); } + get_item_from_frm(item) { + const doc = this.events.get_frm().doc; + const { item_code, batch_no, uom, rate } = item; + const search_field = batch_no ? 'batch_no' : 'item_code'; + const search_value = batch_no || item_code; + + return doc.items.find(i => i[search_field] === search_value && i.uom === uom && i.rate === rate); + } + update_item_html(item, remove_item) { const $item = this.get_cart_item(item); if (remove_item) { $item && $item.next().remove() && $item.remove(); } else { - const { item_code, batch_no, uom } = item; - const search_field = batch_no ? 'batch_no' : 'item_code'; - const search_value = batch_no || item_code; - const item_row = this.events.get_frm().doc.items.find(i => i[search_field] === search_value && i.uom === uom); - + const item_row = this.get_item_from_frm(item); this.render_cart_item(item_row, $item); } @@ -559,7 +566,7 @@ erpnext.PointOfSale.ItemCart = class { this.$cart_items_wrapper.append( `
+ data-batch-no="${escape(item_data.batch_no || '')}" data-rate="${escape(item_data.rate)}">
` ) diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js index 32a4556766..df62696c4b 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_details.js +++ b/erpnext/selling/page/point_of_sale/pos_item_details.js @@ -54,13 +54,24 @@ erpnext.PointOfSale.ItemDetails = class { this.$dicount_section = this.$component.find('.discount-section'); } - toggle_item_details_section(item) { - const { item_code, batch_no, uom } = this.current_item; + has_item_has_changed(item) { + const { item_code, batch_no, uom, rate } = this.current_item; const item_code_is_same = item && item_code === item.item_code; const batch_is_same = item && batch_no == item.batch_no; const uom_is_same = item && uom === item.uom; + const rate_is_same = item && rate === item.rate; + + if (!item) + return false; - this.item_has_changed = !item ? false : item_code_is_same && batch_is_same && uom_is_same ? false : true; + if (item_code_is_same && batch_is_same && uom_is_same && rate_is_same) + return false; + + return true; + } + + toggle_item_details_section(item) { + this.item_has_changed = this.has_item_has_changed(item); this.events.toggle_item_selector(this.item_has_changed); this.toggle_component(this.item_has_changed); @@ -72,11 +83,12 @@ erpnext.PointOfSale.ItemDetails = class { this.item_row = item; this.currency = this.events.get_frm().doc.currency; - this.current_item = { item_code: item.item_code, batch_no: item.batch_no, uom: item.uom }; + this.current_item = { item_code: item.item_code, batch_no: item.batch_no, uom: item.uom, rate: item.rate }; this.render_dom(item); this.render_discount_dom(item); this.render_form(item); + this.events.highlight_cart_item(item); } else { this.validate_serial_batch_item(); this.current_item = {}; @@ -198,12 +210,14 @@ erpnext.PointOfSale.ItemDetails = class { if (this.allow_rate_change) { this.rate_control.df.onchange = function() { if (this.value || flt(this.value) === 0) { + me.events.set_value_in_current_cart_item('rate', this.value); me.events.form_updated(me.doctype, me.name, 'rate', this.value).then(() => { const item_row = frappe.get_doc(me.doctype, me.name); const doc = me.events.get_frm().doc; me.$item_price.html(format_currency(item_row.rate, doc.currency)); me.render_discount_dom(item_row); }); + me.current_item.rate = this.value; } }; } else { @@ -292,11 +306,7 @@ erpnext.PointOfSale.ItemDetails = class { frappe.model.on("POS Invoice Item", "*", (fieldname, value, item_row) => { const field_control = this[`${fieldname}_control`]; - const { item_code, batch_no, uom } = this.current_item; - const item_code_is_same = item_code === item_row.item_code; - const batch_is_same = batch_no == item_row.batch_no; - const uom_is_same = uom === item_row.uom; - const item_is_same = item_code_is_same && batch_is_same && uom_is_same ? true : false; + const item_is_same = !this.has_item_has_changed(item_row); if (item_is_same && field_control && field_control.get_value() !== value) { field_control.set_value(value); 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 b6109acc57..5b48725d9c 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_selector.js +++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js @@ -78,7 +78,7 @@ erpnext.PointOfSale.ItemSelector = class { get_item_html(item) { const me = this; // eslint-disable-next-line no-unused-vars - const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom } = item; + const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom, price_list_rate } = item; const indicator_color = actual_qty > 10 ? "green" : actual_qty <= 0 ? "red" : "orange"; let qty_to_display = actual_qty; @@ -112,6 +112,7 @@ erpnext.PointOfSale.ItemSelector = class { `
${get_item_image_html()} @@ -120,7 +121,7 @@ erpnext.PointOfSale.ItemSelector = class {
${frappe.ellipsis(item.item_name, 18)}
-
${format_currency(item.price_list_rate, item.currency, 0) || 0}
+
${format_currency(price_list_rate, item.currency, 0) || 0}
` ); @@ -222,13 +223,15 @@ erpnext.PointOfSale.ItemSelector = class { let batch_no = unescape($item.attr('data-batch-no')); let serial_no = unescape($item.attr('data-serial-no')); let uom = unescape($item.attr('data-uom')); + let rate = unescape($item.attr('data-rate')); // escape(undefined) returns "undefined" then unescape returns "undefined" batch_no = batch_no === "undefined" ? undefined : batch_no; serial_no = serial_no === "undefined" ? undefined : serial_no; uom = uom === "undefined" ? undefined : uom; + rate = rate === "undefined" ? undefined : rate; - me.events.item_selected({ field: 'qty', value: "+1", item: { item_code, batch_no, serial_no, uom }}); + me.events.item_selected({ field: 'qty', value: "+1", item: { item_code, batch_no, serial_no, uom, rate }}); me.set_search_value(''); });