Validate taxes and charges input, commonified
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 6f16dcd..8040c41 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -3,7 +3,6 @@
 
 frappe.provide("erpnext.accounts");
 {% include 'buying/doctype/purchase_common/purchase_common.js' %};
-{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
 
 erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
 	onload: function() {
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py b/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py
index e93c572..b004a2e 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py
@@ -2,8 +2,11 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
 from frappe.model.document import Document
+from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax
 
 class PurchaseTaxesandChargesMaster(Document):
-	pass
+	def validate(self):
+		for tax in self.get("taxes"):
+			validate_taxes_and_charges(tax)
+			validate_inclusive_tax(tax, self)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index bbc0dd2..4670303 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -5,7 +5,6 @@
 cur_frm.pformat.print_heading = 'Invoice';
 
 {% include 'selling/sales_common.js' %};
-{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
 
 frappe.provide("erpnext.accounts");
 erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js
index 58a80a8..b5dc38f 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js
@@ -1,8 +1,6 @@
 // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
-cur_frm.cscript.tax_table = "Sales Taxes and Charges";
-
 {% include "public/js/controllers/accounts.js" %}
 
 cur_frm.cscript.onload = function(doc, cdt, cdn) {
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py
index 6ab5ab2..4317f2a 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py
@@ -3,8 +3,8 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import cint
 from frappe.model.document import Document
+from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax
 
 class SalesTaxesandChargesMaster(Document):
 	def validate(self):
@@ -15,3 +15,8 @@
 
 		# at least one territory
 		self.validate_table_has_rows("territories")
+
+		for tax in self.get("taxes"):
+			validate_taxes_and_charges(tax)
+			validate_inclusive_tax(tax, self)
+
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index f98dab7..dc3b3a3 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -1,11 +1,12 @@
 // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
+cur_frm.cscript.tax_table = "Purchase Taxes and Charges";
+{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
+
 frappe.provide("erpnext.buying");
 frappe.require("assets/erpnext/js/controllers/transaction.js");
 
-{% include "public/js/controllers/accounts.js" %};
-
 cur_frm.email_field = "contact_email";
 
 erpnext.buying.BuyingController = erpnext.TransactionController.extend({
@@ -166,97 +167,6 @@
 			this.frm.doc.outstanding_amount = flt(this.frm.doc.total_amount_to_pay - this.frm.doc.total_advance,
 				precision("outstanding_amount"));
 		}
-	},
-
-	change_form_labels: function(company_currency) {
-		var me = this;
-		var field_label_map = {};
-
-		var setup_field_label_map = function(fields_list, currency) {
-			$.each(fields_list, function(i, fname) {
-				var docfield = frappe.meta.docfield_map[me.frm.doc.doctype][fname];
-				if(docfield) {
-					var label = __(docfield.label || "").replace(/\([^\)]*\)/g, "");
-					field_label_map[fname] = label.trim() + " (" + currency + ")";
-				}
-			});
-		};
-
-
-		setup_field_label_map(["base_net_total", "base_total_taxes_and_charges", "base_grand_total", "base_in_words",
-			"base_taxes_and_charges_added", "base_taxes_and_charges_deducted",
-			"outstanding_amount", "total_advance", "total_amount_to_pay", "base_rounded_total"],
-			company_currency);
-
-		setup_field_label_map(["net_total", "grand_total", "in_words",
-			"taxes_and_charges_added", "taxes_and_charges_deducted"], this.frm.doc.currency);
-
-		cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency
-			+ " = [?] " + company_currency);
-
-		if(this.frm.doc.price_list_currency && this.frm.doc.price_list_currency!=company_currency) {
-			cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency
-				+ " = [?] " + company_currency);
-		}
-
-		// toggle fields
-		this.frm.toggle_display(["conversion_rate", "base_net_total", "base_grand_total",
-			"base_in_words", "base_taxes_and_charges_added", "base_taxes_and_charges_deducted"],
-			this.frm.doc.currency !== company_currency);
-
-		this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"],
-			this.frm.doc.price_list_currency !== company_currency);
-
-		// set labels
-		$.each(field_label_map, function(fname, label) {
-			me.frm.fields_dict[fname].set_label(label);
-		});
-
-	},
-
-	change_grid_labels: function(company_currency) {
-		var me = this;
-		var field_label_map = {};
-
-		var setup_field_label_map = function(fields_list, currency, parentfield) {
-			var grid_doctype = me.frm.fields_dict[parentfield].grid.doctype;
-			$.each(fields_list, function(i, fname) {
-				var docfield = frappe.meta.docfield_map[grid_doctype][fname];
-				if(docfield) {
-					var label = __(docfield.label || "").replace(/\([^\)]*\)/g, "");
-					field_label_map[grid_doctype + "-" + fname] =
-						label.trim() + " (" + currency + ")";
-				}
-			});
-		};
-
-		setup_field_label_map(["base_rate", "base_price_list_rate", "base_amount", "base_rate"],
-			company_currency, "items");
-
-			setup_field_label_map(["rate", "price_list_rate", "amount"], this.frm.doc.currency, "items");
-
-		if(this.frm.fields_dict["taxes"]) {
-			setup_field_label_map(["tax_amount", "total"], company_currency, "taxes");
-		}
-
-		if(this.frm.fields_dict["advances"]) {
-			setup_field_label_map(["advance_amount", "allocated_amount"], company_currency,
-				"advances");
-		}
-
-		// toggle columns
-		var item_grid = this.frm.fields_dict["items"].grid;
-		var fieldnames = $.map(["base_rate", "base_price_list_rate", "base_amount", "base_rate"], function(fname) {
-			return frappe.meta.get_docfield(item_grid.doctype, fname, me.frm.docname) ? fname : null;
-		});
-
-		item_grid.set_column_disp(fieldnames, this.frm.doc.currency != company_currency);
-
-		// set labels
-		var $wrapper = $(this.frm.wrapper);
-		$.each(field_label_map, function(fname, label) {
-			$wrapper.find('[data-grid-fieldname="'+fname+'"]').text(label);
-		});
 	}
 });
 cur_frm.add_fetch('project_name', 'cost_center', 'cost_center');
@@ -279,8 +189,3 @@
 		}
 	});
 }
-
-
-frappe.ui.form.on("Purchase Taxes and Charges", "rate", function(frm, cdt, cdn) {
-	cur_frm.cscript.calculate_taxes_and_totals();
-})
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index b1eee0e..27ea0d4 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -4,7 +4,6 @@
 frappe.provide("erpnext.buying");
 
 {% include 'buying/doctype/purchase_common/purchase_common.js' %};
-{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
 
 erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
 	refresh: function(doc, cdt, cdn) {
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index 9c2bbed..ecd9185 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -3,7 +3,6 @@
 
 // attach required files
 {% include 'buying/doctype/purchase_common/purchase_common.js' %};
-{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
 
 erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
 	refresh: function() {
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index c0a63cd..1765fbf 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _, throw
-from frappe.utils import today, flt
+from frappe.utils import today, flt, cint
 from erpnext.setup.utils import get_company_currency, get_exchange_rate
 from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
 from erpnext.utilities.transaction_base import TransactionBase
@@ -357,3 +357,34 @@
 	if not conversion_rate:
 		throw(_("{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.").format(
 			conversion_rate_label, currency, company_currency))
+
+def validate_taxes_and_charges(tax):
+	if not tax.charge_type and (tax.row_id or tax.rate or tax.tax_amount):
+		frappe.throw(_("Please select Charge Type first"))
+	elif tax.charge_type in ['Actual', 'On Net Total'] and tax.row_id:
+		frappe.throw(_("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'"))
+	elif tax.charge_type in ['On Previous Row Amount', 'On Previous Row Total'] and tax.row_id:
+		if cint(tax.idx) == 1:
+			frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"))
+		elif not tax.row_id:
+			frappe.throw(_("Please specify a valid Row ID for row {0} in table {1}".format(tax.idx, _(tax.doctype))))
+		elif tax.row_id and cint(tax.row_id) >= cint(tax.idx):
+			frappe.throw(_("Cannot refer row number greater than or equal to current row number for this Charge type"))
+
+def validate_inclusive_tax(tax, doc):
+	def _on_previous_row_error(row_range):
+		throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx,
+			row_range))
+
+	if cint(getattr(tax, "included_in_print_rate", None)):
+		if tax.charge_type == "Actual":
+			# inclusive tax cannot be of type Actual
+			throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate").format(tax.idx))
+		elif tax.charge_type == "On Previous Row Amount" and \
+				not cint(doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate):
+			# referred row should also be inclusive
+			_on_previous_row_error(tax.row_id)
+		elif tax.charge_type == "On Previous Row Total" and \
+				not all([cint(t.included_in_print_rate) for t in doc.get("taxes")[:cint(tax.row_id) - 1]]):
+			# all rows about the reffered tax should be inclusive
+			_on_previous_row_error("1 - %d" % (tax.row_id,))
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 0b32d47..eb397f8 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -3,10 +3,10 @@
 
 from __future__ import unicode_literals
 import json
-from frappe import _, throw
 from frappe.utils import cint, flt, rounded
 from erpnext.setup.utils import get_company_currency
-from erpnext.controllers.accounts_controller import validate_conversion_rate
+from erpnext.controllers.accounts_controller import validate_conversion_rate, \
+	validate_taxes_and_charges, validate_inclusive_tax
 
 class calculate_taxes_and_totals(object):
 	def __init__(self, doc):
@@ -71,6 +71,9 @@
 
 	def initialize_taxes(self):
 		for tax in self.doc.get("taxes"):
+			validate_taxes_and_charges(tax)
+			validate_inclusive_tax(tax, self.doc)
+
 			tax.item_wise_tax_detail = {}
 			tax_fields = ["total", "tax_amount_after_discount_amount",
 				"tax_amount_for_current_item", "grand_total_for_current_item",
@@ -83,37 +86,8 @@
 			for fieldname in tax_fields:
 				tax.set(fieldname, 0.0)
 
-			self.validate_on_previous_row(tax)
-			self.validate_inclusive_tax(tax)
 			self.doc.round_floats_in(tax)
 
-	def validate_on_previous_row(self, tax):
-		"""
-			validate if a valid row id is mentioned in case of
-			On Previous Row Amount and On Previous Row Total
-		"""
-		if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \
-				(not tax.row_id or cint(tax.row_id) >= tax.idx):
-			throw(_("Please specify a valid Row ID for {0} in row {1}").format(_(tax.doctype), tax.idx))
-
-	def validate_inclusive_tax(self, tax):
-		def _on_previous_row_error(row_range):
-			throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx,
-				row_range))
-
-		if cint(getattr(tax, "included_in_print_rate", None)):
-			if tax.charge_type == "Actual":
-				# inclusive tax cannot be of type Actual
-				throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate").format(tax.idx))
-			elif tax.charge_type == "On Previous Row Amount" and \
-					not cint(self.doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate):
-				# referred row should also be inclusive
-				_on_previous_row_error(tax.row_id)
-			elif tax.charge_type == "On Previous Row Total" and \
-					not all([cint(t.included_in_print_rate) for t in self.doc.get("taxes")[:cint(tax.row_id) - 1]]):
-				# all rows about the reffered tax should be inclusive
-				_on_previous_row_error("1 - %d" % (tax.row_id,))
-
 	def determine_exclusive_rate(self):
 		if not any((cint(tax.included_in_print_rate) for tax in self.doc.get("taxes"))) or \
 			self.doc.doctype not in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index 8911832..d0f27bc 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -19,45 +19,94 @@
 	}
 }
 
-
-var validate_taxes_and_charges = function(cdt, cdn) {
+cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) {
 	var d = locals[cdt][cdn];
+	var msg = "";
 	if(!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
-		msgprint(__("Please select Charge Type first"));
+		msg = __("Please select Charge Type first");
 		d.row_id = "";
 		d.rate = d.tax_amount = 0.0;
 	} else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total') && d.row_id) {
-		msgprint(__("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'"));
+		msg = __("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'");
 		d.row_id = "";
 	} else if((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) {
 		if (d.idx == 1) {
-			msgprint(__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"));
+			msg = __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row");
 			d.charge_type = '';
-		} else if (d.row_i && d.row_id >= d.idx) {
-			msgprint(__("Cannot refer row number greater than or equal to current row number for this Charge type"));
+		} else if (!d.row_id) {
+			msg = __("Please specify a valid Row ID for row {0} in table {1}", [d.idx, __(d.doctype)]);
+			d.row_id = "";
+		} else if(d.row_id && d.row_id >= d.idx) {
+			msg = __("Cannot refer row number greater than or equal to current row number for this Charge type");
 			d.row_id = "";
 		}
 	}
-	validated = false;
-	refresh_field('row_id', d.name, 'taxes');
+	if(msg) {
+		validated = false;
+		refresh_field("taxes");
+		frappe.throw(msg);
+	}
+
+}
+
+cur_frm.cscript.validate_inclusive_tax = function(tax) {
+	var actual_type_error = function() {
+		var msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx])
+		frappe.throw(msg);
+	};
+
+	var on_previous_row_error = function(row_range) {
+		var msg = __("For row {0} in {1}. To include {2} in Item rate, rows {3} must also be included",
+			[tax.idx, __(tax.doctype), tax.charge_type, row_range])
+		frappe.throw(msg);
+	};
+
+	if(cint(tax.included_in_print_rate)) {
+		if(tax.charge_type == "Actual") {
+			// inclusive tax cannot be of type Actual
+			actual_type_error();
+		} else if(tax.charge_type == "On Previous Row Amount" &&
+			!cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_print_rate)) {
+				// referred row should also be an inclusive tax
+				on_previous_row_error(tax.row_id);
+		} else if(tax.charge_type == "On Previous Row Total") {
+			var taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id),
+				function(t) { return cint(t.included_in_print_rate) ? null : t; });
+			if(taxes_not_included.length > 0) {
+				// all rows above this tax should be inclusive
+				on_previous_row_error(tax.row_id == 1 ? "1" : "1 - " + tax.row_id);
+			}
+		}
+	}
 }
 
 frappe.ui.form.on(cur_frm.cscript.tax_table, "row_id", function(frm, cdt, cdn) {
-	validate_taxes_and_charges(cdt, cdn);
+	cur_frm.cscript.validate_taxes_and_charges(cdt, cdn);
 });
 
 frappe.ui.form.on(cur_frm.cscript.tax_table, "rate", function(frm, cdt, cdn) {
-	validate_taxes_and_charges(cdt, cdn);
+	cur_frm.cscript.validate_taxes_and_charges(cdt, cdn);
 });
 
 frappe.ui.form.on(cur_frm.cscript.tax_table, "tax_amount", function(frm, cdt, cdn) {
-	validate_taxes_and_charges(cdt, cdn);
+	cur_frm.cscript.validate_taxes_and_charges(cdt, cdn);
 });
 
 frappe.ui.form.on(cur_frm.cscript.tax_table, "charge_type", function(frm, cdt, cdn) {
-	validate_taxes_and_charges(cdt, cdn);
+	cur_frm.cscript.validate_taxes_and_charges(cdt, cdn);
 });
 
+frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) {
+	var tax = frappe.get_doc(cdt, cdn);
+	try {
+		cur_frm.cscript.validate_taxes_and_charges(cdt, cdn);
+		cur_frm.cscript.validate_inclusive_tax(tax);
+	} catch(e) {
+		tax.included_in_print_rate = 0;
+		refresh_field("included_in_print_rate", tax.name, tax.parentfield);
+		throw e;
+	}
+});
 
 cur_frm.set_query("account_head", "taxes", function(doc) {
 	if(cur_frm.cscript.tax_table == "Sales Taxes and Charges") {
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 4018742..4668398 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -94,7 +94,7 @@
 
 			$.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 });
 
-			me.validate_on_previous_row(tax);
+			cur_frm.cscript.validate_taxes_and_charges(tax.doctype, tax.name);
 			me.validate_inclusive_tax(tax);
 			frappe.model.round_floats_in(tax);
 		});
@@ -129,10 +129,7 @@
 			});
 
 			if(cumulated_tax_fraction && !me.discount_amount_applied) {
-				item.net_amount = flt(
-					(item.amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction),
-					precision("net_amount", item));
-
+				item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction), precision("net_amount", item));
 				item.net_rate = flt(item.net_amount / item.qty, precision("net_rate", item));
 
 				me.set_in_company_currency(item, ["net_rate", "net_amount"]);
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 519b04c..88b4ac4 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -274,22 +274,6 @@
 		this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true);
 	},
 
-	tax_amount: function(doc, cdt, cdn) {
-		this.calculate_taxes_and_totals();
-	},
-
-	row_id: function(doc, cdt, cdn) {
-		var tax = frappe.get_doc(cdt, cdn);
-		try {
-			this.validate_on_previous_row(tax);
-			this.calculate_taxes_and_totals();
-		} catch(e) {
-			tax.row_id = null;
-			refresh_field("row_id", tax.name, tax.parentfield);
-			throw e;
-		}
-	},
-
 	set_dynamic_labels: function() {
 		// What TODO? should we make price list system non-mandatory?
 		this.frm.toggle_reqd("plc_conversion_rate",
@@ -301,6 +285,114 @@
 		this.frm.refresh_fields();
 	},
 
+
+	change_form_labels: function(company_currency) {
+		var me = this;
+		var field_label_map = {};
+
+		var setup_field_label_map = function(fields_list, currency) {
+			$.each(fields_list, function(i, fname) {
+				var docfield = frappe.meta.docfield_map[me.frm.doc.doctype][fname];
+				if(docfield) {
+					var label = __(docfield.label || "").replace(/\([^\)]*\)/g, "");
+					field_label_map[fname] = label.trim() + " (" + currency + ")";
+				}
+			});
+		};
+		setup_field_label_map(["base_total", "base_net_total", "base_total_taxes_and_charges",
+			"base_discount_amount", "base_grand_total", "base_rounded_total", "base_in_words",
+			"base_taxes_and_charges_added", "base_taxes_and_charges_deducted", "total_amount_to_pay",
+			"outstanding_amount", "total_advance", "paid_amount", "write_off_amount"],
+			company_currency);
+
+		setup_field_label_map(["total", "net_total", "total_taxes_and_charges", "discount_amount",
+			"grand_total", "taxes_and_charges_added", "taxes_and_charges_deducted",
+			"rounded_total", "in_words"], this.frm.doc.currency);
+
+		cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency
+			+ " = [?] " + company_currency)
+
+		if(this.frm.doc.price_list_currency && this.frm.doc.price_list_currency!=company_currency) {
+			cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency
+				+ " = [?] " + company_currency)
+		}
+
+		// toggle fields
+		this.frm.toggle_display(["conversion_rate", "base_total", "base_net_total", "base_total_taxes_and_charges",
+			"base_taxes_and_charges_added", "base_taxes_and_charges_deducted",
+			"base_grand_total", "base_rounded_total", "base_in_words", "base_discount_amount"],
+			this.frm.doc.currency != company_currency);
+
+		this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"],
+			this.frm.doc.price_list_currency != company_currency);
+
+		// set labels
+		$.each(field_label_map, function(fname, label) {
+			me.frm.fields_dict[fname].set_label(label);
+		});
+	},
+
+	change_grid_labels: function(company_currency) {
+		var me = this;
+		var field_label_map = {};
+
+		var setup_field_label_map = function(fields_list, currency, parentfield) {
+			var grid_doctype = me.frm.fields_dict[parentfield].grid.doctype;
+			$.each(fields_list, function(i, fname) {
+				var docfield = frappe.meta.docfield_map[grid_doctype][fname];
+				if(docfield) {
+					var label = __(docfield.label || "").replace(/\([^\)]*\)/g, "");
+					field_label_map[grid_doctype + "-" + fname] =
+						label.trim() + " (" + currency + ")";
+				}
+			});
+		}
+
+		setup_field_label_map(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount"],
+			company_currency, "items");
+
+		setup_field_label_map(["rate", "net_rate", "price_list_rate", "amount", "net_amount"],
+			this.frm.doc.currency, "items");
+
+		if(this.frm.fields_dict["taxes"]) {
+			setup_field_label_map(["tax_amount", "total", "tax_amount_after_discount"], this.frm.doc.currency, "taxes");
+
+			setup_field_label_map(["base_tax_amount", "base_total", "base_tax_amount_after_discount"], company_currency, "taxes");
+		}
+
+		if(this.frm.fields_dict["advances"]) {
+			setup_field_label_map(["advance_amount", "allocated_amount"], company_currency, "advances");
+		}
+
+		// toggle columns
+		var item_grid = this.frm.fields_dict["items"].grid;
+		$.each(["base_rate", "base_price_list_rate", "base_amount"], function(i, fname) {
+			if(frappe.meta.get_docfield(item_grid.doctype, fname))
+				item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
+		});
+
+		var show = (cint(cur_frm.doc.discount_amount)) ||
+			((cur_frm.doc.taxes || []).filter(function(d) {return d.included_in_print_rate===1}).length);
+
+		$.each(["net_rate", "net_amount"], function(i, fname) {
+			if(frappe.meta.get_docfield(item_grid.doctype, fname))
+				item_grid.set_column_disp(fname, show);
+		});
+
+		$.each(["base_net_rate", "base_net_amount"], function(i, fname) {
+			if(frappe.meta.get_docfield(item_grid.doctype, fname))
+				item_grid.set_column_disp(fname, (show && (me.frm.doc.currency != company_currency)));
+		});
+
+		// set labels
+		var $wrapper = $(this.frm.wrapper);
+		$.each(field_label_map, function(fname, label) {
+			fname = fname.split("-");
+			var df = frappe.meta.get_docfield(fname[0], fname[1], me.frm.doc.name);
+			if(df) df.label = label;
+		});
+	},
+
 	recalculate: function() {
 		this.calculate_taxes_and_totals();
 	},
@@ -426,60 +518,6 @@
 		});
 	},
 
-	included_in_print_rate: function(doc, cdt, cdn) {
-		var tax = frappe.get_doc(cdt, cdn);
-		try {
-			this.validate_on_previous_row(tax);
-			this.validate_inclusive_tax(tax);
-			this.calculate_taxes_and_totals();
-		} catch(e) {
-			tax.included_in_print_rate = 0;
-			refresh_field("included_in_print_rate", tax.name, tax.parentfield);
-			throw e;
-		}
-	},
-
-	validate_on_previous_row: function(tax) {
-		// validate if a valid row id is mentioned in case of
-		// On Previous Row Amount and On Previous Row Total
-		if((["On Previous Row Amount", "On Previous Row Total"].indexOf(tax.charge_type) != -1) &&
-			(!tax.row_id || cint(tax.row_id) >= tax.idx)) {
-				var msg = __("Please specify a valid Row ID for row {0} in table {1}", [tax.idx, __(tax.doctype)])
-				frappe.throw(msg);
-			}
-	},
-
-	validate_inclusive_tax: function(tax) {
-		var actual_type_error = function() {
-			var msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx])
-			frappe.throw(msg);
-		};
-
-		var on_previous_row_error = function(row_range) {
-			var msg = __("For row {0} in {1}. To include {2} in Item rate, rows {3} must also be included",
-				[tax.idx, __(tax.doctype), tax.charge_type, row_range])
-			frappe.throw(msg);
-		};
-
-		if(cint(tax.included_in_print_rate)) {
-			if(tax.charge_type == "Actual") {
-				// inclusive tax cannot be of type Actual
-				actual_type_error();
-			} else if(tax.charge_type == "On Previous Row Amount" &&
-				!cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_print_rate)) {
-					// referred row should also be an inclusive tax
-					on_previous_row_error(tax.row_id);
-			} else if(tax.charge_type == "On Previous Row Total") {
-				var taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id),
-					function(t) { return cint(t.included_in_print_rate) ? null : t; });
-				if(taxes_not_included.length > 0) {
-					// all rows above this tax should be inclusive
-					on_previous_row_error(tax.row_id == 1 ? "1" : "1 - " + tax.row_id);
-				}
-			}
-		}
-	},
-
 	get_item_wise_taxes_html: function() {
 		var item_tax = {};
 		var tax_accounts = [];
@@ -650,3 +688,19 @@
 
 	cur_frm.cscript.calculate_taxes_and_totals();
 })
+
+frappe.ui.form.on(cur_frm.cscript.tax_table, "rate", function(frm, cdt, cdn) {
+	cur_frm.cscript.calculate_taxes_and_totals();
+})
+
+frappe.ui.form.on(cur_frm.cscript.tax_table, "tax_amount", function(frm, cdt, cdn) {
+	cur_frm.cscript.calculate_taxes_and_totals();
+})
+
+frappe.ui.form.on(cur_frm.cscript.tax_table, "row_id", function(frm, cdt, cdn) {
+	cur_frm.cscript.calculate_taxes_and_totals();
+})
+
+frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) {
+	cur_frm.cscript.calculate_taxes_and_totals();
+})
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index c63939d..4767f51 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -3,7 +3,6 @@
 
 
 {% include 'selling/sales_common.js' %}
-{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
 
 erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
 	onload: function(doc, dt, dn) {
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 15b0e39..bc9d0d1 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -2,7 +2,6 @@
 // License: GNU General Public License v3. See license.txt
 
 {% include 'selling/sales_common.js' %}
-{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
 
 erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
 	refresh: function(doc, dt, dn) {
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index c153f94..5d49e2f 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -2,11 +2,12 @@
 // License: GNU General Public License v3. See license.txt
 
 
+cur_frm.cscript.tax_table = "Sales Taxes and Charges";
+{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
+
 frappe.provide("erpnext.selling");
 frappe.require("assets/erpnext/js/controllers/transaction.js");
 
-{% include "public/js/controllers/accounts.js" %};
-
 cur_frm.email_field = "contact_email";
 
 erpnext.selling.SellingController = erpnext.TransactionController.extend({
@@ -311,109 +312,6 @@
 			}
 		}
 		refresh_field('sales_bom_help');
-	},
-
-	change_form_labels: function(company_currency) {
-		var me = this;
-		var field_label_map = {};
-
-		var setup_field_label_map = function(fields_list, currency) {
-			$.each(fields_list, function(i, fname) {
-				var docfield = frappe.meta.docfield_map[me.frm.doc.doctype][fname];
-				if(docfield) {
-					var label = __(docfield.label || "").replace(/\([^\)]*\)/g, "");
-					field_label_map[fname] = label.trim() + " (" + currency + ")";
-				}
-			});
-		};
-		setup_field_label_map(["base_total", "base_net_total", "base_total_taxes_and_charges",
-			"base_discount_amount", "base_grand_total", "base_rounded_total", "base_in_words",
-			"outstanding_amount", "total_advance", "paid_amount", "write_off_amount"],
-			company_currency);
-
-		setup_field_label_map(["total", "net_total", "total_taxes_and_charges", "discount_amount", "grand_total",
-			"rounded_total", "in_words"], this.frm.doc.currency);
-
-		cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency
-			+ " = [?] " + company_currency)
-
-		if(this.frm.doc.price_list_currency && this.frm.doc.price_list_currency!=company_currency) {
-			cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency
-				+ " = [?] " + company_currency)
-		}
-
-		// toggle fields
-		this.frm.toggle_display(["conversion_rate", "base_total", "base_net_total", "base_total_taxes_and_charges",
-			"base_grand_total", "base_rounded_total", "base_in_words", "base_discount_amount"],
-			this.frm.doc.currency != company_currency);
-
-		this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"],
-			this.frm.doc.price_list_currency != company_currency);
-
-		// set labels
-		$.each(field_label_map, function(fname, label) {
-			me.frm.fields_dict[fname].set_label(label);
-		});
-	},
-
-	change_grid_labels: function(company_currency) {
-		var me = this;
-		var field_label_map = {};
-
-		var setup_field_label_map = function(fields_list, currency, parentfield) {
-			var grid_doctype = me.frm.fields_dict[parentfield].grid.doctype;
-			$.each(fields_list, function(i, fname) {
-				var docfield = frappe.meta.docfield_map[grid_doctype][fname];
-				if(docfield) {
-					var label = __(docfield.label || "").replace(/\([^\)]*\)/g, "");
-					field_label_map[grid_doctype + "-" + fname] =
-						label.trim() + " (" + currency + ")";
-				}
-			});
-		}
-
-		setup_field_label_map(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount"],
-			company_currency, "items");
-
-		setup_field_label_map(["rate", "net_rate", "price_list_rate", "amount", "net_amount"],
-			this.frm.doc.currency, "items");
-
-		setup_field_label_map(["tax_amount", "total", "tax_amount_after_discount"], this.frm.doc.currency, "taxes");
-
-		setup_field_label_map(["base_tax_amount", "base_total", "base_tax_amount_after_discount"], company_currency, "taxes");
-
-		if(this.frm.fields_dict["advances"]) {
-			setup_field_label_map(["advance_amount", "allocated_amount"], company_currency,
-				"advances");
-		}
-
-		// toggle columns
-		var item_grid = this.frm.fields_dict["items"].grid;
-		$.each(["base_rate", "base_price_list_rate", "base_amount"], function(i, fname) {
-			if(frappe.meta.get_docfield(item_grid.doctype, fname))
-				item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
-		});
-
-		var show = (cint(cur_frm.doc.discount_amount)) ||
-			((cur_frm.doc.taxes || []).filter(function(d) {return d.included_in_print_rate===1}).length);
-
-		$.each(["net_rate", "net_amount"], function(i, fname) {
-			if(frappe.meta.get_docfield(item_grid.doctype, fname))
-				item_grid.set_column_disp(fname, show);
-		});
-
-		$.each(["base_net_rate", "base_net_amount"], function(i, fname) {
-			if(frappe.meta.get_docfield(item_grid.doctype, fname))
-				item_grid.set_column_disp(fname, (show && (me.frm.doc.currency != company_currency)));
-		});
-
-		// set labels
-		var $wrapper = $(this.frm.wrapper);
-		$.each(field_label_map, function(fname, label) {
-			fname = fname.split("-");
-			var df = frappe.meta.get_docfield(fname[0], fname[1], me.frm.doc.name);
-			if(df) df.label = label;
-		});
 	}
 });
 
@@ -433,7 +331,3 @@
 		})
 	}
 })
-
-frappe.ui.form.on("Sales Taxes and Charges", "rate", function(frm, cdt, cdn) {
-	cur_frm.cscript.calculate_taxes_and_totals();
-})
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 51afa2c..185c242 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -2,7 +2,6 @@
 // License: GNU General Public License v3. See license.txt
 
 {% include 'selling/sales_common.js' %};
-{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
 
 frappe.provide("erpnext.stock");
 frappe.provide("erpnext.stock.delivery_note");
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 50a1073..a7e6620 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -2,7 +2,6 @@
 // License: GNU General Public License v3. See license.txt
 
 {% include 'buying/doctype/purchase_common/purchase_common.js' %};
-{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
 
 frappe.provide("erpnext.stock");
 erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend({