fix: Pricing Rule not created against the Promotional Scheme
diff --git a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py
index e3fac07..5fbe93e 100644
--- a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py
+++ b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py
@@ -20,6 +20,9 @@
 product_discount_fields = ['free_item', 'free_qty', 'free_item_uom',
 	'free_item_rate', 'same_item', 'is_recursive', 'apply_multiple_pricing_rules']
 
+class TransactionExists(frappe.ValidationError):
+	pass
+
 class PromotionalScheme(Document):
 	def validate(self):
 		if not self.selling and not self.buying:
@@ -28,6 +31,40 @@
 			or self.product_discount_slabs):
 			frappe.throw(_("Price or product discount slabs are required"))
 
+		self.validate_applicable_for()
+		self.validate_pricing_rules()
+
+	def validate_applicable_for(self):
+		if self.applicable_for:
+			applicable_for = frappe.scrub(self.applicable_for)
+
+			if not self.get(applicable_for):
+				msg = (f'The field {frappe.bold(self.applicable_for)} is required')
+				frappe.throw(_(msg))
+
+	def validate_pricing_rules(self):
+		if self.is_new():
+			return
+
+		transaction_exists = False
+		docnames = []
+
+		# If user has changed applicable for
+		if self._doc_before_save.applicable_for == self.applicable_for:
+			return
+
+		docnames = frappe.get_all('Pricing Rule',
+			filters= {'promotional_scheme': self.name})
+
+		for docname in docnames:
+			if frappe.db.exists('Pricing Rule Detail',
+				{'pricing_rule': docname.name, 'docstatus': ('<', 2)}):
+				raise_for_transaction_exists(self.name)
+
+		if docnames and not transaction_exists:
+			for docname in docnames:
+				frappe.delete_doc('Pricing Rule', docname.name)
+
 	def on_update(self):
 		pricing_rules = frappe.get_all(
 			'Pricing Rule',
@@ -67,6 +104,13 @@
 			{'promotional_scheme': self.name}):
 			frappe.delete_doc('Pricing Rule', rule.name)
 
+def raise_for_transaction_exists(name):
+	msg = (f"""You can't change the {frappe.bold(_('Applicable For'))}
+		because transactions are present against the Promotional Scheme {frappe.bold(name)}. """)
+	msg += 'Kindly disable this Promotional Scheme and create new for new Applicable For.'
+
+	frappe.throw(_(msg), TransactionExists)
+
 def get_pricing_rules(doc, rules=None):
 	if rules is None:
 		rules = {}
@@ -84,45 +128,59 @@
 	new_doc = []
 	args = get_args_for_pricing_rule(doc)
 	applicable_for = frappe.scrub(doc.get('applicable_for'))
+
 	for idx, d in enumerate(doc.get(child_doc)):
 		if d.name in rules:
-			for applicable_for_value in args.get(applicable_for):
-				temp_args = args.copy()
-				docname = frappe.get_all(
-					'Pricing Rule',
-					fields = ["promotional_scheme_id", "name", applicable_for],
-					filters = {
-						'promotional_scheme_id': d.name,
-						applicable_for: applicable_for_value
-					}
-				)
-
-				if docname:
-					pr = frappe.get_doc('Pricing Rule', docname[0].get('name'))
-					temp_args[applicable_for] = applicable_for_value
-					pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
-				else:
-					pr = frappe.new_doc("Pricing Rule")
-					pr.title = doc.name
-					temp_args[applicable_for] = applicable_for_value
-					pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
-
+			if not args.get(applicable_for):
+				docname = get_pricing_rule_docname(d)
+				pr = prepare_pricing_rule(args, doc, child_doc, discount_fields, d, docname)
 				new_doc.append(pr)
+			else:
+				for applicable_for_value in args.get(applicable_for):
+					docname = get_pricing_rule_docname(d, applicable_for, applicable_for_value)
+					pr = prepare_pricing_rule(args, doc, child_doc, discount_fields,
+						d, docname, applicable_for, applicable_for_value)
+					new_doc.append(pr)
 
-		else:
+		elif args.get(applicable_for):
 			applicable_for_values = args.get(applicable_for) or []
 			for applicable_for_value in applicable_for_values:
-				pr = frappe.new_doc("Pricing Rule")
-				pr.title = doc.name
-				temp_args = args.copy()
-				temp_args[applicable_for] = applicable_for_value
-				pr = set_args(temp_args, pr, doc, child_doc, discount_fields, d)
+				pr = prepare_pricing_rule(args, doc, child_doc, discount_fields,
+					d, applicable_for=applicable_for, value= applicable_for_value)
+
 				new_doc.append(pr)
+		else:
+			pr = prepare_pricing_rule(args, doc, child_doc, discount_fields, d)
+			new_doc.append(pr)
 
 	return new_doc
 
+def get_pricing_rule_docname(row: dict, applicable_for: str = None, applicable_for_value: str = None) -> str:
+	fields = ['promotional_scheme_id', 'name']
+	filters = {
+		'promotional_scheme_id': row.name
+	}
 
+	if applicable_for:
+		fields.append(applicable_for)
+		filters[applicable_for] = applicable_for_value
 
+	docname = frappe.get_all('Pricing Rule', fields = fields, filters = filters)
+	return docname[0].name if docname else ''
+
+def prepare_pricing_rule(args, doc, child_doc, discount_fields, d, docname=None, applicable_for=None, value=None):
+	if docname:
+		pr = frappe.get_doc("Pricing Rule", docname)
+	else:
+		pr = frappe.new_doc("Pricing Rule")
+
+	pr.title = doc.name
+	temp_args = args.copy()
+
+	if value:
+		temp_args[applicable_for] = value
+
+	return set_args(temp_args, pr, doc, child_doc, discount_fields, d)
 
 def set_args(args, pr, doc, child_doc, discount_fields, child_doc_fields):
 	pr.update(args)
@@ -145,6 +203,7 @@
 				apply_on: d.get(apply_on),
 				'uom': d.uom
 			})
+
 	return pr
 
 def get_args_for_pricing_rule(doc):
diff --git a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
index e1852ae..49192a4 100644
--- a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
+++ b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
@@ -5,10 +5,17 @@
 
 import frappe
 
+from erpnext.accounts.doctype.promotional_scheme.promotional_scheme import TransactionExists
+from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
+
 
 class TestPromotionalScheme(unittest.TestCase):
+	def setUp(self):
+		if frappe.db.exists('Promotional Scheme', '_Test Scheme'):
+			frappe.delete_doc('Promotional Scheme', '_Test Scheme')
+
 	def test_promotional_scheme(self):
-		ps = make_promotional_scheme()
+		ps = make_promotional_scheme(applicable_for='Customer', customer='_Test Customer')
 		price_rules = frappe.get_all('Pricing Rule', fields = ["promotional_scheme_id", "name", "creation"],
 			filters = {'promotional_scheme': ps.name})
 		self.assertTrue(len(price_rules),1)
@@ -39,22 +46,62 @@
 			filters = {'promotional_scheme': ps.name})
 		self.assertEqual(price_rules, [])
 
-def make_promotional_scheme():
+	def test_promotional_scheme_without_applicable_for(self):
+		ps = make_promotional_scheme()
+		price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
+
+		self.assertTrue(len(price_rules), 1)
+		frappe.delete_doc('Promotional Scheme', ps.name)
+
+		price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
+		self.assertEqual(price_rules, [])
+
+	def test_change_applicable_for_in_promotional_scheme(self):
+		ps = make_promotional_scheme()
+		price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
+		self.assertTrue(len(price_rules), 1)
+
+		so = make_sales_order(qty=5, currency='USD', do_not_save=True)
+		so.set_missing_values()
+		so.save()
+		self.assertEqual(price_rules[0].name, so.pricing_rules[0].pricing_rule)
+
+		ps.applicable_for = 'Customer'
+		ps.append('customer', {
+			'customer': '_Test Customer'
+		})
+
+		self.assertRaises(TransactionExists, ps.save)
+
+		frappe.delete_doc('Sales Order', so.name)
+		frappe.delete_doc('Promotional Scheme', ps.name)
+		price_rules = frappe.get_all('Pricing Rule', filters = {'promotional_scheme': ps.name})
+		self.assertEqual(price_rules, [])
+
+def make_promotional_scheme(**args):
+	args = frappe._dict(args)
+
 	ps = frappe.new_doc('Promotional Scheme')
 	ps.name = '_Test Scheme'
 	ps.append('items',{
 		'item_code': '_Test Item'
 	})
+
 	ps.selling = 1
 	ps.append('price_discount_slabs',{
 		'min_qty': 4,
+		'validate_applied_rule': 0,
 		'discount_percentage': 20,
 		'rule_description': 'Test'
 	})
-	ps.applicable_for = 'Customer'
-	ps.append('customer',{
-		'customer': "_Test Customer"
-	})
+
+	ps.company = '_Test Company'
+	if args.applicable_for:
+		ps.applicable_for = args.applicable_for
+		ps.append(frappe.scrub(args.applicable_for), {
+			frappe.scrub(args.applicable_for): args.get(frappe.scrub(args.applicable_for))
+		})
+
 	ps.save()
 
 	return ps
diff --git a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json
index a70d5c9..aa3696d 100644
--- a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json
+++ b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json
@@ -136,7 +136,7 @@
    "label": "Threshold for Suggestion"
   },
   {
-   "default": "1",
+   "default": "0",
    "fieldname": "validate_applied_rule",
    "fieldtype": "Check",
    "label": "Validate Applied Rule"
@@ -169,7 +169,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-08-19 15:49:29.598727",
+ "modified": "2021-11-16 00:25:33.843996",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Promotional Scheme Price Discount",