Merge pull request #1827 from anandpdoshi/anand-wip

Naming Series property type as Text
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
index 356cc0d..a1859e5 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
@@ -61,4 +61,31 @@
 	'</table>'].join("\n");
 
 	set_field_options("pricing_rule_help", help_content);
+
+	cur_frm.cscript.set_options_for_applicable_for();
 });
+
+cur_frm.cscript.set_options_for_applicable_for = function() {
+	var options = [""];
+	var applicable_for = cur_frm.doc.applicable_for;
+
+	if(cur_frm.doc.selling) {
+		options = $.merge(options, ["Customer", "Customer Group", "Territory", "Sales Partner", "Campaign"]);
+	}
+	if(cur_frm.doc.buying) {
+		$.merge(options, ["Supplier", "Supplier Type"]);
+	}
+
+	set_field_options("applicable_for", options.join("\n"));
+
+	if(!in_list(options, applicable_for)) applicable_for = null;
+	cur_frm.set_value("applicable_for", applicable_for)
+}
+
+cur_frm.cscript.selling = function() {
+	cur_frm.cscript.set_options_for_applicable_for();
+}
+
+cur_frm.cscript.buying = function() {
+	cur_frm.cscript.set_options_for_applicable_for();
+}
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
index b20563f..2d318c6 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
@@ -1,288 +1,299 @@
 {
- "allow_import": 1,
- "autoname": "PRULE.#####",
- "creation": "2014-02-21 15:02:51",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Master",
+ "allow_import": 1, 
+ "autoname": "PRULE.#####", 
+ "creation": "2014-02-21 15:02:51", 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Master", 
  "fields": [
   {
-   "fieldname": "applicability_section",
-   "fieldtype": "Section Break",
-   "in_list_view": 0,
-   "label": "Applicability",
+   "fieldname": "applicability_section", 
+   "fieldtype": "Section Break", 
+   "in_list_view": 0, 
+   "label": "Applicability", 
    "permlevel": 0
-  },
+  }, 
   {
-   "default": "Item Code",
-   "fieldname": "apply_on",
-   "fieldtype": "Select",
-   "in_list_view": 1,
-   "label": "Apply On",
-   "options": "\nItem Code\nItem Group\nBrand",
-   "permlevel": 0,
+   "default": "Item Code", 
+   "fieldname": "apply_on", 
+   "fieldtype": "Select", 
+   "in_list_view": 1, 
+   "label": "Apply On", 
+   "options": "\nItem Code\nItem Group\nBrand", 
+   "permlevel": 0, 
    "reqd": 1
-  },
+  }, 
   {
-   "depends_on": "eval:doc.apply_on==\"Item Code\"",
-   "fieldname": "item_code",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item Code",
-   "options": "Item",
-   "permlevel": 0,
+   "depends_on": "eval:doc.apply_on==\"Item Code\"", 
+   "fieldname": "item_code", 
+   "fieldtype": "Link", 
+   "in_list_view": 1, 
+   "label": "Item Code", 
+   "options": "Item", 
+   "permlevel": 0, 
    "reqd": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.apply_on==\"Item Group\"",
-   "fieldname": "item_group",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item Group",
-   "options": "Item Group",
+   "depends_on": "eval:doc.apply_on==\"Item Group\"", 
+   "fieldname": "item_group", 
+   "fieldtype": "Link", 
+   "in_list_view": 1, 
+   "label": "Item Group", 
+   "options": "Item Group", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.apply_on==\"Brand\"",
-   "fieldname": "brand",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Brand",
-   "options": "Brand",
+   "depends_on": "eval:doc.apply_on==\"Brand\"", 
+   "fieldname": "brand", 
+   "fieldtype": "Link", 
+   "in_list_view": 1, 
+   "label": "Brand", 
+   "options": "Brand", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "applicable_for",
-   "fieldtype": "Select",
-   "label": "Applicable For",
-   "options": "\nCustomer\nCustomer Group\nTerritory\nSales Partner\nCampaign\nSupplier\nSupplier Type",
+   "fieldname": "selling", 
+   "fieldtype": "Check", 
+   "label": "Selling", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.applicable_for==\"Customer\"",
-   "fieldname": "customer",
-   "fieldtype": "Link",
-   "label": "Customer",
-   "options": "Customer",
+   "fieldname": "buying", 
+   "fieldtype": "Check", 
+   "label": "Buying", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.applicable_for==\"Customer Group\"",
-   "fieldname": "customer_group",
-   "fieldtype": "Link",
-   "label": "Customer Group",
-   "options": "Customer Group",
+   "fieldname": "applicable_for", 
+   "fieldtype": "Select", 
+   "label": "Applicable For", 
+   "options": "\nCustomer\nCustomer Group\nTerritory\nSales Partner\nCampaign\nSupplier\nSupplier Type", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.applicable_for==\"Territory\"",
-   "fieldname": "territory",
-   "fieldtype": "Link",
-   "label": "Territory",
-   "options": "Territory",
+   "depends_on": "eval:doc.applicable_for==\"Customer\"", 
+   "fieldname": "customer", 
+   "fieldtype": "Link", 
+   "label": "Customer", 
+   "options": "Customer", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.applicable_for==\"Sales Partner\"",
-   "fieldname": "sales_partner",
-   "fieldtype": "Link",
-   "label": "Sales Partner",
-   "options": "Sales Partner",
+   "depends_on": "eval:doc.applicable_for==\"Customer Group\"", 
+   "fieldname": "customer_group", 
+   "fieldtype": "Link", 
+   "label": "Customer Group", 
+   "options": "Customer Group", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.applicable_for==\"Campaign\"",
-   "fieldname": "campaign",
-   "fieldtype": "Link",
-   "label": "Campaign",
-   "options": "Campaign",
+   "depends_on": "eval:doc.applicable_for==\"Territory\"", 
+   "fieldname": "territory", 
+   "fieldtype": "Link", 
+   "label": "Territory", 
+   "options": "Territory", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.applicable_for==\"Supplier\"",
-   "fieldname": "supplier",
-   "fieldtype": "Link",
-   "label": "Supplier",
-   "options": "Supplier",
+   "depends_on": "eval:doc.applicable_for==\"Sales Partner\"", 
+   "fieldname": "sales_partner", 
+   "fieldtype": "Link", 
+   "label": "Sales Partner", 
+   "options": "Sales Partner", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.applicable_for==\"Supplier Type\"",
-   "fieldname": "supplier_type",
-   "fieldtype": "Link",
-   "label": "Supplier Type",
-   "options": "Supplier Type",
+   "depends_on": "eval:doc.applicable_for==\"Campaign\"", 
+   "fieldname": "campaign", 
+   "fieldtype": "Link", 
+   "label": "Campaign", 
+   "options": "Campaign", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "min_qty",
-   "fieldtype": "Float",
-   "label": "Min Qty",
+   "depends_on": "eval:doc.applicable_for==\"Supplier\"", 
+   "fieldname": "supplier", 
+   "fieldtype": "Link", 
+   "label": "Supplier", 
+   "options": "Supplier", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "max_qty",
-   "fieldtype": "Float",
-   "label": "Max Qty",
+   "depends_on": "eval:doc.applicable_for==\"Supplier Type\"", 
+   "fieldname": "supplier_type", 
+   "fieldtype": "Link", 
+   "label": "Supplier Type", 
+   "options": "Supplier Type", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "col_break1",
-   "fieldtype": "Column Break",
+   "fieldname": "min_qty", 
+   "fieldtype": "Float", 
+   "label": "Min Qty", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "company",
-   "fieldtype": "Link",
-   "label": "Company",
-   "options": "Company",
+   "fieldname": "max_qty", 
+   "fieldtype": "Float", 
+   "label": "Max Qty", 
    "permlevel": 0
-  },
+  }, 
   {
-   "default": "Today",
-   "fieldname": "valid_from",
-   "fieldtype": "Date",
-   "label": "Valid From",
+   "fieldname": "col_break1", 
+   "fieldtype": "Column Break", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "valid_upto",
-   "fieldtype": "Date",
-   "label": "Valid Upto",
+   "fieldname": "company", 
+   "fieldtype": "Link", 
+   "label": "Company", 
+   "options": "Company", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "priority",
-   "fieldtype": "Select",
-   "label": "Priority",
-   "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20",
+   "default": "Today", 
+   "fieldname": "valid_from", 
+   "fieldtype": "Date", 
+   "label": "Valid From", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "disable",
-   "fieldtype": "Check",
-   "label": "Disable",
+   "fieldname": "valid_upto", 
+   "fieldtype": "Date", 
+   "label": "Valid Upto", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "price_discount_section",
-   "fieldtype": "Section Break",
-   "label": "Price / Discount",
+   "fieldname": "priority", 
+   "fieldtype": "Select", 
+   "label": "Priority", 
+   "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20", 
    "permlevel": 0
-  },
+  }, 
   {
-   "default": "Discount Percentage",
-   "fieldname": "price_or_discount",
-   "fieldtype": "Select",
-   "label": "Price or Discount",
-   "options": "\nPrice\nDiscount Percentage",
-   "permlevel": 0,
+   "fieldname": "disable", 
+   "fieldtype": "Check", 
+   "label": "Disable", 
+   "permlevel": 0
+  }, 
+  {
+   "fieldname": "price_discount_section", 
+   "fieldtype": "Section Break", 
+   "label": "Price / Discount", 
+   "permlevel": 0
+  }, 
+  {
+   "default": "Discount Percentage", 
+   "fieldname": "price_or_discount", 
+   "fieldtype": "Select", 
+   "label": "Price or Discount", 
+   "options": "\nPrice\nDiscount Percentage", 
+   "permlevel": 0, 
    "reqd": 1
-  },
+  }, 
   {
-   "fieldname": "col_break2",
-   "fieldtype": "Column Break",
+   "fieldname": "col_break2", 
+   "fieldtype": "Column Break", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.price_or_discount==\"Price\"",
-   "fieldname": "price",
-   "fieldtype": "Float",
-   "label": "Price",
+   "depends_on": "eval:doc.price_or_discount==\"Price\"", 
+   "fieldname": "price", 
+   "fieldtype": "Float", 
+   "label": "Price", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"",
-   "fieldname": "discount_percentage",
-   "fieldtype": "Float",
-   "label": "Discount Percentage",
+   "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"", 
+   "fieldname": "discount_percentage", 
+   "fieldtype": "Float", 
+   "label": "Discount Percentage", 
    "permlevel": 0
-  },
+  }, 
   {
-   "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"",
-   "fieldname": "for_price_list",
-   "fieldtype": "Link",
-   "label": "For Price List",
-   "options": "Price List",
+   "depends_on": "eval:doc.price_or_discount==\"Discount Percentage\"", 
+   "fieldname": "for_price_list", 
+   "fieldtype": "Link", 
+   "label": "For Price List", 
+   "options": "Price List", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "help_section",
-   "fieldtype": "Section Break",
-   "label": "",
-   "options": "Simple",
+   "fieldname": "help_section", 
+   "fieldtype": "Section Break", 
+   "label": "", 
+   "options": "Simple", 
    "permlevel": 0
-  },
+  }, 
   {
-   "fieldname": "pricing_rule_help",
-   "fieldtype": "HTML",
-   "label": "Pricing Rule Help",
+   "fieldname": "pricing_rule_help", 
+   "fieldtype": "HTML", 
+   "label": "Pricing Rule Help", 
    "permlevel": 0
   }
- ],
- "icon": "icon-gift",
- "idx": 1,
- "istable": 0,
- "modified": "2014-05-28 15:36:29.403659",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Pricing Rule",
- "owner": "Administrator",
+ ], 
+ "icon": "icon-gift", 
+ "idx": 1, 
+ "istable": 0, 
+ "modified": "2014-06-20 19:36:22.502381", 
+ "modified_by": "Administrator", 
+ "module": "Accounts", 
+ "name": "Pricing Rule", 
+ "owner": "Administrator", 
  "permissions": [
   {
-   "create": 1,
-   "delete": 1,
-   "export": 0,
-   "import": 0,
-   "permlevel": 0,
-   "read": 1,
-   "report": 1,
-   "role": "Accounts Manager",
+   "create": 1, 
+   "delete": 1, 
+   "export": 1, 
+   "import": 1, 
+   "permlevel": 0, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Accounts Manager", 
    "write": 1
-  },
+  }, 
   {
-   "create": 1,
-   "delete": 1,
-   "export": 0,
-   "import": 0,
-   "permlevel": 0,
-   "print": 0,
-   "read": 1,
-   "report": 1,
-   "role": "Sales Manager",
+   "create": 1, 
+   "delete": 1, 
+   "export": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 0, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Sales Manager", 
    "write": 1
-  },
+  }, 
   {
-   "create": 1,
-   "delete": 1,
-   "permlevel": 0,
-   "read": 1,
-   "report": 1,
-   "role": "Purchase Manager",
+   "create": 1, 
+   "delete": 1, 
+   "permlevel": 0, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Purchase Manager", 
    "write": 1
-  },
+  }, 
   {
-   "create": 1,
-   "delete": 1,
-   "permlevel": 0,
-   "read": 1,
-   "report": 1,
-   "role": "Website Manager",
+   "create": 1, 
+   "delete": 1, 
+   "permlevel": 0, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Website Manager", 
    "write": 1
-  },
+  }, 
   {
-   "create": 1,
-   "delete": 1,
-   "export": 1,
-   "import": 1,
-   "permlevel": 0,
-   "read": 1,
-   "report": 1,
-   "set_user_permissions": 1,
-   "role": "System Manager",
+   "create": 1, 
+   "delete": 1, 
+   "export": 1, 
+   "import": 1, 
+   "permlevel": 0, 
+   "read": 1, 
+   "report": 1, 
+   "role": "System Manager", 
    "write": 1
   }
- ],
- "sort_field": "modified",
+ ], 
+ "sort_field": "modified", 
  "sort_order": "DESC"
-}
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index a15b45a..967d583 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -5,16 +5,21 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 from frappe import throw, _
-from frappe.utils import flt
+from frappe.utils import flt, cint
 from frappe.model.document import Document
 
+class MultiplePricingRuleConflict(frappe.ValidationError): pass
+
 class PricingRule(Document):
 	def validate(self):
 		self.validate_mandatory()
+		self.validate_applicable_for_selling_or_buying()
 		self.validate_min_max_qty()
 		self.cleanup_fields_value()
 		self.validate_price_or_discount()
+		self.validate_max_discount()
 
 	def validate_mandatory(self):
 		for field in ["apply_on", "applicable_for"]:
@@ -22,6 +27,18 @@
 			if tocheck and not self.get(tocheck):
 				throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
 
+	def validate_applicable_for_selling_or_buying(self):
+		if not self.selling and not self.buying:
+			throw(_("Atleast one of the Selling or Buying must be selected"))
+
+		if not self.selling and self.applicable_for in ["Customer", "Customer Group",
+				"Territory", "Sales Partner", "Campaign"]:
+			throw(_("Selling must be checked, if Applicable For is selected as {0}"
+				.format(self.applicable_for)))
+
+		if not self.buying and self.applicable_for in ["Supplier", "Supplier Type"]:
+			throw(_("Buying must be checked, if Applicable For is selected as {0}"
+				.format(self.applicable_for)))
 
 	def validate_min_max_qty(self):
 		if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty):
@@ -44,3 +61,189 @@
 		for field in ["Price", "Discount Percentage"]:
 			if flt(self.get(frappe.scrub(field))) < 0:
 				throw(_("{0} can not be negative").format(field))
+
+	def validate_max_discount(self):
+		if self.price_or_discount == "Discount Percentage" and self.item_code:
+			max_discount = frappe.db.get_value("Item", self.item_code, "max_discount")
+			if max_discount and flt(self.discount_percentage) > flt(max_discount):
+				throw(_("Max discount allowed for item: {0} is {1}%").format(self.item_code, max_discount))
+
+
+#--------------------------------------------------------------------------------
+
+@frappe.whitelist()
+def apply_pricing_rule(args):
+	"""
+		args = {
+			"item_list": [{"doctype": "", "name": "", "item_code": "", "brand": "", "item_group": ""}, ...],
+			"customer": "something",
+			"customer_group": "something",
+			"territory": "something",
+			"supplier": "something",
+			"supplier_type": "something",
+			"currency": "something",
+			"conversion_rate": "something",
+			"price_list": "something",
+			"plc_conversion_rate": "something",
+			"company": "something",
+			"transaction_date": "something",
+			"campaign": "something",
+			"sales_partner": "something",
+			"ignore_pricing_rule": "something"
+		}
+	"""
+	if isinstance(args, basestring):
+		args = json.loads(args)
+
+	args = frappe._dict(args)
+
+	# list of dictionaries
+	out = []
+
+	if args.get("parenttype") == "Material Request": return out
+
+	if not args.transaction_type:
+		args.transaction_type = "buying" if frappe.get_meta(args.parenttype).get_field("supplier") \
+			else "selling"
+
+	for item in args.get("item_list"):
+		args_copy = args.copy()
+		args_copy.update(item)
+		out.append(get_pricing_rule_for_item(args_copy))
+
+	return out
+
+def get_pricing_rule_for_item(args):
+	if args.get("parenttype") == "Material Request": return {}
+
+	item_details = frappe._dict({
+		"doctype": args.doctype,
+		"name": args.name,
+		"pricing_rule": None
+	})
+
+	if args.ignore_pricing_rule or not args.item_code:
+		return item_details
+
+	if not (args.item_group and args.brand):
+		args.item_group, args.brand = frappe.db.get_value("Item", args.item_code, ["item_group", "brand"])
+
+	if args.customer and not (args.customer_group and args.territory):
+		args.customer_group, args.territory = frappe.db.get_value("Customer", args.customer,
+			["customer_group", "territory"])
+	elif args.supplier and not args.supplier_type:
+		args.supplier_type = frappe.db.get_value("Supplier", args.supplier, "supplier_type")
+
+	pricing_rules = get_pricing_rules(args)
+	pricing_rule = filter_pricing_rules(args, pricing_rules)
+
+	if pricing_rule:
+		item_details.pricing_rule = pricing_rule.name
+		if pricing_rule.price_or_discount == "Price":
+			item_details.update({
+				"price_list_rate": pricing_rule.price/flt(args.conversion_rate) \
+					if args.conversion_rate else 0.0,
+				"discount_percentage": 0.0
+			})
+		else:
+			item_details.discount_percentage = pricing_rule.discount_percentage
+
+	return item_details
+
+def get_pricing_rules(args):
+	def _get_tree_conditions(parenttype, allow_blank=True):
+		field = frappe.scrub(parenttype)
+		condition = ""
+		if args.get(field):
+			lft, rgt = frappe.db.get_value(parenttype, args[field], ["lft", "rgt"])
+			parent_groups = frappe.db.sql_list("""select name from `tab%s`
+				where lft<=%s and rgt>=%s""" % (parenttype, '%s', '%s'), (lft, rgt))
+
+			if parent_groups:
+				if allow_blank: parent_groups.append('')
+				condition = " ifnull("+field+", '') in ('" + "', '".join(parent_groups)+"')"
+
+		return condition
+
+
+	conditions = ""
+	for field in ["company", "customer", "supplier", "supplier_type", "campaign", "sales_partner"]:
+		if args.get(field):
+			conditions += " and ifnull("+field+", '') in (%("+field+")s, '')"
+		else:
+			conditions += " and ifnull("+field+", '') = ''"
+
+	for parenttype in ["Customer Group", "Territory"]:
+		group_condition = _get_tree_conditions(parenttype)
+		if group_condition:
+			conditions += " and " + group_condition
+
+	conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
+
+	if args.get("transaction_date"):
+		conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01')
+			and ifnull(valid_upto, '2500-12-31')"""
+
+	return frappe.db.sql("""select * from `tabPricing Rule`
+		where (item_code=%(item_code)s or {item_group_condition} or brand=%(brand)s)
+			and docstatus < 2 and ifnull(disable, 0) = 0
+			and ifnull({transaction_type}, 0) = 1 {conditions}
+		order by priority desc, name desc""".format(
+			item_group_condition=_get_tree_conditions("Item Group", False),
+			transaction_type=args.transaction_type, conditions=conditions), args, as_dict=1)
+
+def filter_pricing_rules(args, pricing_rules):
+	# filter for qty
+	if pricing_rules and args.get("qty"):
+		pricing_rules = filter(lambda x: (args.qty>=flt(x.min_qty)
+			and (args.qty<=x.max_qty if x.max_qty else True)), pricing_rules)
+
+	# find pricing rule with highest priority
+	if pricing_rules:
+		max_priority = max([cint(p.priority) for p in pricing_rules])
+		if max_priority:
+			pricing_rules = filter(lambda x: cint(x.priority)==max_priority, pricing_rules)
+
+	# apply internal priority
+	all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
+		"supplier", "supplier_type", "campaign", "sales_partner"]
+
+	if len(pricing_rules) > 1:
+		for field_set in [["item_code", "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):
+					pricing_rules = apply_internal_priority(pricing_rules, field_set, args)
+					break
+
+	if len(pricing_rules) > 1:
+		price_or_discount = list(set([d.price_or_discount for d in pricing_rules]))
+		if len(price_or_discount) == 1 and price_or_discount[0] == "Discount Percentage":
+			pricing_rules = filter(lambda x: x.for_price_list==args.price_list, 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}")
+			.format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict)
+	elif pricing_rules:
+		return pricing_rules[0]
+
+def if_all_rules_same(pricing_rules, fields):
+	all_rules_same = True
+	val = [pricing_rules[0][k] for k in fields]
+	for p in pricing_rules[1:]:
+		if val != [p[k] for k in fields]:
+			all_rules_same = False
+			break
+
+	return all_rules_same
+
+def apply_internal_priority(pricing_rules, field_set, args):
+	filtered_rules = []
+	for field in field_set:
+		if args.get(field):
+			filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
+			if filtered_rules: break
+
+	return filtered_rules or pricing_rules
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index b17c995..e8496d0 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -17,6 +17,7 @@
 			"doctype": "Pricing Rule",
 			"apply_on": "Item Code",
 			"item_code": "_Test Item",
+			"selling": 1,
 			"price_or_discount": "Discount Percentage",
 			"price": 0,
 			"discount_percentage": 10,
@@ -29,13 +30,15 @@
 			"company": "_Test Company",
 			"price_list": "_Test Price List",
 			"currency": "_Test Currency",
-			"doctype": "Sales Order",
+			"parenttype": "Sales Order",
 			"conversion_rate": 1,
 			"price_list_currency": "_Test Currency",
 			"plc_conversion_rate": 1,
 			"order_type": "Sales",
 			"transaction_type": "selling",
 			"customer": "_Test Customer",
+			"doctype": "Sales Order Item",
+			"name": None
 		})
 		details = get_item_details(args)
 		self.assertEquals(details.get("discount_percentage"), 10)
@@ -71,7 +74,7 @@
 		self.assertEquals(details.get("discount_percentage"), 5)
 
 		frappe.db.sql("update `tabPricing Rule` set priority=NULL where campaign='_Test Campaign'")
-		from erpnext.stock.get_item_details import MultiplePricingRuleConflict
+		from erpnext.accounts.doctype.pricing_rule.pricing_rule	import MultiplePricingRuleConflict
 		self.assertRaises(MultiplePricingRuleConflict, get_item_details, args)
 
 		args.item_code = "_Test Item 2"
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 505a3ba..8eb3b09 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -232,6 +232,14 @@
    "read_only": 0
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -744,7 +752,7 @@
  "icon": "icon-file-text", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2014-06-04 08:45:25.582170", 
+ "modified": "2014-06-19 15:50:50.898237", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Invoice", 
@@ -823,6 +831,12 @@
    "role": "Auditor", 
    "submit": 0, 
    "write": 0
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Accounts Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 983f2bb..a07b69d 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -242,6 +242,14 @@
    "reqd": 1
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -1180,7 +1188,7 @@
  "icon": "icon-file-text", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2014-05-27 03:49:17.806077", 
+ "modified": "2014-06-19 16:01:19.720382", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Sales Invoice", 
@@ -1225,6 +1233,12 @@
    "read": 1, 
    "report": 1, 
    "role": "Customer"
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Accounts Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index d293683..794c041 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -198,6 +198,14 @@
    "print_hide": 1
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -636,7 +644,7 @@
  "icon": "icon-file-text", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2014-05-27 03:49:15.948363", 
+ "modified": "2014-06-19 15:58:06.375217", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Purchase Order", 
@@ -696,6 +704,12 @@
    "read": 1, 
    "report": 1, 
    "role": "Supplier"
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Purchase Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 91cc865..3a08124 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -187,12 +187,13 @@
 	def on_update(self):
 		pass
 
+def set_missing_values(source, target):
+	target.ignore_pricing_rule = 1
+	target.run_method("set_missing_values")
+	target.run_method("calculate_taxes_and_totals")
+
 @frappe.whitelist()
 def make_purchase_receipt(source_name, target_doc=None):
-	def set_missing_values(source, target):
-		target.run_method("set_missing_values")
-		target.run_method("calculate_taxes_and_totals")
-
 	def update_item(obj, target, source_parent):
 		target.qty = flt(obj.qty) - flt(obj.received_qty)
 		target.stock_qty = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.conversion_factor)
@@ -226,10 +227,6 @@
 
 @frappe.whitelist()
 def make_purchase_invoice(source_name, target_doc=None):
-	def set_missing_values(source, target):
-		target.run_method("set_missing_values")
-		target.run_method("calculate_taxes_and_totals")
-
 	def update_item(obj, target, source_parent):
 		target.amount = flt(obj.amount) - flt(obj.billed_amt)
 		target.base_amount = target.amount * flt(source_parent.conversion_rate)
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 19b0283..c3c5bf4 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -197,6 +197,14 @@
    "print_hide": 1
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -562,7 +570,7 @@
  "icon": "icon-shopping-cart", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2014-05-27 03:49:20.226683", 
+ "modified": "2014-06-19 15:54:27.919675", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Supplier Quotation", 
@@ -640,6 +648,12 @@
    "role": "Supplier", 
    "submit": 0, 
    "write": 0
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Purchase Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
index 74a37b3..2af7bb9 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
@@ -54,6 +54,7 @@
 @frappe.whitelist()
 def make_purchase_order(source_name, target_doc=None):
 	def set_missing_values(source, target):
+		target.ignore_pricing_rule = 1
 		target.run_method("set_missing_values")
 		target.run_method("get_schedule_dates")
 		target.run_method("calculate_taxes_and_totals")
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 3af8290..847e09e 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -89,14 +89,14 @@
 		"""set missing item values"""
 		from erpnext.stock.get_item_details import get_item_details
 		if hasattr(self, "fname"):
-			parent_dict = {"doctype": self.doctype}
+			parent_dict = {}
 			for fieldname in self.meta.get_valid_columns():
 				parent_dict[fieldname] = self.get(fieldname)
 
 			for item in self.get(self.fname):
 				if item.get("item_code"):
-					args = item.as_dict()
-					args.update(parent_dict)
+					args = parent_dict.copy()
+					args.update(item.as_dict())
 					ret = get_item_details(args)
 
 					for fieldname, value in ret.items():
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index dd57c60..041bbd3 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -62,3 +62,4 @@
 erpnext.patches.v4_0.create_price_list_if_missing
 execute:frappe.db.sql("update `tabItem` set end_of_life=null where end_of_life='0000-00-00'") #2014-06-16
 erpnext.patches.v4_0.update_users_report_view_settings
+erpnext.patches.v4_0.set_pricing_rule_for_buying_or_selling
diff --git a/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py b/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
new file mode 100644
index 0000000..8be846f
--- /dev/null
+++ b/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.reload_doc("accounts", "doctype", "pricing_rule")
+	frappe.db.sql("""update `tabPricing Rule` set selling=1 where ifnull(applicable_for, '') in
+		('', 'Customer', 'Customer Group', 'Territory', 'Sales Partner', 'Campaign')""")
+
+	frappe.db.sql("""update `tabPricing Rule` set buying=1 where ifnull(applicable_for, '') in
+		('', 'Supplier', 'Supplier Type')""")
diff --git a/erpnext/public/js/transaction.js b/erpnext/public/js/transaction.js
index 2c37204..ea576d5 100644
--- a/erpnext/public/js/transaction.js
+++ b/erpnext/public/js/transaction.js
@@ -116,8 +116,8 @@
 							barcode: item.barcode,
 							serial_no: item.serial_no,
 							warehouse: item.warehouse,
-							doctype: me.frm.doc.doctype,
-							docname: me.frm.doc.name,
+							parenttype: me.frm.doc.doctype,
+							parent: me.frm.doc.name,
 							customer: me.frm.doc.customer,
 							supplier: me.frm.doc.supplier,
 							currency: me.frm.doc.currency,
@@ -130,7 +130,10 @@
 							order_type: me.frm.doc.order_type,
 							is_pos: cint(me.frm.doc.is_pos),
 							is_subcontracted: me.frm.doc.is_subcontracted,
-							transaction_date: me.frm.doc.transaction_date
+							transaction_date: me.frm.doc.transaction_date,
+							ignore_pricing_rule: me.frm.doc.ignore_pricing_rule,
+							doctype: item.doctype,
+							name: item.name
 						}
 					},
 					callback: function(r) {
@@ -196,7 +199,7 @@
 			}
 
 			this.frm.script_manager.trigger("currency");
-			this.apply_pricing_rule()
+			this.apply_pricing_rule();
 		}
 	},
 
@@ -229,7 +232,12 @@
 				this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate);
 		}
 		if(flt(this.frm.doc.conversion_rate)>0.0) {
-			this.apply_pricing_rule();
+			if(this.frm.doc.ignore_pricing_rule) {
+				this.calculate_taxes_and_totals();
+			} else {
+				this.apply_pricing_rule();
+			}
+
 		}
 	},
 
@@ -283,12 +291,11 @@
 		}
 		if(this.frm.doc.price_list_currency === this.frm.doc.currency) {
 			this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate);
-			this.apply_pricing_rule();
 		}
 	},
 
 	qty: function(doc, cdt, cdn) {
-		this.apply_pricing_rule(frappe.get_doc(cdt, cdn));
+		this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true);
 	},
 
 	// tax rate
@@ -331,51 +338,71 @@
 		this.calculate_taxes_and_totals();
 	},
 
-	apply_pricing_rule: function(item) {
+	ignore_pricing_rule: function() {
+		this.apply_pricing_rule();
+	},
+
+	apply_pricing_rule: function(item, calculate_taxes_and_totals) {
 		var me = this;
-
-		var _apply_pricing_rule = function(item) {
-			return me.frm.call({
-				method: "erpnext.stock.get_item_details.apply_pricing_rule",
-				child: item,
-				args: {
-					args: {
-						item_code: item.item_code,
-						item_group: item.item_group,
-						brand: item.brand,
-						qty: item.qty,
-						customer: me.frm.doc.customer,
-						customer_group: me.frm.doc.customer_group,
-						territory: me.frm.doc.territory,
-						supplier: me.frm.doc.supplier,
-						supplier_type: me.frm.doc.supplier_type,
-						currency: me.frm.doc.currency,
-						conversion_rate: me.frm.doc.conversion_rate,
-						price_list: me.frm.doc.selling_price_list ||
-							 me.frm.doc.buying_price_list,
-						plc_conversion_rate: me.frm.doc.plc_conversion_rate,
-						company: me.frm.doc.company,
-						transaction_date: me.frm.doc.transaction_date || me.frm.doc.posting_date,
-						campaign: me.frm.doc.campaign,
-						sales_partner: me.frm.doc.sales_partner
-					}
-				},
-				callback: function(r) {
-					if(!r.exc) {
-						me.frm.script_manager.trigger("price_list_rate", item.doctype, item.name);
-					}
+		var item_list = this._get_item_list(item);
+		var args = {
+			"item_list": item_list,
+			"customer": me.frm.doc.customer,
+			"customer_group": me.frm.doc.customer_group,
+			"territory": me.frm.doc.territory,
+			"supplier": me.frm.doc.supplier,
+			"supplier_type": me.frm.doc.supplier_type,
+			"currency": me.frm.doc.currency,
+			"conversion_rate": me.frm.doc.conversion_rate,
+			"price_list": me.frm.doc.selling_price_list || me.frm.doc.buying_price_list,
+			"plc_conversion_rate": me.frm.doc.plc_conversion_rate,
+			"company": me.frm.doc.company,
+			"transaction_date": me.frm.doc.transaction_date || me.frm.doc.posting_date,
+			"campaign": me.frm.doc.campaign,
+			"sales_partner": me.frm.doc.sales_partner,
+			"ignore_pricing_rule": me.frm.doc.ignore_pricing_rule,
+			"parenttype": me.frm.doc.doctype,
+			"parent": me.frm.doc.name
+		};
+		return this.frm.call({
+			method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule",
+			args: {	args: args },
+			callback: function(r) {
+				if (!r.exc) {
+					$.each(r.message, function(i, d) {
+						$.each(d, function(k, v) {
+							if (["doctype", "name"].indexOf(k)===-1) {
+								frappe.model.set_value(d.doctype, d.name, k, v);
+							}
+						});
+					});
+					if(calculate_taxes_and_totals) me.calculate_taxes_and_totals();
 				}
+			}
+		});
+	},
+
+	_get_item_list: function(item) {
+		var item_list = [];
+		var append_item = function(d) {
+			item_list.push({
+				"doctype": d.doctype,
+				"name": d.name,
+				"item_code": d.item_code,
+				"item_group": d.item_group,
+				"brand": d.brand,
+				"qty": d.qty
 			});
-		}
+		};
 
-
-		if(item) {
-			_apply_pricing_rule(item);
+		if (item) {
+			append_item(item);
 		} else {
-			$.each(this.get_item_doclist(), function(n, item) {
-				_apply_pricing_rule(item);
+			$.each(this.get_item_doclist(), function(i, d) {
+				append_item(d);
 			});
 		}
+		return item_list;
 	},
 
 	included_in_print_rate: function(doc, cdt, cdn) {
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 0221738..1ae0adb 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -275,6 +275,14 @@
    "reqd": 1
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -818,7 +826,7 @@
  "idx": 1, 
  "is_submittable": 1, 
  "max_attachments": 1, 
- "modified": "2014-05-27 03:49:16.670976", 
+ "modified": "2014-06-19 15:59:30.019826", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Quotation", 
@@ -896,6 +904,12 @@
    "role": "Maintenance User", 
    "submit": 1, 
    "write": 1
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Sales Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 62577db..f396191 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -102,7 +102,7 @@
 		if customer:
 			target.customer = customer.name
 			target.customer_name = customer.customer_name
-
+		target.ignore_pricing_rule = 1
 		target.ignore_permissions = ignore_permissions
 		target.run_method("set_missing_values")
 		target.run_method("calculate_taxes_and_totals")
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index c899227..a036370 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -286,6 +286,14 @@
    "reqd": 1
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -874,7 +882,7 @@
  "idx": 1, 
  "is_submittable": 1, 
  "issingle": 0, 
- "modified": "2014-05-27 08:39:19.027965", 
+ "modified": "2014-06-19 16:00:06.626037", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Order", 
@@ -953,6 +961,12 @@
    "read": 1, 
    "report": 1, 
    "role": "Material User"
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Sales Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 24da577..c14612b 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -245,9 +245,6 @@
 	def get_portal_page(self):
 		return "order" if self.docstatus==1 else None
 
-def set_missing_values(source, target):
-	target.run_method("set_missing_values")
-	target.run_method("calculate_taxes_and_totals")
 
 @frappe.whitelist()
 def make_material_request(source_name, target_doc=None):
@@ -274,6 +271,11 @@
 
 @frappe.whitelist()
 def make_delivery_note(source_name, target_doc=None):
+	def set_missing_values(source, target):
+		target.ignore_pricing_rule = 1
+		target.run_method("set_missing_values")
+		target.run_method("calculate_taxes_and_totals")
+
 	def update_item(source, target, source_parent):
 		target.base_amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.base_rate)
 		target.amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.rate)
@@ -312,6 +314,7 @@
 def make_sales_invoice(source_name, target_doc=None):
 	def set_missing_values(source, target):
 		target.is_pos = 0
+		target.ignore_pricing_rule = 1
 		target.run_method("set_missing_values")
 		target.run_method("calculate_taxes_and_totals")
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 9b13b10..690fd05 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -276,6 +276,14 @@
    "reqd": 1
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -999,7 +1007,7 @@
  "idx": 1, 
  "in_create": 0, 
  "is_submittable": 1, 
- "modified": "2014-05-27 03:49:09.721622", 
+ "modified": "2014-06-19 16:00:47.326127", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Delivery Note", 
@@ -1073,6 +1081,12 @@
    "read": 1, 
    "report": 1, 
    "role": "Customer"
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Material Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index bbc9f81..4b147cc 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -280,6 +280,7 @@
 
 	def update_accounts(source, target):
 		target.is_pos = 0
+		target.ignore_pricing_rule = 1
 		target.run_method("set_missing_values")
 
 		if len(target.get("entries")) == 0:
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 506e5d0..7ab93eb 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -17,7 +17,7 @@
 		item.is_stock_item = "Yes"
 		item.default_warehouse = None
 		self.assertRaises(WarehouseNotSet, item.insert)
-		
+
 	def test_get_item_details(self):
 		from erpnext.stock.get_item_details import get_item_details
 		to_check = {
@@ -41,23 +41,23 @@
 			"uom": "_Test UOM",
 			"conversion_factor": 1.0,
 		}
-		
+
 		make_test_records("Item Price")
-				
+
 		details = get_item_details({
 			"item_code": "_Test Item",
 			"company": "_Test Company",
 			"price_list": "_Test Price List",
 			"currency": "_Test Currency",
-			"doctype": "Sales Order",
+			"parenttype": "Sales Order",
 			"conversion_rate": 1,
 			"price_list_currency": "_Test Currency",
 			"plc_conversion_rate": 1,
 			"order_type": "Sales",
 			"transaction_type": "selling"
 		})
-		
+
 		for key, value in to_check.iteritems():
 			self.assertEquals(value, details.get(key))
 
-test_records = frappe.get_test_records('Item')
\ No newline at end of file
+test_records = frappe.get_test_records('Item')
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index e585bef..ae748ce 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -196,6 +196,14 @@
    "print_hide": 1
   }, 
   {
+   "fieldname": "ignore_pricing_rule", 
+   "fieldtype": "Check", 
+   "label": "Ignore Pricing Rule", 
+   "no_copy": 1, 
+   "permlevel": 1, 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "items", 
    "fieldtype": "Section Break", 
    "label": "Items", 
@@ -754,7 +762,7 @@
  "icon": "icon-truck", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2014-05-27 03:49:16.302198", 
+ "modified": "2014-06-19 15:58:37.932064", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Purchase Receipt", 
@@ -821,6 +829,12 @@
    "read": 1, 
    "report": 1, 
    "role": "Supplier"
+  }, 
+  {
+   "permlevel": 1, 
+   "read": 1, 
+   "role": "Material Manager", 
+   "write": 1
   }
  ], 
  "read_only_onload": 1, 
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 13bb193..71c07eb 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -287,6 +287,7 @@
 			frappe.throw(_("All items have already been invoiced"))
 
 		doc = frappe.get_doc(target)
+		doc.ignore_pricing_rule = 1
 		doc.run_method("set_missing_values")
 		doc.run_method("calculate_taxes_and_totals")
 
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index c5c1280..fe320d1 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -6,8 +6,7 @@
 from frappe import _, throw
 from frappe.utils import flt, cint, add_days
 import json
-
-class MultiplePricingRuleConflict(frappe.ValidationError): pass
+from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item
 
 @frappe.whitelist()
 def get_item_details(args):
@@ -20,14 +19,15 @@
 			"selling_price_list": None,
 			"price_list_currency": None,
 			"plc_conversion_rate": 1.0,
-			"doctype": "",
-			"docname": "",
+			"parenttype": "",
+			"parent": "",
 			"supplier": None,
 			"transaction_date": None,
 			"conversion_rate": 1.0,
 			"buying_price_list": None,
 			"is_subcontracted": "Yes" / "No",
-			"transaction_type": "selling"
+			"transaction_type": "selling",
+			"ignore_pricing_rule": 0/1
 		}
 	"""
 
@@ -37,7 +37,8 @@
 	args = frappe._dict(args)
 
 	if not args.get("transaction_type"):
-		if args.get("doctype")=="Material Request" or frappe.get_meta(args.get("doctype")).get_field("supplier"):
+		if args.get("parenttype")=="Material Request" or \
+				frappe.get_meta(args.get("parenttype")).get_field("supplier"):
 			args.transaction_type = "buying"
 		else:
 			args.transaction_type = "selling"
@@ -73,9 +74,9 @@
 		if args.get(key) is None:
 			args[key] = value
 
-	out.update(apply_pricing_rule(args))
+	out.update(get_pricing_rule_for_item(args))
 
-	if args.get("doctype") in ("Sales Invoice", "Delivery Note"):
+	if args.get("parenttype") in ("Sales Invoice", "Delivery Note"):
 		if item_doc.has_serial_no == "Yes" and not args.serial_no:
 			out.serial_no = get_serial_nos_by_fifo(args, item_doc)
 
@@ -113,7 +114,7 @@
 		elif item.is_sales_item != "Yes":
 			throw(_("Item {0} must be a Sales Item").format(item.name))
 
-	elif args.transaction_type == "buying" and args.doctype != "Material Request":
+	elif args.transaction_type == "buying" and args.parenttype != "Material Request":
 		# validate if purchase item or subcontracted item
 		if item.is_purchase_item != "Yes":
 			throw(_("Item {0} must be a Purchase Item").format(item.name))
@@ -144,7 +145,7 @@
 		"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in
 			item_doc.get("item_tax")))),
 		"uom": item.stock_uom,
-		"min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "",
+		"min_order_qty": flt(item.min_order_qty) if args.parenttype == "Material Request" else "",
 		"conversion_factor": 1.0,
 		"qty": 1.0,
 		"price_list_rate": 0.0,
@@ -162,7 +163,7 @@
 	return out
 
 def get_price_list_rate(args, item_doc, out):
-	meta = frappe.get_meta(args.doctype)
+	meta = frappe.get_meta(args.parenttype)
 
 	if meta.get_field("currency"):
 		validate_price_list(args)
@@ -179,7 +180,7 @@
 		if not out.price_list_rate and args.transaction_type == "buying":
 			from erpnext.stock.doctype.item.item import get_last_purchase_details
 			out.update(get_last_purchase_details(item_doc.name,
-				args.docname, args.conversion_rate))
+				args.parent, args.conversion_rate))
 
 def validate_price_list(args):
 	if args.get("price_list"):
@@ -248,142 +249,6 @@
 
 	return pos_settings and pos_settings[0] or None
 
-@frappe.whitelist()
-def apply_pricing_rule(args):
-	if isinstance(args, basestring):
-		args = json.loads(args)
-
-	args = frappe._dict(args)
-	out = frappe._dict()
-	if args.get("doctype") == "Material Request" or not args.get("item_code"): return out
-
-	if not args.get("item_group") or not args.get("brand"):
-		args.item_group, args.brand = frappe.db.get_value("Item",
-			args.item_code, ["item_group", "brand"])
-
-	if args.get("customer") and (not args.get("customer_group") or not args.get("territory")):
-		args.customer_group, args.territory = frappe.db.get_value("Customer",
-			args.customer, ["customer_group", "territory"])
-
-	if args.get("supplier") and not args.get("supplier_type"):
-		args.supplier_type = frappe.db.get_value("Supplier", args.supplier, "supplier_type")
-
-	pricing_rules = get_pricing_rules(args)
-
-	pricing_rule = filter_pricing_rules(args, pricing_rules)
-
-	if pricing_rule:
-		out.pricing_rule = pricing_rule.name
-		if pricing_rule.price_or_discount == "Price":
-			out.base_price_list_rate = pricing_rule.price
-			out.price_list_rate = pricing_rule.price*flt(args.plc_conversion_rate)/flt(args.conversion_rate)
-			out.base_rate = out.base_price_list_rate
-			out.rate = out.price_list_rate
-			out.discount_percentage = 0.0
-		else:
-			out.discount_percentage = pricing_rule.discount_percentage
-	else:
-		out.pricing_rule = None
-
-	return out
-
-
-def get_pricing_rules(args):
-	def _get_tree_conditions(doctype, allow_blank=True):
-		field = frappe.scrub(doctype)
-		condition = ""
-		if args.get(field):
-			lft, rgt = frappe.db.get_value(doctype, args[field], ["lft", "rgt"])
-			parent_groups = frappe.db.sql_list("""select name from `tab%s`
-				where lft<=%s and rgt>=%s""" % (doctype, '%s', '%s'), (lft, rgt))
-
-			if parent_groups:
-				if allow_blank: parent_groups.append('')
-				condition = " ifnull("+field+", '') in ('" + "', '".join(parent_groups)+"')"
-
-		return condition
-
-
-	conditions = ""
-	for field in ["company", "customer", "supplier", "supplier_type", "campaign", "sales_partner"]:
-			if args.get(field):
-				conditions += " and ifnull("+field+", '') in (%("+field+")s, '')"
-			else:
-				conditions += " and ifnull("+field+", '') = ''"
-
-	for doctype in ["Customer Group", "Territory"]:
-		group_condition = _get_tree_conditions(doctype)
-		if group_condition:
-			conditions += " and " + group_condition
-
-	conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
-
-	if args.get("transaction_date"):
-		conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01')
-			and ifnull(valid_upto, '2500-12-31')"""
-
-	return frappe.db.sql("""select * from `tabPricing Rule`
-		where (item_code=%(item_code)s or {item_group_condition} or brand=%(brand)s)
-			and docstatus < 2 and ifnull(disable, 0) = 0 {conditions}
-		order by priority desc, name desc""".format(
-			item_group_condition=_get_tree_conditions("Item Group", False), conditions=conditions),
-			args, as_dict=1)
-
-def filter_pricing_rules(args, pricing_rules):
-	# filter for qty
-	if pricing_rules and args.get("qty"):
-		pricing_rules = filter(lambda x: (args.qty>=flt(x.min_qty)
-			and (args.qty<=x.max_qty if x.max_qty else True)), pricing_rules)
-
-	# find pricing rule with highest priority
-	if pricing_rules:
-		max_priority = max([cint(p.priority) for p in pricing_rules])
-		if max_priority:
-			pricing_rules = filter(lambda x: cint(x.priority)==max_priority, pricing_rules)
-
-	# apply internal priority
-	all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
-		"supplier", "supplier_type", "campaign", "sales_partner"]
-
-	if len(pricing_rules) > 1:
-		for field_set in [["item_code", "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):
-					pricing_rules = apply_internal_priority(pricing_rules, field_set, args)
-					break
-
-	if len(pricing_rules) > 1:
-		price_or_discount = list(set([d.price_or_discount for d in pricing_rules]))
-		if len(price_or_discount) == 1 and price_or_discount[0] == "Discount Percentage":
-			pricing_rules = filter(lambda x: x.for_price_list==args.price_list, 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}")
-			.format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict)
-	elif pricing_rules:
-		return pricing_rules[0]
-
-def if_all_rules_same(pricing_rules, fields):
-	all_rules_same = True
-	val = [pricing_rules[0][k] for k in fields]
-	for p in pricing_rules[1:]:
-		if val != [p[k] for k in fields]:
-			all_rules_same = False
-			break
-
-	return all_rules_same
-
-def apply_internal_priority(pricing_rules, field_set, args):
-	filtered_rules = []
-	for field in field_set:
-		if args.get(field):
-			filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
-			if filtered_rules: break
-
-	return filtered_rules or pricing_rules
 
 def get_serial_nos_by_fifo(args, item_doc):
 	return "\n".join(frappe.db.sql_list("""select name from `tabSerial No`