fix: Auto tax calculations in Payment Entry
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 939f354..d3ac3a6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -1087,6 +1087,8 @@
 
 	initialize_taxes: function(frm) {
 		$.each(frm.doc["taxes"] || [], function(i, tax) {
+			frm.events.validate_taxes_and_charges(tax);
+			frm.events.validate_inclusive_tax(tax);
 			tax.item_wise_tax_detail = {};
 			let tax_fields = ["total",  "tax_fraction_for_current_item",
 				"grand_total_fraction_for_current_item"];
@@ -1101,6 +1103,73 @@
 		});
 	},
 
+	validate_taxes_and_charges: function(d) {
+		let msg = "";
+
+		if (d.account_head && !d.description) {
+			// set description from account head
+			d.description = d.account_head.split(' - ').slice(0, -1).join(' - ');
+		}
+
+		if (!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
+			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.charge_type == 'On Paid Amount') && d.row_id) {
+			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) {
+				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_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 = "";
+			}
+		}
+		if (msg) {
+			frappe.validated = false;
+			refresh_field("taxes");
+			frappe.throw(msg);
+		}
+
+	},
+
+	validate_inclusive_tax: function(tax) {
+		let actual_type_error = function() {
+			let msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx])
+			frappe.throw(msg);
+		};
+
+		let on_previous_row_error = function(row_range) {
+			let 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_paid_amount)) {
+			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_paid_amount)
+			) {
+				// referred row should also be an inclusive tax
+				on_previous_row_error(tax.row_id);
+			} else if(tax.charge_type == "On Previous Row Total") {
+				let taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id),
+					function(t) { return cint(t.included_in_paid_amount) ? 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);
+				}
+			}
+		}
+	},
+
 	determine_exclusive_rate: function(frm) {
 		let has_inclusive_tax = false;
 		$.each(frm.doc["taxes"] || [], function(i, row) {
@@ -1110,8 +1179,7 @@
 
 		let cumulated_tax_fraction = 0.0;
 		$.each(frm.doc["taxes"] || [], function(i, tax) {
-			let current_tax_fraction = frm.events.get_current_tax_fraction(frm, tax);
-			tax.tax_fraction_for_current_item = current_tax_fraction[0];
+			tax.tax_fraction_for_current_item = frm.events.get_current_tax_fraction(frm, tax);
 
 			if(i==0) {
 				tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
@@ -1132,9 +1200,7 @@
 		if(cint(tax.included_in_paid_amount)) {
 			let tax_rate = tax.rate;
 
-			if (tax.charge_type == "Actual") {
-				current_tax_fraction = tax.tax_amount/(frm.doc.paid_amount_after_tax + frm.doc.tax_amount);
-			} else if(tax.charge_type == "On Paid Amount") {
+			if(tax.charge_type == "On Paid Amount") {
 				current_tax_fraction = (tax_rate / 100.0);
 			} else if(tax.charge_type == "On Previous Row Amount") {
 				current_tax_fraction = (tax_rate / 100.0) *
@@ -1147,7 +1213,6 @@
 
 		if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") {
 			current_tax_fraction *= -1;
-			inclusive_tax_amount_per_qty *= -1;
 		}
 		return current_tax_fraction;
 	},
@@ -1207,10 +1272,8 @@
 				frappe.throw(
 					__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"));
 			}
-			if (!tax.row_id) {
-				tax.row_id = tax.idx - 1;
-			}
 		}
+
 		if(tax.charge_type == "Actual") {
 			current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax))
 		} else if(tax.charge_type == "On Paid Amount") {
@@ -1296,6 +1359,11 @@
 	included_in_paid_amount: function(frm) {
 		frm.events.apply_taxes(frm);
 		frm.events.set_unallocated_amount(frm);
+	},
+
+	charge_type: function(frm) {
+		frm.events.apply_taxes(frm);
+		frm.events.set_unallocated_amount(frm);
 	}
 })
 
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 2c6deb3..70b3873 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -16,9 +16,11 @@
 from erpnext.controllers.accounts_controller import AccountsController, get_supplier_block_status
 from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
 from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
-
 from six import string_types, iteritems
 
+from erpnext.controllers.accounts_controller import validate_conversion_rate, \
+	validate_taxes_and_charges, validate_inclusive_tax
+
 class InvalidPaymentEntry(ValidationError):
 	pass
 
@@ -407,20 +409,6 @@
 		net_total = self.paid_amount
 		included_in_paid_amount = 0
 
-		if self.get('references'):
-			for doc in self.get('references'):
-				if doc.reference_doctype == 'Purchase Order':
-					reference_doclist.append(doc.reference_name)
-
-			if reference_doclist:
-				order_amount = frappe.db.get_all('Purchase Order', fields=['sum(net_total)'],
-					filters = {'name': ('in', reference_doclist), 'docstatus': 1,
-						'apply_tds': 1}, as_list=1)
-
-				if order_amount:
-					net_total = order_amount[0][0]
-					included_in_paid_amount = 1
-
 		# Adding args as purchase invoice to get TDS amount
 		args = frappe._dict({
 			'company': self.company,
@@ -719,9 +707,9 @@
 			if account_currency != self.company_currency:
 				frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency))
 
-			if (self.payment_type == 'Pay' and self.advance_tax_account) or self.payment_type == 'Receive':
+			if self.payment_type == 'Pay':
 				dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
-			elif (self.payment_type == 'Receive' and self.advance_tax_account) or self.payment_type == 'Pay':
+			elif self.payment_type == 'Receive':
 				dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
 
 			payment_or_advance_account = self.get_party_account_for_taxes()
@@ -747,6 +735,8 @@
 					if account_currency==self.company_currency
 					else d.tax_amount,
 					"cost_center": self.cost_center,
+					"party_type": self.party_type,
+					"party": self.party
 				}, account_currency, item=d))
 
 	def add_deductions_gl_entries(self, gl_entries):
@@ -770,9 +760,9 @@
 	def get_party_account_for_taxes(self):
 		if self.advance_tax_account:
 			return self.advance_tax_account
-		elif self.payment_type == 'Pay':
-			return self.paid_from
 		elif self.payment_type == 'Receive':
+			return self.paid_from
+		elif self.payment_type == 'Pay':
 			return self.paid_to
 
 	def update_advance_paid(self):
@@ -823,6 +813,9 @@
 
 	def initialize_taxes(self):
 		for tax in self.get("taxes"):
+			validate_taxes_and_charges(tax)
+			validate_inclusive_tax(tax, self)
+
 			tax_fields = ["total", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
 
 			if tax.charge_type != "Actual":
@@ -918,15 +911,11 @@
 		if cint(tax.included_in_paid_amount):
 			tax_rate = tax.rate
 
-			if tax.charge_type == 'Actual':
-				current_tax_fraction = tax.tax_amount/ (self.paid_amount_after_tax + tax.tax_amount)
-			elif tax.charge_type == "On Paid Amount":
+			if tax.charge_type == "On Paid Amount":
 				current_tax_fraction = tax_rate / 100.0
-
 			elif tax.charge_type == "On Previous Row Amount":
 				current_tax_fraction = (tax_rate / 100.0) * \
 					self.get("taxes")[cint(tax.row_id) - 1].tax_fraction_for_current_item
-
 			elif tax.charge_type == "On Previous Row Total":
 				current_tax_fraction = (tax_rate / 100.0) * \
 					self.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
@@ -1626,6 +1615,13 @@
 			paid_amount = received_amount * doc.get('conversion_rate', 1)
 			if dt == "Employee Advance":
 				paid_amount = received_amount * doc.get('exchange_rate', 1)
+
+	if dt == "Purchase Order" and doc.apply_tds:
+		if party_account_currency == bank.account_currency:
+			paid_amount = received_amount = doc.base_net_total
+		else:
+			paid_amount = received_amount = doc.base_net_total * doc.get('exchange_rate', 1)
+
 	return paid_amount, received_amount
 
 def apply_early_payment_discount(paid_amount, received_amount, doc):
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index 9b07645..1fa68e0 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -218,6 +218,7 @@
   },
   {
    "default": "0",
+   "depends_on": "eval:['Purchase Taxes and Charges Template', 'Payment Entry'].includes(parent.doctype)",
    "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
    "fieldname": "included_in_paid_amount",
    "fieldtype": "Check",
@@ -227,7 +228,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-06-09 11:48:25.335733",
+ "modified": "2021-06-14 01:43:50.750455",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Taxes and Charges",
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
index 170d34e..1b7a0fe 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
@@ -195,6 +195,7 @@
   },
   {
    "default": "0",
+   "depends_on": "eval:['Sales Taxes and Charges Template', 'Payment Entry'].includes(parent.doctype)",
    "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
    "fieldname": "included_in_paid_amount",
    "fieldtype": "Check",
@@ -205,7 +206,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-06-09 11:48:04.691596",
+ "modified": "2021-06-14 01:44:36.899147",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Taxes and Charges",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 7c6061d..a507159 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1192,7 +1192,7 @@
 
 
 def validate_taxes_and_charges(tax):
-	if tax.charge_type in ['Actual', 'On Net Total'] and tax.row_id:
+	if tax.charge_type in ['Actual', 'On Net Total', 'On Paid Amount'] 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']:
 		if cint(tax.idx) == 1:
@@ -1209,23 +1209,23 @@
 
 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))
+		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,))
-		elif tax.get("category") == "Valuation":
-			frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
+	for fieldname in ['included_in_print_rate', 'included_in_paid_amount']:
+		if cint(getattr(tax, fieldname, 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 or Paid Amount").format(tax.idx))
+			elif tax.charge_type == "On Previous Row Amount" and \
+					not cint(doc.get("taxes")[cint(tax.row_id) - 1].get(fieldname)):
+				# 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.get(fieldname) for t in doc.get("taxes")[:cint(tax.row_id) - 1])]):
+				# all rows about the referred tax should be inclusive
+				_on_previous_row_error("1 - %d" % (cint(tax.row_id),))
+			elif tax.get("category") == "Valuation":
+				frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
 
 
 def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):