From f6dda738dc99060090e703b21f7a77692887605b Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 20 Jan 2022 12:22:56 +0530 Subject: [PATCH 1/4] fix: ignore pricing rule in all transactions --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 4 +++- erpnext/public/js/controllers/transaction.js | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index ac96b045a2..93c68f07ce 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -249,7 +249,8 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa "free_item_data": [], "parent": args.parent, "parenttype": args.parenttype, - "child_docname": args.get('child_docname') + "child_docname": args.get('child_docname'), + "price_list_rate": args.get('price_list_rate') }) if args.ignore_pricing_rule or not args.item_code: @@ -403,6 +404,7 @@ def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): if pricing_rule.rate_or_discount == 'Discount Percentage': item_details.discount_percentage = 0.0 item_details.discount_amount = 0.0 + item_details.rate = item_details.get('price_list_rate', 0) if pricing_rule.rate_or_discount == 'Discount Amount': item_details.discount_amount = 0.0 diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 3791741663..65ccd1f11f 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1463,7 +1463,8 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe "item_code": d.item_code, "pricing_rules": d.pricing_rules, "parenttype": d.parenttype, - "parent": d.parent + "parent": d.parent, + "price_list_rate": d.price_list_rate }) } }); From b8c41e303035993d98aeb406865052a968335afe Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 20 Jan 2022 13:06:08 +0530 Subject: [PATCH 2/4] test: item price on remove pricing rule --- .../doctype/pricing_rule/pricing_rule.py | 1 + .../doctype/pricing_rule/test_pricing_rule.py | 41 +++++++++++++++++++ erpnext/controllers/accounts_controller.py | 8 ++++ 3 files changed, 50 insertions(+) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 93c68f07ce..65ded03673 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -423,6 +423,7 @@ def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): item_details.applied_on_items = ','.join(items) item_details.pricing_rules = '' + item_details.pricing_rule_removed = True return item_details diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 5746a840f3..2a2b1cf681 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -628,6 +628,47 @@ class TestPricingRule(unittest.TestCase): for doc in [si, si1]: doc.delete() + def test_remove_pricing_rule(self): + item = make_item("Water Flask") + make_item_price("Water Flask", "_Test Price List", 100) + + pricing_rule_record = { + "doctype": "Pricing Rule", + "title": "_Test Water Flask Rule", + "apply_on": "Item Code", + "price_or_product_discount": "Price", + "items": [{ + "item_code": "Water Flask", + }], + "selling": 1, + "currency": "INR", + "rate_or_discount": "Discount Percentage", + "discount_percentage": 20, + "company": "_Test Company" + } + rule = frappe.get_doc(pricing_rule_record) + rule.insert() + + si = create_sales_invoice(do_not_save=True, item_code="Water Flask") + si.selling_price_list = "_Test Price List" + si.save() + + self.assertEqual(si.items[0].price_list_rate, 100) + self.assertEqual(si.items[0].discount_percentage, 20) + self.assertEqual(si.items[0].rate, 80) + + si.ignore_pricing_rule = 1 + si.save() + + self.assertEqual(si.items[0].discount_percentage, 0) + self.assertEqual(si.items[0].rate, 100) + + si.delete() + rule.delete() + frappe.get_doc("Item Price", {"item_code": "Water Flask"}).delete() + item.delete() + + test_dependencies = ["Campaign"] def make_pricing_rule(**args): diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 4775f56a01..27e882e8d5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -402,6 +402,14 @@ class AccountsController(TransactionBase): if item_qty != len(get_serial_nos(item.get('serial_no'))): item.set(fieldname, value) + elif ret.get("pricing_rule_removed") and value is not None \ + and fieldname in [ + 'discount_percentage', 'discount_amount', 'rate', + 'margin_rate_or_amount', 'margin_type', 'remove_free_item' + ]: + # reset pricing rule fields if pricing_rule_removed + item.set(fieldname, value) + if self.doctype in ["Purchase Invoice", "Sales Invoice"] and item.meta.get_field('is_fixed_asset'): item.set('is_fixed_asset', ret.get('is_fixed_asset', 0)) From 6fa406dd04d7538b38e076cb4636b5713994456d Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 8 Feb 2022 16:32:08 +0530 Subject: [PATCH 3/4] fix(test): pass price_list_rate only if pricing rule has to be removed --- .../doctype/pos_invoice/test_pos_invoice.py | 36 +++++++++++-------- .../doctype/pricing_rule/pricing_rule.py | 30 ++++++++++------ 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index ba751c081b..cf8affdd01 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -586,23 +586,29 @@ class TestPOSInvoice(unittest.TestCase): item_price.insert() pr = make_pricing_rule(selling=1, priority=5, discount_percentage=10) pr.save() - pos_inv = create_pos_invoice(qty=1, do_not_submit=1) - pos_inv.items[0].rate = 300 - pos_inv.save() - self.assertEquals(pos_inv.items[0].discount_percentage, 10) - # rate shouldn't change - self.assertEquals(pos_inv.items[0].rate, 405) - pos_inv.ignore_pricing_rule = 1 - pos_inv.items[0].rate = 300 - pos_inv.save() - self.assertEquals(pos_inv.ignore_pricing_rule, 1) - # rate should change since pricing rules are ignored - self.assertEquals(pos_inv.items[0].rate, 300) + try: + pos_inv = create_pos_invoice(qty=1, do_not_submit=1) + pos_inv.items[0].rate = 300 + pos_inv.save() + self.assertEquals(pos_inv.items[0].discount_percentage, 10) + # rate shouldn't change + self.assertEquals(pos_inv.items[0].rate, 405) - item_price.delete() - pos_inv.delete() - pr.delete() + pos_inv.ignore_pricing_rule = 1 + pos_inv.save() + self.assertEquals(pos_inv.ignore_pricing_rule, 1) + # rate should reset since pricing rules are ignored + self.assertEquals(pos_inv.items[0].rate, 450) + + pos_inv.items[0].rate = 300 + pos_inv.save() + self.assertEquals(pos_inv.items[0].rate, 300) + + finally: + item_price.delete() + pos_inv.delete() + pr.delete() def create_pos_invoice(**args): diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 65ded03673..933fda8a0a 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -250,13 +250,16 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa "parent": args.parent, "parenttype": args.parenttype, "child_docname": args.get('child_docname'), - "price_list_rate": args.get('price_list_rate') }) if args.ignore_pricing_rule or not args.item_code: if frappe.db.exists(args.doctype, args.name) and args.get("pricing_rules"): - item_details = remove_pricing_rule_for_item(args.get("pricing_rules"), - item_details, args.get('item_code')) + item_details = remove_pricing_rule_for_item( + args.get("pricing_rules"), + item_details, + item_code=args.get("item_code"), + rate=args.get("price_list_rate"), + ) return item_details update_args_for_pricing_rule(args) @@ -309,8 +312,12 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa if not doc: return item_details elif args.get("pricing_rules"): - item_details = remove_pricing_rule_for_item(args.get("pricing_rules"), - item_details, args.get('item_code')) + item_details = remove_pricing_rule_for_item( + args.get("pricing_rules"), + item_details, + item_code=args.get("item_code"), + rate=args.get("price_list_rate"), + ) return item_details @@ -391,7 +398,7 @@ def apply_price_discount_rule(pricing_rule, item_details, args): item_details[field] += (pricing_rule.get(field, 0) if pricing_rule else args.get(field, 0)) -def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): +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, @@ -404,7 +411,7 @@ def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): if pricing_rule.rate_or_discount == 'Discount Percentage': item_details.discount_percentage = 0.0 item_details.discount_amount = 0.0 - item_details.rate = item_details.get('price_list_rate', 0) + item_details.rate = rate or 0.0 if pricing_rule.rate_or_discount == 'Discount Amount': item_details.discount_amount = 0.0 @@ -435,9 +442,12 @@ def remove_pricing_rules(item_list): out = [] for item in item_list: item = frappe._dict(item) - if item.get('pricing_rules'): - out.append(remove_pricing_rule_for_item(item.get("pricing_rules"), - item, item.item_code)) + if item.get("pricing_rules"): + out.append( + remove_pricing_rule_for_item( + item.get("pricing_rules"), item, item.item_code, item.get("price_list_rate") + ) + ) return out From ab36b27a94f5f88a71358292ef7b76103c7080b7 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 9 Feb 2022 10:10:17 +0530 Subject: [PATCH 4/4] fix: ignore pricing rule in all transactions --- erpnext/controllers/accounts_controller.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index d86b6c7ea4..994b903b32 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -407,11 +407,19 @@ class AccountsController(TransactionBase): if item_qty != len(get_serial_nos(item.get('serial_no'))): item.set(fieldname, value) - elif ret.get("pricing_rule_removed") and value is not None \ - and fieldname in [ - 'discount_percentage', 'discount_amount', 'rate', - 'margin_rate_or_amount', 'margin_type', 'remove_free_item' - ]: + elif ( + ret.get("pricing_rule_removed") + and value is not None + and fieldname + in [ + "discount_percentage", + "discount_amount", + "rate", + "margin_rate_or_amount", + "margin_type", + "remove_free_item", + ] + ): # reset pricing rule fields if pricing_rule_removed item.set(fieldname, value)