Merge pull request #40388 from GursheenK/promotional-scheme-recurse-for

feat: add recursion qty field in promotional scheme
diff --git a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py
index 0bb8d3a..a9c1900 100644
--- a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py
+++ b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py
@@ -60,6 +60,8 @@
 	"free_item_rate",
 	"same_item",
 	"is_recursive",
+	"recurse_for",
+	"apply_recursion_over",
 	"apply_multiple_pricing_rules",
 ]
 
diff --git a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
index 9e576fb..9b40c98 100644
--- a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
+++ b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
@@ -107,6 +107,28 @@
 		price_rules = frappe.get_all("Pricing Rule", filters={"promotional_scheme": ps.name})
 		self.assertEqual(price_rules, [])
 
+	def test_pricing_rule_for_product_discount_slabs(self):
+		ps = make_promotional_scheme()
+		ps.set("price_discount_slabs", [])
+		ps.set(
+			"product_discount_slabs",
+			[
+				{
+					"rule_description": "12+1",
+					"min_qty": 12,
+					"free_item": "_Test Item 2",
+					"free_qty": 1,
+					"is_recursive": 1,
+					"recurse_for": 12,
+				}
+			],
+		)
+		ps.save()
+		pr = frappe.get_doc("Pricing Rule", {"promotional_scheme_id": ps.product_discount_slabs[0].name})
+		self.assertSequenceEqual(
+			[pr.min_qty, pr.free_item, pr.free_qty, pr.recurse_for], [12, "_Test Item 2", 1, 12]
+		)
+
 
 def make_promotional_scheme(**args):
 	args = frappe._dict(args)
diff --git a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.json b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.json
index 3eab515..4e61d04 100644
--- a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.json
+++ b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.json
@@ -27,7 +27,9 @@
   "threshold_percentage",
   "column_break_15",
   "priority",
-  "is_recursive"
+  "is_recursive",
+  "recurse_for",
+  "apply_recursion_over"
  ],
  "fields": [
   {
@@ -161,17 +163,36 @@
    "fieldname": "is_recursive",
    "fieldtype": "Check",
    "label": "Is Recursive"
+  },
+  {
+   "default": "0",
+   "depends_on": "is_recursive",
+   "description": "Give free item for every N quantity",
+   "fieldname": "recurse_for",
+   "fieldtype": "Float",
+   "label": "Recurse Every (As Per Transaction UOM)",
+   "mandatory_depends_on": "is_recursive"
+  },
+  {
+   "default": "0",
+   "depends_on": "is_recursive",
+   "description": "Qty for which recursion isn't applicable.",
+   "fieldname": "apply_recursion_over",
+   "fieldtype": "Float",
+   "label": "Apply Recursion Over (As Per Transaction UOM)",
+   "mandatory_depends_on": "is_recursive"
   }
  ],
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-03-06 21:58:18.162346",
+ "modified": "2024-03-12 12:53:58.199108",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Promotional Scheme Product Discount",
  "owner": "Administrator",
  "permissions": [],
  "sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py
index 7dd5fea..1463a7b 100644
--- a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py
+++ b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py
@@ -15,6 +15,7 @@
 		from frappe.types import DF
 
 		apply_multiple_pricing_rules: DF.Check
+		apply_recursion_over: DF.Float
 		disable: DF.Check
 		free_item: DF.Link | None
 		free_item_rate: DF.Currency
@@ -51,6 +52,7 @@
 			"19",
 			"20",
 		]
+		recurse_for: DF.Float
 		rule_description: DF.SmallText
 		same_item: DF.Check
 		threshold_percentage: DF.Percent
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 3a4615d..0e6bd5f 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1826,8 +1826,8 @@
 			let items = [];
 
 			me.frm.doc.items.forEach(d => {
-				// if same item was added a free item through a different pricing rule, keep it
-				if(d.item_code != item.remove_free_item || !d.is_free_item || removed_pricing_rule?.includes(d.pricing_rules)) {
+				// if same item was added as free item through a different pricing rule, keep it
+				if(d.item_code != item.remove_free_item || !d.is_free_item || !removed_pricing_rule?.includes(d.pricing_rules)) {
 					items.push(d);
 				}
 			});