Apply Tax Rule based on Customer Selection in Sales / Purchase Transactions
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json
index 656d29c..5c25517 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json
@@ -153,5 +153,65 @@
     "territory": "_Test Territory Rest Of The World"
    }
   ]
+ },
+ {
+  "company": "_Test Company",
+  "doctype": "Sales Taxes and Charges Template",
+  "taxes": [
+   {
+    "account_head": "_Test Account VAT - _TC",
+    "charge_type": "On Net Total",
+    "description": "VAT",
+    "doctype": "Sales Taxes and Charges",
+    "parentfield": "taxes",
+    "rate": 12
+   },
+   {
+    "account_head": "_Test Account Service Tax - _TC",
+    "charge_type": "On Net Total",
+    "description": "Service Tax",
+    "doctype": "Sales Taxes and Charges",
+    "parentfield": "taxes",
+    "rate": 4
+   }
+  ],
+  "title": "_Test Sales Taxes and Charges Template 1",
+  "territories": [
+   {
+    "doctype": "Applicable Territory",
+    "parentfield": "territories",
+    "territory": "_Test Territory Rest Of The World"
+   }
+  ]
+ },
+ {
+  "company": "_Test Company",
+  "doctype": "Sales Taxes and Charges Template",
+  "taxes": [
+   {
+    "account_head": "_Test Account VAT - _TC",
+    "charge_type": "On Net Total",
+    "description": "VAT",
+    "doctype": "Sales Taxes and Charges",
+    "parentfield": "taxes",
+    "rate": 12
+   },
+   {
+    "account_head": "_Test Account Service Tax - _TC",
+    "charge_type": "On Net Total",
+    "description": "Service Tax",
+    "doctype": "Sales Taxes and Charges",
+    "parentfield": "taxes",
+    "rate": 4
+   }
+  ],
+  "title": "_Test Sales Taxes and Charges Template 2",
+  "territories": [
+   {
+    "doctype": "Applicable Territory",
+    "parentfield": "territories",
+    "territory": "_Test Territory Rest Of The World"
+   }
+  ]
  }
 ]
diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.js b/erpnext/accounts/doctype/tax_rule/tax_rule.js
index b922178..d4a10aa 100644
--- a/erpnext/accounts/doctype/tax_rule/tax_rule.js
+++ b/erpnext/accounts/doctype/tax_rule/tax_rule.js
@@ -2,6 +2,41 @@
 // License: GNU General Public License v3. See license.txt
 
 cur_frm.add_fetch("customer", "customer_group", "customer_group" );
+cur_frm.add_fetch("supplier", "supplier_type", "supplier_type" );
 
-this.frm.toggle_reqd("sales_tax_template", this.frm.doc.tax_type=="Sales");
-this.frm.toggle_reqd("purchase_tax_template", this.frm.doc.tax_type=="Purchase");
\ No newline at end of file
+cur_frm.toggle_reqd("sales_tax_template", cur_frm.doc.tax_type=="Sales");
+cur_frm.toggle_reqd("purchase_tax_template", cur_frm.doc.tax_type=="Purchase");
+
+frappe.ui.form.on("Tax Rule", "customer", function(frm) {
+	frappe.call({
+		method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
+		args: {
+			"party": frm.doc.customer,
+			"party_type": "customer"
+		},
+		callback: function(r) {
+			if(!r.exc) {
+				$.each(r.message, function(k, v) {
+					frm.set_value(k, v);
+				});
+			}
+		}
+	});
+});
+
+frappe.ui.form.on("Tax Rule", "supplier", function(frm) {
+	frappe.call({
+		method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
+		args: {
+			"party": frm.doc.supplier,
+			"party_type": "supplier"
+		},
+		callback: function(r) {
+			if(!r.exc) {
+				$.each(r.message, function(k, v) {
+					frm.set_value(k, v);
+				});
+			}
+		}
+	});
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json
index f2df654..52ca63f 100644
--- a/erpnext/accounts/doctype/tax_rule/tax_rule.json
+++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json
@@ -7,10 +7,95 @@
  "custom": 0, 
  "docstatus": 0, 
  "doctype": "DocType", 
- "document_type": "Master", 
+ "document_type": "Setup", 
  "fields": [
   {
    "allow_on_submit": 0, 
+   "default": "Sales", 
+   "fieldname": "tax_type", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 1, 
+   "label": "Tax Type", 
+   "no_copy": 0, 
+   "options": "Sales\nPurchase", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "fieldname": "column_break_1", 
+   "fieldtype": "Column Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "depends_on": "eval:doc.tax_type==\"Sales\"", 
+   "fieldname": "sales_tax_template", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Sales Tax Template", 
+   "no_copy": 0, 
+   "options": "Sales Taxes and Charges Template", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "depends_on": "eval:doc.tax_type==\"Purchase\"", 
+   "fieldname": "purchase_tax_template", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Purchase Tax Template", 
+   "no_copy": 0, 
+   "options": "Purchase Taxes and Charges Template", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
    "fieldname": "filters", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -31,6 +116,7 @@
   }, 
   {
    "allow_on_submit": 0, 
+   "depends_on": "eval:doc.tax_type==\"Sales\"", 
    "fieldname": "customer", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -52,6 +138,28 @@
   }, 
   {
    "allow_on_submit": 0, 
+   "depends_on": "eval:doc.tax_type==\"Purchase\"", 
+   "fieldname": "supplier", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Supplier", 
+   "no_copy": 0, 
+   "options": "Supplier", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
    "fieldname": "billing_city", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -112,6 +220,7 @@
   }, 
   {
    "allow_on_submit": 0, 
+   "depends_on": "eval:doc.tax_type==\"Sales\"", 
    "fieldname": "customer_group", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -133,6 +242,28 @@
   }, 
   {
    "allow_on_submit": 0, 
+   "depends_on": "eval:doc.tax_type==\"Purchase\"", 
+   "fieldname": "supplier_type", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Supplier Type", 
+   "no_copy": 0, 
+   "options": "Supplier Type", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
    "fieldname": "shipping_city", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -253,109 +384,6 @@
   }, 
   {
    "allow_on_submit": 0, 
-   "fieldname": "section_break_7", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "fieldname": "tax_type", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Tax Type", 
-   "no_copy": 0, 
-   "options": "\nSales\nPurchase", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "fieldname": "column_break_9", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "depends_on": "eval: doc.tax_type == \"Sales\"", 
-   "fieldname": "sales_tax_template", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Sales Tax Template", 
-   "no_copy": 0, 
-   "options": "Sales Taxes and Charges Template", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "depends_on": "eval: doc.tax_type == \"Purchase\"", 
-   "fieldname": "purchase_tax_template", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Purchase Tax Template", 
-   "no_copy": 0, 
-   "options": "Purchase Taxes and Charges Template", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
    "fieldname": "section_break_6", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -442,7 +470,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
- "modified": "2015-08-14 08:10:56.694925", 
+ "modified": "2015-08-21 03:27:43.564183", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Tax Rule", 
diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py
index d1b0bdc..635bdc1 100644
--- a/erpnext/accounts/doctype/tax_rule/tax_rule.py
+++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py
@@ -6,43 +6,56 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
+from frappe.utils import cstr
 
 class IncorrectCustomerGroup(frappe.ValidationError): pass
+class IncorrectSupplierType(frappe.ValidationError): pass
+class ConflictingTaxRule(frappe.ValidationError): pass
 
 class TaxRule(Document):
 	def validate(self):
 		self.validate_tax_template()
 		self.validate_customer_group()
+		self.validate_supplier_type()
 		self.validate_date()
 		self.validate_filters()
-		
+
 	def validate_tax_template(self):
+		if self.tax_type== "Sales":
+			self.purchase_tax_template = self.supplier = self.supplier_type= None
+		else:
+			self.sales_tax_template= self.customer = self.customer_group= None
+		
 		if not (self.sales_tax_template or self.purchase_tax_template):
 			frappe.throw(_("Tax Template is mandatory."))
-		if self.tax_type=="Sales":
-			self.purchase_tax_template= None
-		else:
-			self.sales_tax_template= None
 
 	def validate_customer_group(self):
 		if self.customer and self.customer_group:
 			if not frappe.db.get_value("Customer", self.customer, "customer_group") == self.customer_group:
 				frappe.throw(_("Customer {0} does not belong to customer group {1}"). \
 					format(self.customer, self.customer_group), IncorrectCustomerGroup)
-				
+	
+	def validate_supplier_type(self):
+		if self.supplier and self.supplier_type:
+			if not frappe.db.get_value("Supplier", self.supplier, "supplier_type") == self.supplier_type:
+				frappe.throw(_("Supplier {0} does not belong to Supplier Type {1}"). \
+					format(self.supplier, self.supplier_type), IncorrectSupplierType)
+
 	def validate_date(self):
 		if self.from_date and self.to_date and self.from_date > self.to_date:
 			frappe.throw(_("From Date cannot be greater than To Date"))
 
 	def validate_filters(self):
 		filters = {
+			"tax_type":			self.tax_type,
 			"customer": 		self.customer,
 			"customer_group": 	self.customer_group,
+			"supplier":			self.supplier,
+			"supplier_type":	self.supplier_type,
 			"billing_city":		self.billing_city,
 			"billing_country":	self.billing_country,
 			"shipping_city":	self.shipping_city,
 			"shipping_country":	self.shipping_country,
-			"tax_type":			self.tax_type,
 			"company":			self.company
 		}
 		
@@ -50,16 +63,58 @@
 		for d in filters:
 			if conds:
 				conds += " and "
-			conds += """{0} = '{1}'""".format(d, filters[d])
-			
-		conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or
-				(to_date > '{from_date}' and to_date < '{to_date}') or
-				('{from_date}' > from_date and '{from_date}' < to_date) or
-				('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date)
+			conds += """ifnull({0}, '') = '{1}'""".format(d, frappe.db.escape(cstr(filters[d])))
+		
+		if self.from_date and self.to_date:
+			conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or
+					(to_date > '{from_date}' and to_date < '{to_date}') or
+					('{from_date}' > from_date and '{from_date}' < to_date) or
+					('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date)
+					
+		elif self.from_date and not self.to_date:
+			conds += """ and to_date > '{from_date}'""".format(from_date = self.from_date)
+
+		elif self.to_date and not self.from_date:
+			conds += """ and from_date < '{to_date}'""".format(to_date = self.to_date)
 		
 		tax_rule = frappe.db.sql("select name, priority \
 			from `tabTax Rule` where {0} and name != '{1}'".format(conds, self.name), as_dict=1) 
 		
 		if tax_rule:
 			if tax_rule[0].priority == self.priority:
-				frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)))
\ No newline at end of file
+				frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule)
+
+@frappe.whitelist()
+def get_party_details(party, party_type):
+	out = {}
+	billing_address = frappe.get_list("Address", fields=["city", "country"], filters={party_type: party, "is_primary_address": 1})
+	shipping_address = frappe.get_list("Address", fields=["city", "country"], filters={party_type:party, "is_shipping_address": 1})
+	if billing_address:
+		out["billing_city"]= billing_address[0].city
+		out["billing_country"]= billing_address[0].country
+	if shipping_address:
+		out["shipping_city"]= shipping_address[0].city
+		out["shipping_country"]= shipping_address[0].country
+	return out
+
+def get_tax_template(posting_date, args):
+	"""Get matching tax rule"""
+	args = frappe._dict(args)
+	conditions = []
+
+	for key, value in args.iteritems():
+		conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value))))
+
+	matching = frappe.db.sql("""select * from `tabTax Rule`
+		where {0}""".format(" and ".join(conditions)), as_dict = True)
+		
+	if not matching:
+		return None
+		
+	for rule in matching:
+		rule.no_of_keys_matched = 0
+		for key in args:
+			if rule.get(key): rule.no_of_keys_matched += 1
+			
+	rule = sorted(matching, lambda b, a: cmp(a.no_of_keys_matched, b.no_of_keys_matched) or cmp(a.priority, b.priority))[0]
+	return rule.sales_tax_template or rule.purchase_tax_template
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py
index 7a2c6ef..873a4e3 100644
--- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py
+++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py
@@ -5,39 +5,127 @@
 
 import frappe
 import unittest
-from frappe.utils import nowdate, add_days
-from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup
+from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template
 
 # test_records = frappe.get_test_records('Tax Rule')
 
 class TestTaxRule(unittest.TestCase):
+	def setUp(self):
+		frappe.db.sql("delete from `tabTax Rule`")
+		
 	def test_customer_group(self):
-		tax_rule = make_tax_rule_test_record(customer_group= "_Test Customer Group 1", do_not_save= True)
+		tax_rule = make_tax_rule(customer= "_Test Customer", customer_group= "_Test Customer Group 1",
+			sales_tax_template = "_Test Sales Taxes and Charges Template")
 		self.assertRaises(IncorrectCustomerGroup, tax_rule.save)
 		
-	def test_tax_template(self):
-		tax_rule = make_tax_rule_test_record()
-		self.assertEquals(tax_rule.purchase_tax_template, None)
+	def test_supplier_type(self):
+		tax_rule = make_tax_rule(supplier= "_Test Supplier", supplier_type= "_Test Supplier Type 1",
+			purchase_tax_template = "_Test Purchase Taxes and Charges Template")
+		self.assertRaises(IncorrectSupplierType, tax_rule.save)
+		
+	def test_conflict(self):		
+		tax_rule1 = make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
+		tax_rule1.save()
 
-def make_tax_rule_test_record(**args):
+		tax_rule2 = make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
+		
+		self.assertRaises(ConflictingTaxRule, tax_rule2.save)
+
+	def test_conflict_with_non_overlapping_dates(self):
+		tax_rule1 = make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
+		tax_rule1.save()
+
+		tax_rule2 = make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, to_date = "2013-01-01")
+		
+		tax_rule2.save()
+		self.assertTrue(tax_rule2.name)
+
+	def test_conflict_with_overlapping_dates(self):		
+		tax_rule1 = make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
+		tax_rule1.save()
+
+		tax_rule2 = make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
+		
+		self.assertRaises(ConflictingTaxRule, tax_rule2.save)
+		
+	def test_tax_template(self):
+		tax_rule = make_tax_rule()
+		self.assertEquals(tax_rule.purchase_tax_template, None)
+		
+		
+	def test_select_tax_rule_based_on_customer(self):
+		make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
+
+		make_tax_rule(customer= "_Test Customer 1",
+			sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
+
+		make_tax_rule(customer= "_Test Customer 2",
+			sales_tax_template = "_Test Sales Taxes and Charges Template 2", save=1)
+			
+		self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}), 
+			"_Test Sales Taxes and Charges Template 2")
+
+	def test_select_tax_rule_based_on_better_match(self):
+		make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
+
+		make_tax_rule(customer= "_Test Customer",
+			sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
+			
+		self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}), 
+			"_Test Sales Taxes and Charges Template")
+
+	def test_select_tax_rule_based_on_better_priority(self):
+		make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", priority=1, save=1)
+
+		make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
+			sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
+			
+		self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}), 
+			"_Test Sales Taxes and Charges Template 1")
+
+	def test_select_tax_rule_based_cross_matching_keys(self):
+		make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
+
+		make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1",
+			sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
+			
+		self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}), 
+			None)
+
+	def test_select_tax_rule_based_cross_partially_keys(self):
+		make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
+			sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
+
+		make_tax_rule(billing_city = "Test City 1",
+			sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
+			
+		self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}), 
+			"_Test Sales Taxes and Charges Template 1")
+		
+
+def make_tax_rule(**args):
 	args = frappe._dict(args)
 	
 	tax_rule = frappe.new_doc("Tax Rule")
-	tax_rule.customer= args.customer or "_Test Customer"
-	tax_rule.customer_group= args.customer_group or "_Test Customer Group"
-	tax_rule.billing_city= args.billing_city or "_Test City"
-	tax_rule.billing_country= args.billing_country or "_Test Country"
-	tax_rule.shipping_city= args.shipping_city or "_Test City"
-	tax_rule.shipping_country= args.shipping_country or "_Test Country"
-	tax_rule.from_date= args.from_date or nowdate()
-	tax_rule.to_date= args.to_date or add_days(nowdate(), 1)
-	tax_rule.tax_type= args.tax_type or "Sales"
-	tax_rule.sales_tax_template= args.sales_tax_template or "_Test Sales Taxes and Charges Template"
-	tax_rule.purchase_tax_template= args.purchase_tax_template or "_Test Purchase Taxes and Charges Template"
-	tax_rule.priority= args.priority or 1
-	tax_rule.compant= args.company or "_Test Company"
 	
-	if not args.do_not_save:
-		tax_rule.save()
+	for key, val in args.iteritems():
+		if key != "save":
+			tax_rule.set(key, val)
+	
+	tax_rule.company = args.company or "_Test Company"
+	
+	if args.save:
+		tax_rule.insert()
+	
 	return tax_rule
 	
\ No newline at end of file
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 4f49bc0..313544f 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -43,6 +43,7 @@
 	set_contact_details(out, party, party_type)
 	set_other_values(out, party, party_type)
 	set_price_list(out, party, party_type, price_list)
+	out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out)
 
 	if not out.get("currency"):
 		out["currency"] = currency
@@ -99,7 +100,7 @@
 		out[f] = party.get(f)
 
 	# fields prepended with default in Customer doctype
-	for f in ['currency', 'taxes_and_charges'] \
+	for f in ['currency'] \
 		+ (['sales_partner', 'commission_rate'] if party_type=="Customer" else []):
 		if party.get("default_" + f):
 			out[f] = party.get("default_" + f)
@@ -274,4 +275,21 @@
 				msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)")
 					.format(date_diff(due_date, default_due_date)))
 			else:
-				frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
\ No newline at end of file
+				frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
+				
+def set_taxes(party, party_type, posting_date, company, out):
+	print "posting_date", posting_date
+	from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
+	args = {
+		party_type: 		party,
+		"customer_group":	out.customer_group,
+		"supplier_type":	out.supplier_type,
+		"company":			company
+	}
+	args.update(get_party_details(party, party_type))
+	if party_type=="Customer":
+		args.update({"tax_type": "Sales"})
+	else:
+		args.update({"tax_type": "Purchase"})
+		
+	return get_tax_template(posting_date, args)
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json
index 2a0a50d..ce68370 100644
--- a/erpnext/buying/doctype/supplier/supplier.json
+++ b/erpnext/buying/doctype/supplier/supplier.json
@@ -1,4 +1,5 @@
 {
+<<<<<<< HEAD
  "allow_copy": 0,
  "allow_import": 1,
  "allow_rename": 1,
diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js
index 919225f..59992eb 100644
--- a/erpnext/public/js/utils/party.js
+++ b/erpnext/public/js/utils/party.js
@@ -20,6 +20,7 @@
 				price_list: frm.doc.buying_price_list
 			};
 		}
+		args.posting_date = frm.doc.transaction_date;
 	}
 	if(!args) return;