feat: Item Taxes based on net rate
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index d1dcdc2..6f51053 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -436,18 +436,22 @@
 	return itemwise_barcode
 
 @frappe.whitelist()
-def get_item_tax_info(company, tax_category, item_codes):
+def get_item_tax_info(company, tax_category, item_codes, item_rates=None):
 	out = {}
 	if isinstance(item_codes, string_types):
 		item_codes = json.loads(item_codes)
 
+	if isinstance(item_rates, string_types):
+		item_rates = json.loads(item_rates)
+
 	for item_code in item_codes:
-		if not item_code or item_code in out:
+		if not item_code or item_code[1] in out:
 			continue
-		out[item_code] = {}
-		item = frappe.get_cached_doc("Item", item_code)
-		get_item_tax_template({"company": company, "tax_category": tax_category}, item, out[item_code])
-		out[item_code]["item_tax_rate"] = get_item_tax_map(company, out[item_code].get("item_tax_template"), as_json=True)
+		out[item_code[1]] = {}
+		item = frappe.get_cached_doc("Item", item_code[0])
+		args = {"company": company, "tax_category": tax_category, "net_rate": item_rates[item_code[1]]}
+		get_item_tax_template(args, item, out[item_code[1]])
+		out[item_code[1]]["item_tax_rate"] = get_item_tax_map(company, out[item_code[1]].get("item_tax_template"), as_json=True)
 
 	return out
 
@@ -478,12 +482,13 @@
 
 	for tax in taxes:
 		tax_company = frappe.get_value("Item Tax Template", tax.item_tax_template, 'company')
-		if tax.valid_from and tax_company == args['company']:
+		if (tax.valid_from or tax.maximum_net_rate) and tax_company == args['company']:
 			# In purchase Invoice first preference will be given to supplier invoice date
 			# if supplier date is not present then posting date
 			validation_date = args.get('transaction_date') or args.get('bill_date') or args.get('posting_date')
 
-			if getdate(tax.valid_from) <= getdate(validation_date):
+			if getdate(tax.valid_from) <= getdate(validation_date) \
+				and is_within_valid_range(args, tax):
 				taxes_with_validity.append(tax)
 		else:
 			if tax_company == args['company']:
@@ -502,12 +507,25 @@
 	if not taxes_with_validity and (not taxes_with_no_validity):
 		return None
 
+	# do not change if already a valid template
+	if args.get('item_tax_template') in taxes:
+		return arg.get('item_tax_template')
+
 	for tax in taxes:
 		if cstr(tax.tax_category) == cstr(args.get("tax_category")):
 			out["item_tax_template"] = tax.item_tax_template
 			return tax.item_tax_template
 	return None
 
+def is_within_valid_range(args, tax):
+	if not flt(tax.maximum_net_rate):
+		# No range specified, just ignore
+		return True
+	elif flt(tax.minimum_net_rate) <= flt(args.get('net_rate')) <= flt(tax.maximum_net_rate):
+		return True
+
+	return False
+
 @frappe.whitelist()
 def get_item_tax_map(company, item_tax_template, as_json=True):
 	item_tax_map = {}