diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 9787fda86d3e..7b73fca7bf94 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -375,6 +375,44 @@ def test_pricing_rule_with_margin_and_discount_amount(self): self.assertEqual(item.discount_amount, 110) self.assertEqual(item.rate, 990) + def test_pricing_rule_with_multiple_margins(self): + frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule") + make_pricing_rule( + selling=1, + margin_type="Percentage", + margin_rate_or_amount=10, + rate_or_discount="Discount Amount", + apply_multiple_pricing_rules=1, + discount_amount=0, + ) + make_pricing_rule( + selling=1, + margin_type="Percentage", + margin_rate_or_amount=5, + rate_or_discount="Discount Amount", + discount_amount=0, + apply_multiple_pricing_rules=1, + ) + make_pricing_rule( + selling=1, + margin_type="Amount", + margin_rate_or_amount=100, + rate_or_discount="Discount Amount", + discount_amount=0, + apply_multiple_pricing_rules=1, + ) + + si = create_sales_invoice(do_not_save=True) + si.items[0].price_list_rate = 1000 + si.payment_schedule = [] + si.insert(ignore_permissions=True) + + item = si.items[0] + self.assertEqual(item.margin_type, "Amount") + self.assertEqual(item.margin_rate_or_amount, 250) + self.assertEqual(item.rate_with_margin, 1250) + self.assertEqual(item.rate, 1250) + def test_pricing_rule_for_product_discount_on_same_item(self): frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule") test_record = { diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index ca0b037ea5b0..3a980d316ec6 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -962,19 +962,46 @@ def calculate_margin(self, item): if item.price_list_rate: if item.pricing_rules and not self.doc.ignore_pricing_rule: has_margin = False - for d in get_applied_pricing_rules(item.pricing_rules): - pricing_rule = frappe.get_cached_doc("Pricing Rule", d) - if pricing_rule.margin_rate_or_amount and ( - ( - pricing_rule.currency == self.doc.currency - and pricing_rule.margin_type in ["Amount", "Percentage"] - ) - or pricing_rule.margin_type == "Percentage" - ): - item.margin_type = pricing_rule.margin_type - item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount - has_margin = True + applied_pricing_rules = get_applied_pricing_rules(item.pricing_rules) + + # If only one pricing rule is applied + if len(applied_pricing_rules) == 1: + for d in applied_pricing_rules: + pricing_rule = frappe.get_cached_doc("Pricing Rule", d) + + if pricing_rule.margin_rate_or_amount and ( + ( + pricing_rule.currency == self.doc.currency + and pricing_rule.margin_type in ["Amount", "Percentage"] + ) + or pricing_rule.margin_type == "Percentage" + ): + item.margin_type = pricing_rule.margin_type + item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount + has_margin = True + + # If multiple pricing rules are applied + if len(applied_pricing_rules) > 1: + item.margin_rate_or_amount = 0 + for d in applied_pricing_rules: + pricing_rule = frappe.get_cached_doc("Pricing Rule", d) + + if pricing_rule.margin_rate_or_amount: + if pricing_rule.margin_type == "Percentage": + item.margin_type = "Amount" + item.margin_rate_or_amount += item.price_list_rate * ( + pricing_rule.margin_rate_or_amount / 100 + ) + has_margin = True + + elif ( + pricing_rule.margin_type == "Amount" + and pricing_rule.currency == self.doc.currency + ): + item.margin_type = "Amount" + item.margin_rate_or_amount += pricing_rule.margin_rate_or_amount + has_margin = True if not has_margin: item.margin_type = None