diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index c002c322d1c0cd9bbcb904bebbbc3c2fdda541f4..4df452fbdce3902bd8e743cdfc5a99127d8a8851 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -138,6 +138,7 @@ class PricingRule(Document): self.validate_price_list_with_currency() self.validate_dates() self.validate_condition() + self.validate_mixed_with_recursion() if not self.margin_type: self.margin_rate_or_amount = 0.0 @@ -307,6 +308,10 @@ class PricingRule(Document): ): frappe.throw(_("Invalid condition expression")) + def validate_mixed_with_recursion(self): + if self.mixed_conditions and self.is_recursive: + frappe.throw(_("Recursive Discounts with Mixed condition is not supported by the system")) + # -------------------------------------------------------------------------------- diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 21605bd1a075be39dccc3e5293b32ac2422ccf70..bcc55c82a573817e19171aa11ccbf7a9bb88770e 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -1366,6 +1366,18 @@ class TestPricingRule(unittest.TestCase): frappe.delete_doc("Item Price", item_price.name, force=True) + def test_validation_on_mixed_condition_with_recursion(self): + pricing_rule = make_pricing_rule( + discount_percentage=10, + selling=1, + priority=2, + min_qty=4, + title="_Test Pricing Rule with Min Qty - 2", + ) + pricing_rule.mixed_conditions = True + pricing_rule.is_recursive = True + self.assertRaises(frappe.ValidationError, pricing_rule.save) + test_dependencies = ["Campaign"] diff --git a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py index af6d096b058685ab42aee997fd0661a619177e9b..6cd3c137dd26cafe8fb30773140a9a7ceacef487 100644 --- a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py +++ b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py @@ -79,6 +79,7 @@ class PromotionalScheme(Document): self.validate_applicable_for() self.validate_pricing_rules() + self.validate_mixed_with_recursion() def validate_applicable_for(self): if self.applicable_for: @@ -96,15 +97,13 @@ class PromotionalScheme(Document): docnames = [] # If user has changed applicable for - if self._doc_before_save.applicable_for == self.applicable_for: + if self.get_doc_before_save() and self.get_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)} - ): + 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: @@ -112,6 +111,7 @@ class PromotionalScheme(Document): frappe.delete_doc("Pricing Rule", docname.name) def on_update(self): + self.validate() pricing_rules = ( frappe.get_all( "Pricing Rule", @@ -123,6 +123,15 @@ class PromotionalScheme(Document): ) self.update_pricing_rules(pricing_rules) + def validate_mixed_with_recursion(self): + if self.mixed_conditions: + if self.product_discount_slabs: + for slab in self.product_discount_slabs: + if slab.is_recursive: + frappe.throw( + _("Recursive Discounts with Mixed condition is not supported by the system") + ) + def update_pricing_rules(self, pricing_rules): rules = {} count = 0 @@ -189,7 +198,14 @@ def _get_pricing_rules(doc, child_doc, discount_fields, rules=None): 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 + args, + doc, + child_doc, + discount_fields, + d, + docname, + applicable_for, + applicable_for_value, ) new_doc.append(pr) @@ -214,9 +230,7 @@ def _get_pricing_rules(doc, child_doc, discount_fields, rules=None): return new_doc -def get_pricing_rule_docname( - row: dict, applicable_for: str = None, applicable_for_value: str = None -) -> str: +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} diff --git a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py index 9b40c98829ca996fe77180ec8a8d7ac15adbb019..c7338c5f416a511b9783b0c3195ccf7700f5b184 100644 --- a/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py +++ b/erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py @@ -14,6 +14,10 @@ class TestPromotionalScheme(unittest.TestCase): if frappe.db.exists("Promotional Scheme", "_Test Scheme"): frappe.delete_doc("Promotional Scheme", "_Test Scheme") + def tearDown(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(applicable_for="Customer", customer="_Test Customer") price_rules = frappe.get_all( @@ -129,6 +133,25 @@ class TestPromotionalScheme(unittest.TestCase): [pr.min_qty, pr.free_item, pr.free_qty, pr.recurse_for], [12, "_Test Item 2", 1, 12] ) + def test_validation_on_recurse_with_mixed_condition(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.mixed_conditions = True + self.assertRaises(frappe.ValidationError, ps.save) + def make_promotional_scheme(**args): args = frappe._dict(args)