Merge pull request #39084 from deepeshgarg007/pricing_rule_remove

fix: Pricing rule application/removal on qty change
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index 82bd662..ca70490 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -579,12 +579,17 @@
 			item_details[field] += pricing_rule.get(field, 0) if pricing_rule else args.get(field, 0)
 
 
+@frappe.whitelist()
 def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None, rate=None):
 	from erpnext.accounts.doctype.pricing_rule.utils import (
 		get_applied_pricing_rules,
 		get_pricing_rule_items,
 	)
 
+	if isinstance(item_details, str):
+		item_details = json.loads(item_details)
+		item_details = frappe._dict(item_details)
+
 	for d in get_applied_pricing_rules(pricing_rules):
 		if not d or not frappe.db.exists("Pricing Rule", d):
 			continue
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 18b0f0f..6406735 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1199,8 +1199,9 @@
 		let item = frappe.get_doc(cdt, cdn);
 		// item.pricing_rules = ''
 		frappe.run_serially([
-			() => this.remove_pricing_rule(item),
+			() => this.remove_pricing_rule_for_item(item),
 			() => this.conversion_factor(doc, cdt, cdn, true),
+			() => this.apply_price_list(item, true), //reapply price list before applying pricing rule
 			() => this.calculate_stock_uom_rate(doc, cdt, cdn),
 			() => this.apply_pricing_rule(item, true)
 		]);
@@ -1447,8 +1448,8 @@
 
 	ignore_pricing_rule() {
 		if(this.frm.doc.ignore_pricing_rule) {
-			var me = this;
-			var item_list = [];
+			let me = this;
+			let item_list = [];
 
 			$.each(this.frm.doc["items"] || [], function(i, d) {
 				if (d.item_code) {
@@ -1487,6 +1488,34 @@
 		}
 	}
 
+	remove_pricing_rule_for_item(item) {
+		let me = this;
+		return this.frm.call({
+			method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.remove_pricing_rule_for_item",
+			args: {
+				pricing_rules: item.pricing_rules,
+				item_details: {
+					"doctype": item.doctype,
+					"name": item.name,
+					"item_code": item.item_code,
+					"pricing_rules": item.pricing_rules,
+					"parenttype": item.parenttype,
+					"parent": item.parent,
+					"price_list_rate": item.price_list_rate
+				},
+				item_code: item.item_code,
+				rate: item.price_list_rate,
+			},
+			callback: function(r) {
+				if (!r.exc && r.message) {
+					me.remove_pricing_rule(r.message);
+					me.calculate_taxes_and_totals();
+					if(me.frm.doc.apply_discount_on) me.frm.trigger("apply_discount_on");
+				}
+			}
+		});
+	}
+
 	apply_pricing_rule(item, calculate_taxes_and_totals) {
 		var me = this;
 		var args = this._get_args(item);
@@ -1711,8 +1740,8 @@
 			this.frm.set_value("plc_conversion_rate", "");
 		}
 
-		var me = this;
-		var args = this._get_args(item);
+		let me = this;
+		let args = this._get_args(item);
 		if (!((args.items && args.items.length) || args.price_list)) {
 			return;
 		}
@@ -1754,7 +1783,7 @@
 			"discount_amount", "margin_rate_or_amount", "rate_with_margin"];
 
 		if(item.remove_free_item) {
-			var items = [];
+			let items = [];
 
 			me.frm.doc.items.forEach(d => {
 				if(d.item_code != item.remove_free_item || !d.is_free_item) {
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index e746595..ebcdd11 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -497,8 +497,8 @@
 
 
 def get_barcode_data(items_list):
-	# get itemwise batch no data
-	# exmaple: {'LED-GRE': [Batch001, Batch002]}
+	# get item-wise batch no data
+	# example: {'LED-GRE': [Batch001, Batch002]}
 	# where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
 
 	itemwise_barcode = {}