From faf9b589c4d54ea72a47b088183ebe641c84e4d3 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 8 Feb 2016 18:49:27 +0530 Subject: [PATCH] [fix] pricing rule for variant, if rule for template available, use it --- .../doctype/pricing_rule/pricing_rule.py | 42 ++++++---- .../doctype/pricing_rule/test_pricing_rule.py | 76 ++++++++++++++++++- .../quotation_item/quotation_item.json | 41 +++++++++- 3 files changed, 140 insertions(+), 19 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index fcc1f92173..cd6bcf450b 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -97,10 +97,10 @@ def apply_pricing_rule(args): args = json.loads(args) args = frappe._dict(args) - + if not args.transaction_type: set_transaction_type(args) - + # list of dictionaries out = [] @@ -142,7 +142,7 @@ def get_pricing_rule_for_item(args): customer = frappe.db.get_value("Customer", args.customer, ["customer_group", "territory"]) if customer: args.customer_group, args.territory = customer - + args.supplier = args.supplier_type = None elif args.supplier and not args.supplier_type: @@ -186,7 +186,7 @@ def get_pricing_rules(args): return condition - conditions = "" + conditions = item_variant_condition = "" values = {"item_code": args.get("item_code"), "brand": args.get("brand")} for field in ["company", "customer", "supplier", "supplier_type", "campaign", "sales_partner"]: @@ -211,16 +211,26 @@ def get_pricing_rules(args): values['transaction_date'] = args.get('transaction_date') item_group_condition = _get_tree_conditions("Item Group", False) - if item_group_condition: item_group_condition = " or " + item_group_condition + if item_group_condition: + item_group_condition = " or " + item_group_condition + + # load variant of if not defined + if "variant_of" not in args: + args.variant_of = frappe.db.get_value("Item", args.item_code, "variant_of") + + if args.variant_of: + item_variant_condition = ' or item_code=%(variant_of)s ' + values['variant_of'] = args.variant_of return frappe.db.sql("""select * from `tabPricing Rule` - where (item_code=%(item_code)s {item_group_condition} or brand=%(brand)s) + where (item_code=%(item_code)s {item_variant_condition} {item_group_condition} or brand=%(brand)s) and docstatus < 2 and disable = 0 and {transaction_type} = 1 {conditions} order by priority desc, name desc""".format( - item_group_condition=item_group_condition, - transaction_type= args.transaction_type, - conditions=conditions), values, as_dict=1) + item_group_condition = item_group_condition, + item_variant_condition = item_variant_condition, + transaction_type = args.transaction_type, + conditions = conditions), values, as_dict=1) def filter_pricing_rules(args, pricing_rules): # filter for qty @@ -228,6 +238,11 @@ def filter_pricing_rules(args, pricing_rules): pricing_rules = filter(lambda x: (flt(args.get("qty"))>=flt(x.min_qty) and (flt(args.get("qty"))<=x.max_qty if x.max_qty else True)), pricing_rules) + # add variant_of property in pricing rule + for p in pricing_rules: + if p.item_code and args.variant_of: + p.variant_of = args.variant_of + # find pricing rule with highest priority if pricing_rules: max_priority = max([cint(p.priority) for p in pricing_rules]) @@ -239,7 +254,7 @@ def filter_pricing_rules(args, pricing_rules): "supplier", "supplier_type", "campaign", "sales_partner"] if len(pricing_rules) > 1: - for field_set in [["item_code", "item_group", "brand"], + for field_set in [["item_code", "variant_of", "item_group", "brand"], ["customer", "customer_group", "territory"], ["supplier", "supplier_type"]]: remaining_fields = list(set(all_fields) - set(field_set)) if if_all_rules_same(pricing_rules, remaining_fields): @@ -253,8 +268,7 @@ def filter_pricing_rules(args, pricing_rules): or pricing_rules if len(pricing_rules) > 1: - frappe.throw(_("Multiple Price Rule exists with same criteria, please resolve \ - conflict by assigning priority. Price Rules: {0}") + frappe.throw(_("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: {0}") .format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict) elif pricing_rules: return pricing_rules[0] @@ -281,10 +295,10 @@ def apply_internal_priority(pricing_rules, field_set, args): def set_transaction_type(args): if args.doctype in ("Opportunity", "Quotation", "Sales Order", "Delivery Note", "Sales Invoice"): args.transaction_type = "selling" - elif args.doctype in ("Material Request", "Supplier Quotation", "Purchase Order", + elif args.doctype in ("Material Request", "Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"): args.transaction_type = "buying" elif args.customer: args.transaction_type = "selling" else: - args.transaction_type = "buying" \ No newline at end of file + args.transaction_type = "buying" diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index bdd743125a..d8d74bc707 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -41,12 +41,12 @@ class TestPricingRule(unittest.TestCase): }) details = get_item_details(args) self.assertEquals(details.get("discount_percentage"), 10) - + prule = frappe.get_doc(test_record.copy()) prule.applicable_for = "Customer" prule.title = "_Test Pricing Rule for Customer" self.assertRaises(MandatoryError, prule.insert) - + prule.customer = "_Test Customer" prule.discount_percentage = 20 prule.insert() @@ -59,7 +59,7 @@ class TestPricingRule(unittest.TestCase): prule.title = "_Test Pricing Rule for Item Group" prule.discount_percentage = 15 prule.insert() - + args.customer = "_Test Customer 1" details = get_item_details(args) self.assertEquals(details.get("discount_percentage"), 10) @@ -85,3 +85,73 @@ class TestPricingRule(unittest.TestCase): self.assertEquals(details.get("discount_percentage"), 15) frappe.db.sql("delete from `tabPricing Rule`") + + def test_pricing_rule_for_variants(self): + from erpnext.stock.get_item_details import get_item_details + from frappe import MandatoryError + + frappe.db.sql("delete from `tabPricing Rule`") + + if not frappe.db.exists("Item", "Test Variant PRT"): + frappe.get_doc({ + "doctype": "Item", + "item_code": "Test Variant PRT", + "item_name": "Test Variant PRT", + "description": "Test Variant PRT", + "item_group": "_Test Item Group", + "is_stock_item": 1, + "variant_of": "_Test Variant Item", + "default_warehouse": "_Test Warehouse - _TC", + "stock_uom": "_Test UOM", + "attributes": [ + { + "attribute": "Test Size", + "attribute_value": "Medium" + } + ], + }).insert() + + frappe.get_doc({ + "doctype": "Pricing Rule", + "title": "_Test Pricing Rule 1", + "apply_on": "Item Code", + "item_code": "_Test Variant Item", + "selling": 1, + "price_or_discount": "Discount Percentage", + "price": 0, + "discount_percentage": 7.5, + "company": "_Test Company" + }).insert() + + args = frappe._dict({ + "item_code": "Test Variant PRT", + "company": "_Test Company", + "price_list": "_Test Price List", + "currency": "_Test Currency", + "doctype": "Sales Order", + "conversion_rate": 1, + "price_list_currency": "_Test Currency", + "plc_conversion_rate": 1, + "order_type": "Sales", + "customer": "_Test Customer", + "name": None + }) + + details = get_item_details(args) + self.assertEquals(details.get("discount_percentage"), 7.5) + + # add a new pricing rule for that item code, it should take priority + frappe.get_doc({ + "doctype": "Pricing Rule", + "title": "_Test Pricing Rule 2", + "apply_on": "Item Code", + "item_code": "Test Variant PRT", + "selling": 1, + "price_or_discount": "Discount Percentage", + "price": 0, + "discount_percentage": 17.5, + "company": "_Test Company" + }).insert() + + details = get_item_details(args) + self.assertEquals(details.get("discount_percentage"), 17.5) diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index b1d441c56c..0146f38133 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -26,6 +26,7 @@ "options": "Item", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "150px", "read_only": 0, "report_hide": 0, @@ -50,6 +51,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -71,6 +73,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -95,6 +98,7 @@ "oldfieldtype": "Data", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "150px", "read_only": 0, "report_hide": 0, @@ -107,18 +111,20 @@ { "allow_on_submit": 0, "bold": 0, - "collapsible": 0, + "collapsible": 1, "fieldname": "section_break_5", "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, + "label": "Description", "length": 0, "no_copy": 0, "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -143,6 +149,7 @@ "oldfieldtype": "Small Text", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "300px", "read_only": 0, "report_hide": 0, @@ -167,6 +174,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -190,6 +198,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -214,6 +223,7 @@ "permlevel": 0, "precision": "", "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -236,6 +246,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -260,6 +271,7 @@ "oldfieldtype": "Currency", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 0, "report_hide": 0, @@ -287,6 +299,7 @@ "options": "currency", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 1, "report_hide": 0, @@ -314,6 +327,7 @@ "oldfieldtype": "Float", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 0, "report_hide": 0, @@ -337,6 +351,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -362,6 +377,7 @@ "options": "UOM", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 1, "report_hide": 0, @@ -389,6 +405,7 @@ "options": "Company:company:default_currency", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 1, "report_hide": 0, @@ -412,6 +429,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -437,6 +455,7 @@ "options": "currency", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 0, "report_hide": 0, @@ -462,6 +481,7 @@ "permlevel": 0, "precision": "", "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -487,6 +507,7 @@ "options": "currency", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 1, "report_hide": 0, @@ -513,6 +534,7 @@ "permlevel": 0, "precision": "", "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -534,6 +556,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -559,6 +582,7 @@ "options": "Company:company:default_currency", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 1, "report_hide": 0, @@ -584,6 +608,7 @@ "permlevel": 0, "precision": "", "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -609,6 +634,7 @@ "options": "Company:company:default_currency", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "100px", "read_only": 1, "report_hide": 0, @@ -635,6 +661,7 @@ "permlevel": 0, "precision": "", "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -658,6 +685,7 @@ "options": "Pricing Rule", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -680,6 +708,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -705,6 +734,7 @@ "options": "DocType", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "150px", "read_only": 1, "report_hide": 0, @@ -732,6 +762,7 @@ "options": "prevdoc_doctype", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "150px", "read_only": 1, "report_hide": 0, @@ -758,6 +789,7 @@ "oldfieldtype": "Small Text", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 1, "reqd": 0, @@ -779,6 +811,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -803,6 +836,7 @@ "oldfieldtype": "Check", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 1, "reqd": 0, @@ -829,6 +863,7 @@ "options": "Item Group", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -854,6 +889,7 @@ "options": "Brand", "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "print_width": "150px", "read_only": 1, "report_hide": 0, @@ -873,7 +909,8 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2015-11-16 06:29:55.206667", + "menu_index": 0, + "modified": "2016-02-08 08:02:06.257910", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item",