Show hsn code in tax breakup for India and render via template (#9866)

* Show hsn code in tax breakup for India and render via template

* tax breakup if gst_tax_field does not exists

* Fixed tax-breakup test cases
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 800e6a9..90b36e0 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -13,6 +13,7 @@
 from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
 from frappe.model.naming import make_autoname
 from erpnext.accounts.doctype.account.test_account import get_inventory_account
+from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
 
 class TestSalesInvoice(unittest.TestCase):
 	def make(self):
@@ -1105,10 +1106,75 @@
 			for i, k in enumerate(expected_values["keys"]):
 				self.assertEquals(d.get(k), expected_values[d.item_code][i])
 
-	def test_item_wise_tax_breakup(self):
+	def test_item_wise_tax_breakup_india(self):
+		frappe.flags.country = "India"
+		
+		si = self.create_si_to_test_tax_breakup()
+		itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(si)
+
+		expected_itemised_tax = {
+			"999800": {
+				"Service Tax": {
+					"tax_rate": 10.0,
+					"tax_amount": 1500.0
+				}
+			}
+		}
+		expected_itemised_taxable_amount = {
+			"999800": 15000.0
+		}
+
+		self.assertEqual(itemised_tax, expected_itemised_tax)
+		self.assertEqual(itemised_taxable_amount, expected_itemised_taxable_amount)
+		
+		frappe.flags.country = None
+
+	def test_item_wise_tax_breakup_outside_india(self):
+		frappe.flags.country = "United States"
+		
+		si = self.create_si_to_test_tax_breakup()
+
+		itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(si)
+
+		expected_itemised_tax = {
+			"_Test Item": {
+				"Service Tax": {
+					"tax_rate": 10.0,
+					"tax_amount": 1000.0
+				}
+			},
+			"_Test Item 2": {
+				"Service Tax": {
+					"tax_rate": 10.0,
+					"tax_amount": 500.0
+				}
+			}
+		}
+		expected_itemised_taxable_amount = {
+			"_Test Item": 10000.0,
+			"_Test Item 2": 5000.0
+		}
+
+		self.assertEqual(itemised_tax, expected_itemised_tax)
+		self.assertEqual(itemised_taxable_amount, expected_itemised_taxable_amount)
+		
+		frappe.flags.country = None
+
+	def create_si_to_test_tax_breakup(self):
 		si = create_sales_invoice(qty=100, rate=50, do_not_save=True)
 		si.append("items", {
 			"item_code": "_Test Item",
+			"gst_hsn_code": "999800",
+			"warehouse": "_Test Warehouse - _TC",
+			"qty": 100,
+			"rate": 50,
+			"income_account": "Sales - _TC",
+			"expense_account": "Cost of Goods Sold - _TC",
+			"cost_center": "_Test Cost Center - _TC"
+		})
+		si.append("items", {
+			"item_code": "_Test Item 2",
+			"gst_hsn_code": "999800",
 			"warehouse": "_Test Warehouse - _TC",
 			"qty": 100,
 			"rate": 50,
@@ -1125,11 +1191,7 @@
 			"rate": 10
 		})
 		si.insert()
-
-		tax_breakup_html = '''\n<div class="tax-break-up" style="overflow-x: auto;">\n\t<table class="table table-bordered table-hover">\n\t\t<thead><tr><th class="text-left" style="min-width: 120px;">Item Name</th><th class="text-right" style="min-width: 80px;">Taxable Amount</th><th class="text-right" style="min-width: 80px;">_Test Account Service Tax - _TC</th></tr></thead>\n\t\t<tbody><tr><td>_Test Item</td><td class="text-right">\u20b9 10,000.00</td><td class="text-right">(10.0%) \u20b9 1,000.00</td></tr></tbody>\n\t</table>\n</div>'''
-		
-		self.assertEqual(si.other_charges_calculation, tax_breakup_html)
-		
+		return si
 
 def create_sales_invoice(**args):
 	si = frappe.new_doc("Sales Invoice")
@@ -1150,6 +1212,7 @@
 
 	si.append("items", {
 		"item_code": args.item or args.item_code or "_Test Item",
+		"gst_hsn_code": "999800",
 		"warehouse": args.warehouse or "_Test Warehouse - _TC",
 		"qty": args.qty or 1,
 		"rate": args.rate or 100,
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index 506427e..a5f9b3c 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -1398,10 +1398,6 @@
 		return erpnext.get_currency(this.frm.doc.company);
 	},
 
-	show_item_wise_taxes: function () {
-		return null;
-	},
-
 	show_items_in_item_cart: function () {
 		var me = this;
 		var $items = this.wrapper.find(".items").empty();
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 8b96152..f1e95ec 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -5,7 +5,7 @@
 import json
 import frappe, erpnext
 from frappe import _, scrub
-from frappe.utils import cint, flt, cstr, fmt_money, round_based_on_smallest_currency_fraction
+from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction
 from erpnext.controllers.accounts_controller import validate_conversion_rate, \
 	validate_taxes_and_charges, validate_inclusive_tax
 
@@ -509,108 +509,72 @@
 		return rate_with_margin
 
 	def set_item_wise_tax_breakup(self):
-		item_tax = {}
-		tax_accounts = []
-		company_currency = erpnext.get_company_currency(self.doc.company)
+		if not self.doc.taxes:
+			return
+		frappe.flags.company = self.doc.company
 		
-		item_tax, tax_accounts = self.get_item_tax(item_tax, tax_accounts, company_currency)
+		# get headers
+		tax_accounts = list(set([d.description for d in self.doc.taxes]))
+		headers = get_itemised_tax_breakup_header(self.doc.doctype + " Item", tax_accounts)
 		
-		headings = get_table_column_headings(tax_accounts)
+		# get tax breakup data
+		itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(self.doc)
 		
-		distinct_items, taxable_amount = self.get_distinct_items()
+		frappe.flags.company = None
 		
-		rows = get_table_rows(distinct_items, item_tax, tax_accounts, company_currency, taxable_amount)
-		
-		if not rows:
-			self.doc.other_charges_calculation = ""
-		else:
-			self.doc.other_charges_calculation = '''
-<div class="tax-break-up" style="overflow-x: auto;">
-	<table class="table table-bordered table-hover">
-		<thead><tr>{headings}</tr></thead>
-		<tbody>{rows}</tbody>
-	</table>
-</div>'''.format(**{
-	"headings": "".join(headings),
-	"rows": "".join(rows)
-})
+		self.doc.other_charges_calculation = frappe.render_template(
+			"templates/includes/itemised_tax_breakup.html", dict(
+				headers=headers,
+				itemised_tax=itemised_tax,
+				itemised_taxable_amount=itemised_taxable_amount,
+				tax_accounts=tax_accounts,
+				company_currency=erpnext.get_company_currency(self.doc.company)
+			)
+		)
 
-	def get_item_tax(self, item_tax, tax_accounts, company_currency):
-		for tax in self.doc.taxes:
-			tax_amount_precision = tax.precision("tax_amount")
-			tax_rate_precision = tax.precision("rate");
+@erpnext.allow_regional
+def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
+	return [_("Item"), _("Taxable Amount")] + tax_accounts
+
+@erpnext.allow_regional
+def get_itemised_tax_breakup_data(doc):
+	itemised_tax = get_itemised_tax(doc.taxes)
+
+	itemised_taxable_amount = get_itemised_taxable_amount(doc.items)
+
+	return itemised_tax, itemised_taxable_amount
+
+def get_itemised_tax(taxes):
+	itemised_tax = {}
+	for tax in taxes:
+		tax_amount_precision = tax.precision("tax_amount")
+		tax_rate_precision = tax.precision("rate")
+		
+		item_tax_map = json.loads(tax.item_wise_tax_detail) if tax.item_wise_tax_detail else {}
+		
+		for item_code, tax_data in item_tax_map.items():
+			itemised_tax.setdefault(item_code, frappe._dict())
 			
-			item_tax_map = self._load_item_tax_rate(tax.item_wise_tax_detail)
-			for item_code, tax_data in item_tax_map.items():
-				if not item_tax.get(item_code):
-					item_tax[item_code] = {}
-					
-				if isinstance(tax_data, list):
-					tax_rate = ""
-					if tax_data[0]:
-						if tax.charge_type == "Actual":
-							tax_rate = fmt_money(flt(tax_data[0], tax_amount_precision),
-								tax_amount_precision, company_currency)
-						else:
-							tax_rate = cstr(flt(tax_data[0], tax_rate_precision)) + "%"
-							
-						tax_amount = fmt_money(flt(tax_data[1], tax_amount_precision),
-							tax_amount_precision, company_currency)
-							
-						item_tax[item_code][tax.name] = [tax_rate, tax_amount]
-					else:
-						item_tax[item_code][tax.name] = [cstr(flt(tax_data, tax_rate_precision)) + "%", "0.00"]
-			tax_accounts.append([tax.name, tax.account_head])
-		
-		return item_tax, tax_accounts
-
-	
-	def get_distinct_items(self):
-		distinct_item_names = []
-		distinct_items = []
-		taxable_amount = {}
-		for item in self.doc.items:
-			item_code = item.item_code or item.item_name
-			if item_code not in distinct_item_names:
-				distinct_item_names.append(item_code)
-				distinct_items.append(item)
-				taxable_amount[item_code] = item.net_amount
-			else:
-				taxable_amount[item_code] = taxable_amount.get(item_code, 0) + item.net_amount
+			if isinstance(tax_data, list) and tax_data[0]:
+				precision = tax_amount_precision if tax.charge_type == "Actual" else tax_rate_precision
 				
-		return distinct_items, taxable_amount
-
-def get_table_column_headings(tax_accounts):
-	headings_name = [_("Item Name"), _("Taxable Amount")] + [d[1] for d in tax_accounts]
-	headings = []
-	for head in headings_name:
-		if head == _("Item Name"):
-			headings.append('<th style="min-width: 120px;" class="text-left">' + (head or "") + "</th>")
-		else:
-			headings.append('<th style="min-width: 80px;" class="text-right">' + (head or "") + "</th>")
-			
-	return headings
-
-def get_table_rows(distinct_items, item_tax, tax_accounts, company_currency, taxable_amount):
-	rows = []
-	for item in distinct_items:
-		item_tax_record = item_tax.get(item.item_code or item.item_name)
-		if not item_tax_record:
-			continue
-		
-		taxes = []
-		for head in tax_accounts:
-			if item_tax_record[head[0]]:
-				taxes.append("<td class='text-right'>(" + item_tax_record[head[0]][0] + ") "
-					 + item_tax_record[head[0]][1] + "</td>")
+				itemised_tax[item_code][tax.description] = frappe._dict(dict(
+					tax_rate=flt(tax_data[0], precision),
+					tax_amount=flt(tax_data[1], tax_amount_precision)
+				))
 			else:
-				taxes.append("<td></td>")
+				itemised_tax[item_code][tax.description] = frappe._dict(dict(
+					tax_rate=flt(tax_data, tax_rate_precision),
+					tax_amount=0.0
+				))
 
+	return itemised_tax
+
+def get_itemised_taxable_amount(items):
+	itemised_taxable_amount = frappe._dict()
+	for item in items:
 		item_code = item.item_code or item.item_name
-		rows.append("<tr><td>{item_name}</td><td class='text-right'>{taxable_amount}</td>{taxes}</tr>".format(**{
-			"item_name": item.item_name,
-			"taxable_amount": fmt_money(taxable_amount.get(item_code, 0), item.precision("net_amount"), company_currency),
-			"taxes": "".join(taxes)
-		}))
-		
-	return rows
\ No newline at end of file
+		itemised_taxable_amount.setdefault(item_code, 0)
+		itemised_taxable_amount[item_code] += item.net_amount
+
+	return itemised_taxable_amount
\ No newline at end of file
diff --git a/erpnext/docs/assets/img/regional/india/sample-gst-tax-invoice.png b/erpnext/docs/assets/img/regional/india/sample-gst-tax-invoice.png
index cb65724..6543518 100644
--- a/erpnext/docs/assets/img/regional/india/sample-gst-tax-invoice.png
+++ b/erpnext/docs/assets/img/regional/india/sample-gst-tax-invoice.png
Binary files differ
diff --git a/erpnext/docs/license.html b/erpnext/docs/license.html
index 4740c5c..1d50b78 100644
--- a/erpnext/docs/license.html
+++ b/erpnext/docs/license.html
@@ -640,8 +640,8 @@
 the exclusion of warranty; and each file should have at least the
 "copyright" line and a pointer to where the full notice is found.</p>
 
-<pre><code>    &lt;one line to give the program's name and a brief idea of what it does.&gt;
-    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
+<pre><code>    &lt;one line="" to="" give="" the="" program's="" name="" and="" a="" brief="" idea="" of="" what="" it="" does.=""&gt;
+    Copyright (C) &lt;year&gt;  &lt;name of="" author=""&gt;
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index fedc6d5..173531d 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -209,6 +209,8 @@
 
 regional_overrides = {
 	'India': {
-		'erpnext.tests.test_regional.test_method': 'erpnext.regional.india.utils.test_method'
+		'erpnext.tests.test_regional.test_method': 'erpnext.regional.india.utils.test_method',
+		'erpnext.controllers.taxes_and_totals.get_itemised_tax_breakup_header': 'erpnext.regional.india.utils.get_itemised_tax_breakup_header',
+		'erpnext.controllers.taxes_and_totals.get_itemised_tax_breakup_data': 'erpnext.regional.india.utils.get_itemised_tax_breakup_data'
 	}
 }
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 837097b..3a010c6 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -54,7 +54,6 @@
 		this.manipulate_grand_total_for_inclusive_tax();
 		this.calculate_totals();
 		this._cleanup();
-		this.show_item_wise_taxes();
 	},
 
 	validate_conversion_rate: function() {
@@ -634,99 +633,5 @@
 		}
 		
 		this.calculate_outstanding_amount(false)
-	},
-	
-	show_item_wise_taxes: function() {
-		if(this.frm.fields_dict.other_charges_calculation) {
-			this.frm.toggle_display("other_charges_calculation", this.frm.doc.other_charges_calculation);
-		}
-	},
-	
-	set_item_wise_tax_breakup: function() {
-		if(this.frm.fields_dict.other_charges_calculation) {
-			var html = this.get_item_wise_taxes_html();
-			// console.log(html);
-			this.frm.set_value("other_charges_calculation", html);
-			this.show_item_wise_taxes();
-		}
-	},
-		
-	get_item_wise_taxes_html: function() {
-		var item_tax = {};
-		var tax_accounts = [];
-		var company_currency = this.get_company_currency();
-
-		$.each(this.frm.doc["taxes"] || [], function(i, tax) {
-			var tax_amount_precision = precision("tax_amount", tax);
-			var tax_rate_precision = precision("rate", tax);
-			$.each(JSON.parse(tax.item_wise_tax_detail || '{}'),
-				function(item_code, tax_data) {
-					if(!item_tax[item_code]) item_tax[item_code] = {};
-					if($.isArray(tax_data)) {
-						var tax_rate = "";
-						if(tax_data[0] != null) {
-							tax_rate = (tax.charge_type === "Actual") ?
-								format_currency(flt(tax_data[0], tax_amount_precision),
-									company_currency, tax_amount_precision) :
-								(flt(tax_data[0], tax_rate_precision) + "%");
-						}
-						var tax_amount = format_currency(flt(tax_data[1], tax_amount_precision),
-							company_currency, tax_amount_precision);
-
-						item_tax[item_code][tax.name] = [tax_rate, tax_amount];
-					} else {
-						item_tax[item_code][tax.name] = [flt(tax_data, tax_rate_precision) + "%", "0.00"];
-					}
-				});
-			tax_accounts.push([tax.name, tax.account_head]);
-		});
-		
-		var headings = $.map([__("Item Name"), __("Taxable Amount")].concat($.map(tax_accounts, 
-			function(head) { return head[1]; })), function(head) {
-				if(head==__("Item Name")) {
-					return '<th style="min-width: 100px;" class="text-left">' + (head || "") + "</th>";
-				} else {
-					return '<th style="min-width: 80px;" class="text-right">' + (head || "") + "</th>";
-				}	
-			}
-		).join("");
-
-		var distinct_item_names = [];
-		var distinct_items = [];
-		var taxable_amount = {};
-		$.each(this.frm.doc["items"] || [], function(i, item) {
-			var item_code = item.item_code || item.item_name;
-			if(distinct_item_names.indexOf(item_code)===-1) {
-				distinct_item_names.push(item_code);
-				distinct_items.push(item);
-				taxable_amount[item_code] = item.net_amount;
-			} else {
-				taxable_amount[item_code] = taxable_amount[item_code] + item.net_amount;
-			}
-		});
-
-		var rows = $.map(distinct_items, function(item) {
-			var item_code = item.item_code || item.item_name;
-			var item_tax_record = item_tax[item_code];
-			if(!item_tax_record) { return null; }
-
-			return repl("<tr><td>%(item_name)s</td><td class='text-right'>%(taxable_amount)s</td>%(taxes)s</tr>", {
-				item_name: item.item_name,
-				taxable_amount: format_currency(taxable_amount[item_code],
-					company_currency, precision("net_amount", item)),
-				taxes: $.map(tax_accounts, function(head) {
-					return item_tax_record[head[0]] ?
-						"<td class='text-right'>(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "</td>" :
-						"<td></td>";
-				}).join("")
-			});
-		}).join("");
-
-		if(!rows) return "";
-		return '<div class="tax-break-up" style="overflow-x: auto;">\
-		<table class="table table-bordered table-hover">\
-			<thead><tr>' + headings + '</tr></thead> \
-			<tbody>' + rows + '</tbody> \
-		</table></div>';
 	}
 })
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 9ed1de2..1e8353b 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -210,7 +210,6 @@
 	refresh: function() {
 		erpnext.toggle_naming_series();
 		erpnext.hide_company();
-		this.show_item_wise_taxes();
 		this.set_dynamic_labels();
 		this.setup_sms();
 	},
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index c35ff0a..0369487 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -80,7 +80,7 @@
 
 def make_custom_fields():
 	hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
-		fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
+		fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description', print_hide=1)
 	
 	custom_fields = {
 		'Address': [
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 437465a..8f2dacd 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -1,6 +1,7 @@
 import frappe, re
 from frappe import _
 from erpnext.regional.india import states, state_numbers
+from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
 
 def validate_gstin_for_india(doc, method):
 	if not hasattr(doc, 'gstin'):
@@ -23,6 +24,42 @@
 				frappe.throw(_("First 2 digits of GSTIN should match with State number {0}")
 					.format(doc.gst_state_number))
 
+def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
+	if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):
+		return [_("HSN/SAC"), _("Taxable Amount")] + tax_accounts
+	else:
+		return [_("Item"), _("Taxable Amount")] + tax_accounts
+	
+def get_itemised_tax_breakup_data(doc):
+	itemised_tax = get_itemised_tax(doc.taxes)
+
+	itemised_taxable_amount = get_itemised_taxable_amount(doc.items)
+	
+	if not frappe.get_meta(doc.doctype + " Item").has_field('gst_hsn_code'):
+		return itemised_tax, itemised_taxable_amount
+
+	item_hsn_map = frappe._dict()
+	for d in doc.items:
+		item_hsn_map.setdefault(d.item_code or d.item_name, d.get("gst_hsn_code"))
+
+	hsn_tax = {}
+	for item, taxes in itemised_tax.items():
+		hsn_code = item_hsn_map.get(item)
+		hsn_tax.setdefault(hsn_code, frappe._dict())
+		for tax_account, tax_detail in taxes.items():
+			hsn_tax[hsn_code].setdefault(tax_account, {"tax_rate": 0, "tax_amount": 0})
+			hsn_tax[hsn_code][tax_account]["tax_rate"] = tax_detail.get("tax_rate")
+			hsn_tax[hsn_code][tax_account]["tax_amount"] += tax_detail.get("tax_amount")
+
+	# set taxable amount
+	hsn_taxable_amount = frappe._dict()
+	for item, taxable_amount in itemised_taxable_amount.items():
+		hsn_code = item_hsn_map.get(item)
+		hsn_taxable_amount.setdefault(hsn_code, 0)
+		hsn_taxable_amount[hsn_code] += itemised_taxable_amount.get(item)
+
+	return hsn_tax, hsn_taxable_amount
+
 # don't remove this function it is used in tests
 def test_method():
 	'''test function'''
diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json
index 2a1520e..7c5ad4f 100644
--- a/erpnext/stock/doctype/item/test_records.json
+++ b/erpnext/stock/doctype/item/test_records.json
@@ -15,6 +15,7 @@
   "item_group": "_Test Item Group",
   "item_name": "_Test Item",
   "apply_warehouse_wise_reorder_level": 1,
+  "gst_hsn_code": "999800",
   "valuation_rate": 100,
   "reorder_levels": [
    {
diff --git a/erpnext/templates/includes/itemised_tax_breakup.html b/erpnext/templates/includes/itemised_tax_breakup.html
new file mode 100644
index 0000000..342ce6b
--- /dev/null
+++ b/erpnext/templates/includes/itemised_tax_breakup.html
@@ -0,0 +1,38 @@
+<div class="tax-break-up" style="overflow-x: auto;">
+	<table class="table table-bordered table-hover">
+		<thead>
+			<tr>
+				{% set i = 0 %}
+				{% for key in headers %}
+					{% if i==0 %}
+						<th style="min-width: 120px;" class="text-left">{{ key }}</th>
+					{% else %}
+						<th style="min-width: 80px;" class="text-right">{{ key }}</th>
+					{% endif %}
+					{% set i = i + 1 %}
+				{% endfor%}
+			</tr>
+		</thead>
+		<tbody>
+			{% for item, taxes in itemised_tax.items() %}
+				<tr>
+					<td>{{ item }}</td>
+					<td class='text-right'>
+						{{ frappe.utils.fmt_money(itemised_taxable_amount.get(item), None, company_currency) }}
+					</td>
+					{% for tax_account in tax_accounts %}
+						{% set tax_details = taxes.get(tax_account) %}
+						{% if tax_details %}
+							<td class='text-right'>
+								({{ tax_details.tax_rate }})
+								{{ frappe.utils.fmt_money(tax_details.tax_amount, None, company_currency) }}
+							</td>
+						{% else %}
+							<td></td>
+						{% endif %}
+					{% endfor %}
+				</tr>
+			{% endfor %}
+		</tbody>
+	</table>
+</div>
\ No newline at end of file