feat: add tax and charges in expense claim
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 7c6abc7..0ff70cb 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -157,6 +157,14 @@
 				}
 			};
 		});
+		// frm.set_query("taxes", "account_head", function(doc) {
+		// 	return {
+		// 		filters: [
+		// 			['docstatus', '=', 1],
+		// 			['company', '=', doc.company]
+		// 		]
+		// 	};
+		// });
 	},
 
 	onload: function(frm) {
@@ -259,6 +267,18 @@
 		frm.events.get_advances(frm);
 	},
 
+	get_taxes: function(frm) {
+		if(frm.doc.taxes) {
+			frappe.call({
+				method: "calculate_taxes",
+				doc: frm.doc,
+				callback: (r) => {
+					refresh_field("taxes");
+				}
+			});
+		}
+	},
+
 	get_advances: function(frm) {
 		frappe.model.clear_table(frm.doc, "advances");
 		if (frm.doc.employee) {
@@ -298,6 +318,7 @@
 	sanctioned_amount: function(frm, cdt, cdn) {
 		var doc = frm.doc;
 		cur_frm.cscript.calculate_total(doc,cdt,cdn);
+		frm.trigger("get_taxes");
 	}
 });
 
@@ -332,6 +353,47 @@
 	}
 });
 
+frappe.ui.form.on("Expense Taxes and Charges", {
+	account_head: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+		if(child.account_head && !child.description && !child.rate) {
+			// set description from account head
+			child.description = child.account_head.split(' - ').slice(0, -1).join(' - ');
+
+			// set the tax rate from account head
+			frappe.db.get_value("Account", child.account_head, "tax_rate").then((r) => {
+				if(r.message) {
+					frappe.model.set_value(cdt, cdn, 'rate', r.message.tax_rate);
+				}
+			});
+			refresh_field("taxes");
+		}
+	},
+
+	calculate_total: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+		child.total = flt(frm.doc.total_sanctioned_amount) + flt(child.tax_amount);
+
+		refresh_field("taxes");
+	},
+
+	rate: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+		if(!child.amount) {
+			child.tax_amount = flt(frm.doc.total_sanctioned_amount) * (flt(child.rate)/100);
+			refresh_field("taxes");
+		}
+		frm.trigger("calculate_total", cdt, cdn)
+	},
+
+	tax_amount: function(frm, cdt, cdn) {
+		var child = locals[cdt][cdn];
+		child.rate = flt(child.tax_amount/frm.doc.total_sanctioned_amount) * 100;
+		frm.trigger("calculate_total", cdt, cdn)
+		refresh_field("taxes");
+	}
+});
+
 cur_frm.fields_dict['task'].get_query = function(doc) {
 	return {
 		filters:{
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json
index 6e04644..007e646 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.json
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.json
@@ -4,6 +4,7 @@
  "creation": "2013-01-10 16:34:14",
  "doctype": "DocType",
  "document_type": "Setup",
+ "engine": "InnoDB",
  "field_order": [
   "naming_series",
   "employee",
@@ -18,6 +19,9 @@
   "expense_details",
   "expenses",
   "sb1",
+  "taxes",
+  "net_total",
+  "section_break_16",
   "posting_date",
   "vehicle_log",
   "task",
@@ -315,12 +319,28 @@
   {
    "fieldname": "dimension_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "taxes",
+   "fieldtype": "Table",
+   "label": "Expense Taxes and Charges",
+   "options": "Expense Taxes and Charges"
+  },
+  {
+   "fieldname": "section_break_16",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "net_total",
+   "fieldtype": "Currency",
+   "label": "Net Total",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-money",
  "idx": 1,
  "is_submittable": 1,
- "modified": "2019-05-25 22:53:31.682151",
+ "modified": "2019-06-11 13:21:42.386420",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Expense Claim",
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index d6b0eca..c5b6ebe 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -12,6 +12,7 @@
 from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account
 from erpnext.controllers.accounts_controller import AccountsController
 from frappe.utils.csvutils import getlink
+from erpnext.accounts.utils import get_account_currency
 
 class InvalidExpenseApproverError(frappe.ValidationError): pass
 class ExpenseApproverIdentityError(frappe.ValidationError): pass
@@ -29,6 +30,7 @@
 		self.set_expense_account(validate=True)
 		self.set_payable_account()
 		self.set_cost_center()
+		self.calculate_taxes()
 		self.set_status()
 		if self.task and not self.project:
 			self.project = frappe.db.get_value("Task", self.task, "project")
@@ -93,7 +95,7 @@
 		elif self.project:
 			frappe.get_doc("Project", self.project).update_project()
 
-	def make_gl_entries(self, cancel = False):
+	def make_gl_entries(self, cancel=False):
 		if flt(self.total_sanctioned_amount) > 0:
 			gl_entries = self.get_gl_entries()
 			make_gl_entries(gl_entries, cancel)
@@ -102,7 +104,7 @@
 		gl_entry = []
 		self.validate_account_details()
 
-		payable_amount = flt(self.total_sanctioned_amount) - flt(self.total_advance_amount)
+		payable_amount = flt(self.net_total) - flt(self.total_advance_amount)
 
 		# payable entry
 		if payable_amount:
@@ -170,8 +172,26 @@
 				})
 			)
 
+		gl_entry = self.make_tax_gl_entries(gl_entry)
+
 		return gl_entry
 
+	def make_tax_gl_entries(self, gl_entries):
+		# tax table gl entries
+		for tax in self.get("taxes"):
+			account_currency = get_account_currency(tax.account_head)
+			gl_entries.append(
+				self.get_gl_dict({
+					"account": tax.account_head,
+					"debit": tax.tax_amount,
+					"against": self.employee,
+					"cost_center": self.cost_center,
+					"against_voucher_type": self.doctype,
+					"against_voucher": self.name
+				}, account_currency)
+			)
+		return gl_entries
+
 	def validate_account_details(self):
 		if not self.cost_center:
 			frappe.throw(_("Cost center is required to book an expense claim"))
@@ -193,6 +213,15 @@
 			self.total_claimed_amount += flt(d.claim_amount)
 			self.total_sanctioned_amount += flt(d.sanctioned_amount)
 
+	def calculate_taxes(self):
+		for tax in self.taxes:
+			if tax.rate:
+				tax.tax_amount = flt(self.total_sanctioned_amount) * flt(tax.rate/100)
+			if tax.tax_amount:
+				tax.rate = flt(tax.tax_amount)/flt(self.total_sanctioned_amount) * 100
+			tax.total = flt(tax.tax_amount) + flt(self.total_sanctioned_amount)
+			self.net_total += tax.total
+
 	def update_task(self):
 		task = frappe.get_doc("Task", self.task)
 		task.update_total_expense_claim()
diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/__init__.py b/erpnext/hr/doctype/expense_taxes_and_charges/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/expense_taxes_and_charges/__init__.py
diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json
new file mode 100644
index 0000000..8caf0a9
--- /dev/null
+++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.json
@@ -0,0 +1,103 @@
+{
+ "autoname": "hash",
+ "creation": "2019-06-03 11:42:33.123976",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account_head",
+  "cost_center",
+  "col_break1",
+  "rate",
+  "description",
+  "section_break_6",
+  "tax_amount",
+  "column_break_8",
+  "total"
+ ],
+ "fields": [
+  {
+   "fieldname": "col_break1",
+   "fieldtype": "Column Break"
+  },
+  {
+   "columns": 2,
+   "fieldname": "account_head",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Account Head",
+   "oldfieldname": "account_head",
+   "oldfieldtype": "Link",
+   "options": "Account",
+   "reqd": 1
+  },
+  {
+   "default": ":Company",
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "oldfieldname": "cost_center",
+   "oldfieldtype": "Link",
+   "options": "Cost Center"
+  },
+  {
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "label": "Description",
+   "oldfieldname": "description",
+   "oldfieldtype": "Small Text",
+   "print_width": "300px",
+   "reqd": 1,
+   "width": "300px"
+  },
+  {
+   "columns": 2,
+   "fieldname": "rate",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Rate",
+   "oldfieldname": "rate",
+   "oldfieldtype": "Currency"
+  },
+  {
+   "columns": 2,
+   "fieldname": "tax_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "oldfieldname": "tax_amount",
+   "oldfieldtype": "Currency",
+   "options": "currency"
+  },
+  {
+   "columns": 2,
+   "fieldname": "total",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Total",
+   "oldfieldname": "total",
+   "oldfieldtype": "Currency",
+   "options": "currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_6",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_8",
+   "fieldtype": "Column Break"
+  }
+ ],
+ "istable": 1,
+ "modified": "2019-06-11 14:19:34.780611",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Expense Taxes and Charges",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py
new file mode 100644
index 0000000..4103bef
--- /dev/null
+++ b/erpnext/hr/doctype/expense_taxes_and_charges/expense_taxes_and_charges.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ExpenseTaxesandCharges(Document):
+	pass