Merge branch 'develop' into trim-custom-field-length
diff --git a/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.json b/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.json
index 3eb0d74..67acb26 100644
--- a/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.json
+++ b/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.json
@@ -1,63 +1,33 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2014-10-02 13:35:44.155278", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 1, 
+ "actions": [],
+ "creation": "2014-10-02 13:35:44.155278",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "company"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Company", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company"
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2016-07-11 03:28:00.505946", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Fiscal Year Company", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_seen": 0
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-09-28 18:01:53.495929",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Fiscal Year Company",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json
index b7bbb74..20678d7 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.json
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json
@@ -13,10 +13,12 @@
   "voucher_type",
   "naming_series",
   "finance_book",
+  "tax_withholding_category",
   "column_break1",
   "from_template",
   "company",
   "posting_date",
+  "apply_tds",
   "2_add_edit_gl_entries",
   "accounts",
   "section_break99",
@@ -498,16 +500,32 @@
    "options": "Journal Entry Template",
    "print_hide": 1,
    "report_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.apply_tds",
+   "fieldname": "tax_withholding_category",
+   "fieldtype": "Link",
+   "label": "Tax Withholding Category",
+   "mandatory_depends_on": "eval:doc.apply_tds",
+   "options": "Tax Withholding Category"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:['Credit Note', 'Debit Note'].includes(doc.voucher_type)",
+   "fieldname": "apply_tds",
+   "fieldtype": "Check",
+   "label": "Apply Tax Withholding Amount "
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 176,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-30 13:56:01.121995",
+ "modified": "2021-09-09 15:31:14.484029",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Journal Entry",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 24368f0..e568a82 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -15,6 +15,9 @@
 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 erpnext.accounts.party import get_party_account
 from erpnext.accounts.utils import (
 	check_if_stock_and_account_balance_synced,
@@ -57,7 +60,8 @@
 
 		self.validate_against_jv()
 		self.validate_reference_doc()
-		self.set_against_account()
+		if self.docstatus == 0:
+			self.set_against_account()
 		self.create_remarks()
 		self.set_print_format_fields()
 		self.validate_expense_claim()
@@ -66,6 +70,10 @@
 		self.set_account_and_party_balance()
 		self.validate_inter_company_accounts()
 		self.validate_stock_accounts()
+
+		if self.docstatus == 0:
+			self.apply_tax_withholding()
+
 		if not self.title:
 			self.title = self.get_title()
 
@@ -139,6 +147,72 @@
 				frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
 					.format(account), StockAccountInvalidTransaction)
 
+	def apply_tax_withholding(self):
+		from erpnext.accounts.report.general_ledger.general_ledger import get_account_type_map
+
+		if not self.apply_tds or self.voucher_type not in ('Debit Note', 'Credit Note'):
+			return
+
+		parties = [d.party for d in self.get('accounts') if d.party]
+		parties = list(set(parties))
+
+		if len(parties) > 1:
+			frappe.throw(_("Cannot apply TDS against multiple parties in one entry"))
+
+		account_type_map = get_account_type_map(self.company)
+		party_type = 'supplier' if self.voucher_type == 'Credit Note' else 'customer'
+		doctype = 'Purchase Invoice' if self.voucher_type == 'Credit Note' else 'Sales Invoice'
+		debit_or_credit = 'debit_in_account_currency' if self.voucher_type == 'Credit Note' else 'credit_in_account_currency'
+		rev_debit_or_credit = 'credit_in_account_currency' if debit_or_credit == 'debit_in_account_currency' else 'debit_in_account_currency'
+
+		party_account = get_party_account(party_type.title(), parties[0], self.company)
+
+		net_total = sum(d.get(debit_or_credit) for d in self.get('accounts') if account_type_map.get(d.account)
+			not in ('Tax', 'Chargeable'))
+
+		party_amount = sum(d.get(rev_debit_or_credit) for d in self.get('accounts') if d.account == party_account)
+
+		inv = frappe._dict({
+			party_type: parties[0],
+			'doctype': doctype,
+			'company': self.company,
+			'posting_date': self.posting_date,
+			'net_total': net_total
+		})
+
+		tax_withholding_details = get_party_tax_withholding_details(inv, self.tax_withholding_category)
+
+		if not tax_withholding_details:
+			return
+
+		accounts = []
+		for d in self.get('accounts'):
+			if d.get('account') == tax_withholding_details.get("account_head"):
+				d.update({
+					'account': tax_withholding_details.get("account_head"),
+					debit_or_credit: tax_withholding_details.get('tax_amount')
+				})
+
+			accounts.append(d.get('account'))
+
+			if d.get('account') == party_account:
+				d.update({
+					rev_debit_or_credit: party_amount - tax_withholding_details.get('tax_amount')
+				})
+
+		if not accounts or tax_withholding_details.get("account_head") not in accounts:
+			self.append("accounts", {
+				'account': tax_withholding_details.get("account_head"),
+				rev_debit_or_credit: tax_withholding_details.get('tax_amount'),
+				'against_account': parties[0]
+			})
+
+		to_remove = [d for d in self.get('accounts')
+			if not d.get(rev_debit_or_credit) and d.account == tax_withholding_details.get("account_head")]
+
+		for d in to_remove:
+			self.remove(d)
+
 	def update_inter_company_jv(self):
 		if self.voucher_type == "Inter Company Journal Entry" and self.inter_company_journal_entry_reference:
 			frappe.db.set_value("Journal Entry", self.inter_company_journal_entry_reference,\
diff --git a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
index 43eb0b6..8961167 100644
--- a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
+++ b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
@@ -93,6 +93,7 @@
    "options": "Payment Term"
   },
   {
+   "depends_on": "exchange_gain_loss",
    "fieldname": "exchange_gain_loss",
    "fieldtype": "Currency",
    "label": "Exchange Gain/Loss",
@@ -103,7 +104,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-04-21 13:30:11.605388",
+ "modified": "2021-09-26 17:06:55.597389",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Entry Reference",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index dde0328..55e288e 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -1303,6 +1303,7 @@
    "fetch_from": "supplier.is_internal_supplier",
    "fieldname": "is_internal_supplier",
    "fieldtype": "Check",
+   "ignore_user_permissions": 1,
    "label": "Is Internal Supplier",
    "read_only": 1
   },
@@ -1400,7 +1401,7 @@
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-09-21 09:27:39.967811",
+ "modified": "2021-09-28 13:10:28.351810",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index dd4a005..1c9943f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -1146,6 +1146,12 @@
 		if not self.apply_tds:
 			return
 
+		if self.apply_tds and not self.get('tax_withholding_category'):
+			self.tax_withholding_category = frappe.db.get_value('Supplier', self.supplier, 'tax_withholding_category')
+
+		if not self.tax_withholding_category:
+			return
+
 		tax_withholding_details = get_party_tax_withholding_details(self, self.tax_withholding_category)
 
 		if not tax_withholding_details:
diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json
index 63dfff8..9fcbf5c 100644
--- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json
+++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json
@@ -97,6 +97,7 @@
    "width": "100px"
   },
   {
+   "depends_on": "exchange_gain_loss",
    "fieldname": "exchange_gain_loss",
    "fieldtype": "Currency",
    "label": "Exchange Gain/Loss",
@@ -104,6 +105,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "exchange_gain_loss",
    "fieldname": "ref_exchange_rate",
    "fieldtype": "Float",
    "label": "Reference Exchange Rate",
@@ -115,7 +117,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-04-20 16:26:53.820530",
+ "modified": "2021-09-26 15:47:28.167371",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice Advance",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index f383b52..2d6c04e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1953,6 +1953,7 @@
    "fetch_from": "customer.represents_company",
    "fieldname": "represents_company",
    "fieldtype": "Link",
+   "ignore_user_permissions": 1,
    "label": "Represents Company",
    "options": "Company",
    "read_only": 1
@@ -2022,7 +2023,7 @@
    "link_fieldname": "consolidated_invoice"
   }
  ],
- "modified": "2021-09-21 09:27:50.191854",
+ "modified": "2021-09-28 13:09:34.391799",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 619dc7b..bdd30f3 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -2352,6 +2352,7 @@
 	if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
 		address = frappe.get_doc({
 			"address_line1": "_Test Address Line 1",
+			"address_line2": "_Test Address Line 2",
 			"address_title": "_Test Address for Eway bill",
 			"address_type": "Billing",
 			"city": "_Test City",
@@ -2373,11 +2374,12 @@
 
 		address.save()
 
-	if not frappe.db.exists('Address', '_Test Customer-Address for Eway bill-Shipping'):
+	if not frappe.db.exists('Address', '_Test Customer-Address for Eway bill-Billing'):
 		address = frappe.get_doc({
 			"address_line1": "_Test Address Line 1",
+			"address_line2": "_Test Address Line 2",
 			"address_title": "_Test Customer-Address for Eway bill",
-			"address_type": "Shipping",
+			"address_type": "Billing",
 			"city": "_Test City",
 			"state": "Test State",
 			"country": "India",
@@ -2397,9 +2399,34 @@
 
 		address.save()
 
+	if not frappe.db.exists('Address', '_Test Customer-Address for Eway bill-Shipping'):
+		address = frappe.get_doc({
+			"address_line1": "_Test Address Line 1",
+			"address_line2": "_Test Address Line 2",
+			"address_title": "_Test Customer-Address for Eway bill",
+			"address_type": "Shipping",
+			"city": "_Test City",
+			"state": "Test State",
+			"country": "India",
+			"doctype": "Address",
+			"is_primary_address": 1,
+			"phone": "+910000000000",
+			"gst_state": "Maharashtra",
+			"gst_state_number": "27",
+			"pincode": "410098"
+		}).insert()
+
+		address.append("links", {
+			"link_doctype": "Customer",
+			"link_name": "_Test Customer"
+		})
+
+		address.save()
+
 	if not frappe.db.exists('Address', '_Test Dispatch-Address for Eway bill-Shipping'):
 		address = frappe.get_doc({
 			"address_line1": "_Test Dispatch Address Line 1",
+			"address_line2": "_Test Dispatch Address Line 2",
 			"address_title": "_Test Dispatch-Address for Eway bill",
 			"address_type": "Shipping",
 			"city": "_Test City",
@@ -2414,11 +2441,6 @@
 			"pincode": "1100101"
 		}).insert()
 
-		address.append("links", {
-			"link_doctype": "Company",
-			"link_name": "_Test Company"
-		})
-
 		address.save()
 
 def make_test_transporter_for_ewaybill():
@@ -2458,7 +2480,8 @@
 
 	si.distance = 2000
 	si.company_address = "_Test Address for Eway bill-Billing"
-	si.customer_address = "_Test Customer-Address for Eway bill-Shipping"
+	si.customer_address = "_Test Customer-Address for Eway bill-Billing"
+	si.shipping_address_name = "_Test Customer-Address for Eway bill-Shipping"
 	si.dispatch_address_name = "_Test Dispatch-Address for Eway bill-Shipping"
 	si.vehicle_no = "KA12KA1234"
 	si.gst_category = "Registered Regular"
diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json
index 29422d6..f92b57a 100644
--- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json
+++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json
@@ -98,6 +98,7 @@
    "width": "120px"
   },
   {
+   "depends_on": "exchange_gain_loss",
    "fieldname": "exchange_gain_loss",
    "fieldtype": "Currency",
    "label": "Exchange Gain/Loss",
@@ -105,6 +106,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "exchange_gain_loss",
    "fieldname": "ref_exchange_rate",
    "fieldtype": "Float",
    "label": "Reference Exchange Rate",
@@ -116,7 +118,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-06-04 20:25:49.832052",
+ "modified": "2021-09-26 15:47:46.911595",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice Advance",
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index fa4ea21..16ef5fc 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -100,6 +100,7 @@
 	for account_detail in tax_withholding.accounts:
 		if company == account_detail.company:
 			return frappe._dict({
+				"tax_withholding_category": tax_withholding_category,
 				"account_head": account_detail.account,
 				"rate": tax_rate_detail.tax_withholding_rate,
 				"from_date": tax_rate_detail.from_date,
@@ -206,18 +207,39 @@
 
 def get_invoice_vouchers(parties, tax_details, company, party_type='Supplier'):
 	dr_or_cr = 'credit' if party_type == 'Supplier' else 'debit'
+	doctype = 'Purchase Invoice' if party_type == 'Supplier' else 'Sales Invoice'
 
 	filters = {
-		dr_or_cr: ['>', 0],
 		'company': company,
-		'party_type': party_type,
-		'party': ['in', parties],
+		frappe.scrub(party_type): ['in', parties],
 		'posting_date': ['between', (tax_details.from_date, tax_details.to_date)],
 		'is_opening': 'No',
-		'is_cancelled': 0
+		'docstatus': 1
 	}
 
-	return frappe.get_all('GL Entry', filters=filters, distinct=1, pluck="voucher_no") or [""]
+	if not tax_details.get('consider_party_ledger_amount') and doctype != "Sales Invoice":
+		filters.update({
+			'apply_tds': 1,
+			'tax_withholding_category': tax_details.get('tax_withholding_category')
+		})
+
+	invoices = frappe.get_all(doctype, filters=filters, pluck="name") or [""]
+
+	journal_entries = frappe.db.sql("""
+		SELECT j.name
+			FROM `tabJournal Entry` j, `tabJournal Entry Account` ja
+		WHERE
+			j.docstatus = 1
+			AND j.is_opening = 'No'
+			AND j.posting_date between %s and %s
+			AND ja.{dr_or_cr} > 0
+			AND ja.party in %s
+	""".format(dr_or_cr=dr_or_cr), (tax_details.from_date, tax_details.to_date, tuple(parties)), as_list=1)
+
+	if journal_entries:
+		journal_entries = journal_entries[0]
+
+	return invoices + journal_entries
 
 def get_advance_vouchers(parties, company=None, from_date=None, to_date=None, party_type='Supplier'):
 	# for advance vouchers, debit and credit is reversed
diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
index 8a88d79..84b364b 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
@@ -176,6 +176,29 @@
 		for d in invoices:
 			d.cancel()
 
+	def test_multi_category_single_supplier(self):
+		frappe.db.set_value("Supplier", "Test TDS Supplier5", "tax_withholding_category", "Test Service Category")
+		invoices = []
+
+		pi = create_purchase_invoice(supplier = "Test TDS Supplier5", rate = 500, do_not_save=True)
+		pi.tax_withholding_category = "Test Service Category"
+		pi.save()
+		pi.submit()
+		invoices.append(pi)
+
+		# Second Invoice will apply TDS checked
+		pi1 = create_purchase_invoice(supplier = "Test TDS Supplier5", rate = 2500, do_not_save=True)
+		pi1.tax_withholding_category = "Test Goods Category"
+		pi1.save()
+		pi1.submit()
+		invoices.append(pi1)
+
+		self.assertEqual(pi1.taxes[0].tax_amount, 250)
+
+		#delete invoices to avoid clashing
+		for d in invoices:
+			d.cancel()
+
 def cancel_invoices():
 	purchase_invoices = frappe.get_all("Purchase Invoice", {
 		'supplier': ['in', ['Test TDS Supplier', 'Test TDS Supplier1', 'Test TDS Supplier2']],
@@ -251,7 +274,8 @@
 
 def create_records():
 	# create a new suppliers
-	for name in ['Test TDS Supplier', 'Test TDS Supplier1', 'Test TDS Supplier2', 'Test TDS Supplier3', 'Test TDS Supplier4']:
+	for name in ['Test TDS Supplier', 'Test TDS Supplier1', 'Test TDS Supplier2', 'Test TDS Supplier3',
+		'Test TDS Supplier4', 'Test TDS Supplier5']:
 		if frappe.db.exists('Supplier', name):
 			continue
 
@@ -390,3 +414,39 @@
 				'account': 'TDS - _TC'
 			}]
 		}).insert()
+
+	if not frappe.db.exists("Tax Withholding Category", "Test Service Category"):
+		frappe.get_doc({
+			"doctype": "Tax Withholding Category",
+			"name": "Test Service Category",
+			"category_name": "Test Service Category",
+			"rates": [{
+				'from_date': fiscal_year[1],
+				'to_date': fiscal_year[2],
+				'tax_withholding_rate': 10,
+				'single_threshold': 2000,
+				'cumulative_threshold': 2000
+			}],
+			"accounts": [{
+				'company': '_Test Company',
+				'account': 'TDS - _TC'
+			}]
+		}).insert()
+
+	if not frappe.db.exists("Tax Withholding Category", "Test Goods Category"):
+		frappe.get_doc({
+			"doctype": "Tax Withholding Category",
+			"name": "Test Goods Category",
+			"category_name": "Test Goods Category",
+			"rates": [{
+				'from_date': fiscal_year[1],
+				'to_date': fiscal_year[2],
+				'tax_withholding_rate': 10,
+				'single_threshold': 2000,
+				'cumulative_threshold': 2000
+			}],
+			"accounts": [{
+				'company': '_Test Company',
+				'account': 'TDS - _TC'
+			}]
+		}).insert()
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.json b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.json
index dfc4b18..91f0798 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.json
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.json
@@ -1,12 +1,15 @@
 {
- "add_total_row": 0,
+ "add_total_row": 1,
+ "columns": [],
  "creation": "2018-08-21 11:25:00.551823",
+ "disable_prepared_report": 0,
  "disabled": 0,
  "docstatus": 0,
  "doctype": "Report",
+ "filters": [],
  "idx": 0,
  "is_standard": "Yes",
- "modified": "2018-09-21 11:25:00.551823",
+ "modified": "2021-09-20 17:43:39.518851",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "TDS Computation Summary",
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
index c4a8c7a..536df1f 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
@@ -2,11 +2,10 @@
 
 import frappe
 from frappe import _
-from frappe.utils import flt
 
-from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
-	get_advance_vouchers,
-	get_debit_note_amount,
+from erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly import (
+	get_result,
+	get_tds_docs,
 )
 from erpnext.accounts.utils import get_fiscal_year
 
@@ -17,9 +16,12 @@
 	filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name')
 
 	columns = get_columns(filters)
-	res = get_result(filters)
+	tds_docs, tds_accounts, tax_category_map = get_tds_docs(filters)
 
-	return columns, res
+	res = get_result(filters, tds_docs, tds_accounts, tax_category_map)
+	final_result = group_by_supplier_and_category(res)
+
+	return columns, final_result
 
 def validate_filters(filters):
 	''' Validate if dates are properly set and lie in the same fiscal year'''
@@ -33,81 +35,39 @@
 
 	filters["fiscal_year"] = from_year
 
-def get_result(filters):
-	# if no supplier selected, fetch data for all tds applicable supplier
-	# else fetch relevant data for selected supplier
-	pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id"
-	fields = ["name", pan+" as pan", "tax_withholding_category", "supplier_type", "supplier_name"]
+def group_by_supplier_and_category(data):
+	supplier_category_wise_map = {}
 
-	if filters.supplier:
-		filters.supplier = frappe.db.get_list('Supplier',
-			{"name": filters.supplier}, fields)
-	else:
-		filters.supplier = frappe.db.get_list('Supplier',
-			{"tax_withholding_category": ["!=", ""]}, fields)
+	for row in data:
+		supplier_category_wise_map.setdefault((row.get('supplier'), row.get('section_code')), {
+			'pan': row.get('pan'),
+			'supplier': row.get('supplier'),
+			'supplier_name': row.get('supplier_name'),
+			'section_code': row.get('section_code'),
+			'entity_type': row.get('entity_type'),
+			'tds_rate': row.get('tds_rate'),
+			'total_amount_credited': 0.0,
+			'tds_deducted': 0.0
+		})
 
+		supplier_category_wise_map.get((row.get('supplier'), row.get('section_code')))['total_amount_credited'] += \
+			row.get('total_amount_credited', 0.0)
+
+		supplier_category_wise_map.get((row.get('supplier'), row.get('section_code')))['tds_deducted'] += \
+			row.get('tds_deducted', 0.0)
+
+	final_result = get_final_result(supplier_category_wise_map)
+
+	return final_result
+
+
+def get_final_result(supplier_category_wise_map):
 	out = []
-	for supplier in filters.supplier:
-		tds = frappe.get_doc("Tax Withholding Category", supplier.tax_withholding_category)
-		rate = [d.tax_withholding_rate for d in tds.rates if d.fiscal_year == filters.fiscal_year]
-
-		if rate:
-			rate = rate[0]
-
-		try:
-			account = [d.account for d in tds.accounts if d.company == filters.company][0]
-
-		except IndexError:
-			account = []
-		total_invoiced_amount, tds_deducted = get_invoice_and_tds_amount(supplier.name, account,
-			filters.company, filters.from_date, filters.to_date, filters.fiscal_year)
-
-		if total_invoiced_amount or tds_deducted:
-			row = [supplier.pan, supplier.name]
-
-			if filters.naming_series == 'Naming Series':
-				row.append(supplier.supplier_name)
-
-			row.extend([tds.name, supplier.supplier_type, rate, total_invoiced_amount, tds_deducted])
-			out.append(row)
+	for key, value in supplier_category_wise_map.items():
+		out.append(value)
 
 	return out
 
-def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date, fiscal_year):
-	''' calculate total invoice amount and total tds deducted for given supplier  '''
-
-	entries = frappe.db.sql("""
-		select voucher_no, credit
-		from `tabGL Entry`
-		where party in (%s) and credit > 0
-			and company=%s and is_cancelled = 0
-			and posting_date between %s and %s
-	""", (supplier, company, from_date, to_date), as_dict=1)
-
-	supplier_credit_amount = flt(sum(d.credit for d in entries))
-
-	vouchers = [d.voucher_no for d in entries]
-	vouchers += get_advance_vouchers([supplier], company=company,
-		from_date=from_date, to_date=to_date)
-
-	tds_deducted = 0
-	if vouchers:
-		tds_deducted = flt(frappe.db.sql("""
-			select sum(credit)
-			from `tabGL Entry`
-			where account=%s and posting_date between %s and %s
-				and company=%s and credit > 0 and voucher_no in ({0})
-		""".format(', '.join("'%s'" % d for d in vouchers)),
-			(account, from_date, to_date, company))[0][0])
-
-	date_range_filter = [fiscal_year, from_date, to_date]
-
-	debit_note_amount = get_debit_note_amount([supplier], date_range_filter, company=company)
-
-	total_invoiced_amount = supplier_credit_amount + tds_deducted - debit_note_amount
-
-	return total_invoiced_amount, tds_deducted
-
 def get_columns(filters):
 	columns = [
 		{
@@ -149,7 +109,7 @@
 		{
 			"label": _("TDS Rate %"),
 			"fieldname": "tds_rate",
-			"fieldtype": "Float",
+			"fieldtype": "Percent",
 			"width": 90
 		},
 		{
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
index 72de318..ff2aa30 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
@@ -16,69 +16,6 @@
 			"label": __("Supplier"),
 			"fieldtype": "Link",
 			"options": "Supplier",
-			"get_query": function() {
-				return {
-					"filters": {
-						"tax_withholding_category": ["!=", ""],
-					}
-				}
-			},
-			on_change: function() {
-				frappe.query_report.set_filter_value("purchase_invoice", "");
-				frappe.query_report.refresh();
-			}
-		},
-		{
-			"fieldname":"purchase_invoice",
-			"label": __("Purchase Invoice"),
-			"fieldtype": "Link",
-			"options": "Purchase Invoice",
-			"get_query": function() {
-				return {
-					"filters": {
-						"name": ["in", frappe.query_report.invoices]
-					}
-				}
-			},
-			on_change: function() {
-				let supplier = frappe.query_report.get_filter_value('supplier');
-				if(!supplier) return; // return if no supplier selected
-
-				// filter invoices based on selected supplier
-				let invoices = [];
-				frappe.query_report.invoice_data.map(d => {
-					if(d.supplier==supplier)
-						invoices.push(d.name)
-				});
-				frappe.query_report.invoices = invoices;
-				frappe.query_report.refresh();
-			}
-		},
-		{
-			"fieldname":"purchase_order",
-			"label": __("Purchase Order"),
-			"fieldtype": "Link",
-			"options": "Purchase Order",
-			"get_query": function() {
-				return {
-					"filters": {
-						"name": ["in", frappe.query_report.invoices]
-					}
-				}
-			},
-			on_change: function() {
-				let supplier = frappe.query_report.get_filter_value('supplier');
-				if(!supplier) return; // return if no supplier selected
-
-				// filter invoices based on selected supplier
-				let invoices = [];
-				frappe.query_report.invoice_data.map(d => {
-					if(d.supplier==supplier)
-						invoices.push(d.name)
-				});
-				frappe.query_report.invoices = invoices;
-				frappe.query_report.refresh();
-			}
 		},
 		{
 			"fieldname":"from_date",
@@ -96,23 +33,5 @@
 			"reqd": 1,
 			"width": "60px"
 		}
-	],
-
-	onload: function(report) {
-		// fetch all tds applied invoices
-		frappe.call({
-			"method": "erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly.get_tds_invoices_and_orders",
-			callback: function(r) {
-				let invoices = [];
-
-				r.message.map(d => {
-					invoices.push(d.name);
-				});
-
-				report["invoice_data"] = r.message.invoices;
-				report["invoices"] = invoices;
-
-			}
-		});
-	}
+	]
 }
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.json b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.json
index 557a62d..4d555bd 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.json
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.json
@@ -1,13 +1,15 @@
 {
  "add_total_row": 1,
+ "columns": [],
  "creation": "2018-08-21 11:32:30.874923",
  "disable_prepared_report": 0,
  "disabled": 0,
  "docstatus": 0,
  "doctype": "Report",
+ "filters": [],
  "idx": 0,
  "is_standard": "Yes",
- "modified": "2019-09-24 13:46:16.473711",
+ "modified": "2021-09-20 12:05:50.387572",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "TDS Payable Monthly",
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
index 9e1382b..621b697 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -8,19 +8,12 @@
 
 
 def execute(filters=None):
-	filters["invoices"] = frappe.cache().hget("invoices", frappe.session.user)
 	validate_filters(filters)
-	set_filters(filters)
-
-	# TDS payment entries
-	payment_entries = get_payment_entires(filters)
+	tds_docs, tds_accounts, tax_category_map = get_tds_docs(filters)
 
 	columns = get_columns(filters)
-	if not filters.get("invoices"):
-		return columns, []
 
-	res = get_result(filters, payment_entries)
-
+	res = get_result(filters, tds_docs, tds_accounts, tax_category_map)
 	return columns, res
 
 def validate_filters(filters):
@@ -28,109 +21,59 @@
 	if filters.from_date > filters.to_date:
 		frappe.throw(_("From Date must be before To Date"))
 
-def set_filters(filters):
-	invoices = []
-
-	if not filters.get("invoices"):
-		filters["invoices"] = get_tds_invoices_and_orders()
-
-	if filters.supplier and filters.purchase_invoice:
-		for d in filters["invoices"]:
-			if d.name == filters.purchase_invoice and d.supplier == filters.supplier:
-				invoices.append(d)
-	elif filters.supplier and not filters.purchase_invoice:
-		for d in filters["invoices"]:
-			if d.supplier == filters.supplier:
-				invoices.append(d)
-	elif filters.purchase_invoice and not filters.supplier:
-		for d in filters["invoices"]:
-			if d.name == filters.purchase_invoice:
-				invoices.append(d)
-	elif filters.supplier and filters.purchase_order:
-		for d in filters.get("invoices"):
-			if d.name == filters.purchase_order and d.supplier == filters.supplier:
-				invoices.append(d)
-	elif filters.supplier and not filters.purchase_order:
-		for d in filters.get("invoices"):
-			if d.supplier == filters.supplier:
-				invoices.append(d)
-	elif filters.purchase_order and not filters.supplier:
-		for d in filters.get("invoices"):
-			if d.name == filters.purchase_order:
-				invoices.append(d)
-
-	filters["invoices"] = invoices if invoices else filters["invoices"]
-	filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name')
-
-	#print(filters.get('invoices'))
-
-def get_result(filters, payment_entries):
-	supplier_map, tds_docs = get_supplier_map(filters, payment_entries)
-	documents = [d.get('name') for d in filters.get('invoices')] + [d.get('name') for d in payment_entries]
-
-	gle_map = get_gle_map(filters, documents)
+def get_result(filters, tds_docs, tds_accounts, tax_category_map):
+	supplier_map = get_supplier_pan_map()
+	tax_rate_map = get_tax_rate_map(filters)
+	gle_map = get_gle_map(filters, tds_docs)
 
 	out = []
-	for d in gle_map:
+	for name, details in gle_map.items():
 		tds_deducted, total_amount_credited = 0, 0
-		supplier = supplier_map[d]
+		tax_withholding_category = tax_category_map.get(name)
+		rate = tax_rate_map.get(tax_withholding_category)
 
-		tds_doc = tds_docs[supplier.tax_withholding_category]
-		account_list = [i.account for i in tds_doc.accounts if i.company == filters.company]
+		for entry in details:
+			supplier = entry.party or entry.against
+			posting_date = entry.posting_date
+			voucher_type = entry.voucher_type
 
-		if account_list:
-			account = account_list[0]
+			if entry.account in tds_accounts:
+				tds_deducted += (entry.credit - entry.debit)
 
-		for k in gle_map[d]:
-			if k.party == supplier_map[d] and k.credit > 0:
-				total_amount_credited += (k.credit - k.debit)
-			elif account_list and k.account == account and (k.credit - k.debit) > 0:
-				tds_deducted = (k.credit - k.debit)
-				total_amount_credited += (k.credit - k.debit)
-			voucher_type = k.voucher_type
+			total_amount_credited += (entry.credit - entry.debit)
 
-		rate = [i.tax_withholding_rate for i in tds_doc.rates
-			if i.fiscal_year == gle_map[d][0].fiscal_year]
-
-		if rate and len(rate) > 0 and tds_deducted:
-			rate = rate[0]
-
-			row = [supplier.pan, supplier.name]
+		if rate and tds_deducted:
+			row = {
+				'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier).pan,
+				'supplier': supplier_map.get(supplier).name
+			}
 
 			if filters.naming_series == 'Naming Series':
-				row.append(supplier.supplier_name)
+				row.update({'supplier_name': supplier_map.get(supplier).supplier_name})
 
-			row.extend([tds_doc.name, supplier.supplier_type, rate, total_amount_credited,
-				tds_deducted, gle_map[d][0].posting_date, voucher_type, d])
+			row.update({
+				'section_code': tax_withholding_category,
+				'entity_type': supplier_map.get(supplier).supplier_type,
+				'tds_rate': rate,
+				'total_amount_credited': total_amount_credited,
+				'tds_deducted': tds_deducted,
+				'transaction_date': posting_date,
+				'transaction_type': voucher_type,
+				'ref_no': name
+			})
+
 			out.append(row)
 
 	return out
 
-def get_supplier_map(filters, payment_entries):
-	# create a supplier_map of the form {"purchase_invoice": {supplier_name, pan, tds_name}}
-	# pre-fetch all distinct applicable tds docs
-	supplier_map, tds_docs = {}, {}
-	pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id"
-	supplier_list = [d.supplier for d in filters["invoices"]]
+def get_supplier_pan_map():
+	supplier_map = frappe._dict()
+	suppliers = frappe.db.get_all('Supplier', fields=['name', 'pan', 'supplier_type', 'supplier_name'])
 
-	supplier_detail = frappe.db.get_all('Supplier',
-		{"name": ["in", supplier_list]},
-		["tax_withholding_category", "name", pan+" as pan", "supplier_type", "supplier_name"])
+	for d in suppliers:
+		supplier_map[d.name] = d
 
-	for d in filters["invoices"]:
-		supplier_map[d.get("name")] = [k for k in supplier_detail
-			if k.name == d.get("supplier")][0]
-
-	for d in payment_entries:
-		supplier_map[d.get("name")] = [k for k in supplier_detail
-			if k.name == d.get("supplier")][0]
-
-	for d in supplier_detail:
-		if d.get("tax_withholding_category") not in tds_docs:
-			tds_docs[d.get("tax_withholding_category")] = \
-				frappe.get_doc("Tax Withholding Category", d.get("tax_withholding_category"))
-
-	return supplier_map, tds_docs
+	return supplier_map
 
 def get_gle_map(filters, documents):
 	# create gle_map of the form
@@ -140,10 +83,9 @@
 	gle = frappe.db.get_all('GL Entry',
 		{
 			"voucher_no": ["in", documents],
-			'is_cancelled': 0,
-			'posting_date': ("between", [filters.get('from_date'), filters.get('to_date')]),
+			"credit": (">", 0)
 		},
-		["fiscal_year", "credit", "debit", "account", "voucher_no", "posting_date", "voucher_type"],
+		["credit", "debit", "account", "voucher_no", "posting_date", "voucher_type", "against", "party"],
 	)
 
 	for d in gle:
@@ -233,39 +175,57 @@
 
 	return columns
 
-def get_payment_entires(filters):
-	filter_dict = {
-		'posting_date': ("between", [filters.get('from_date'), filters.get('to_date')]),
-		'party_type': 'Supplier',
-		'apply_tax_withholding_amount': 1
+def get_tds_docs(filters):
+	tds_documents = []
+	purchase_invoices = []
+	payment_entries = []
+	journal_entries = []
+	tax_category_map = {}
+
+	tds_accounts = frappe.get_all("Tax Withholding Account", {'company': filters.get('company')},
+		pluck="account")
+
+	query_filters = {
+		"credit": ('>', 0),
+		"account": ("in", tds_accounts),
+		"posting_date": ("between", [filters.get("from_date"), filters.get("to_date")]),
+		"is_cancelled": 0
 	}
 
-	if filters.get('purchase_invoice') or filters.get('purchase_order'):
-		parent = frappe.db.get_all('Payment Entry Reference',
-			{'reference_name': ('in', [d.get('name') for d in filters.get('invoices')])}, ['parent'])
+	if filters.get('supplier'):
+		query_filters.update({'against': filters.get('supplier')})
 
-		filter_dict.update({'name': ('in', [d.get('parent') for d in parent])})
+	tds_docs = frappe.get_all("GL Entry", query_filters, ["voucher_no", "voucher_type", "against", "party"])
 
-	payment_entries = frappe.get_all('Payment Entry', fields=['name', 'party_name as supplier'],
-		filters=filter_dict)
+	for d in tds_docs:
+		if d.voucher_type == "Purchase Invoice":
+			purchase_invoices.append(d.voucher_no)
+		elif d.voucher_type == "Payment Entry":
+			payment_entries.append(d.voucher_no)
+		elif d.voucher_type == "Journal Entry":
+			journal_entries.append(d.voucher_no)
 
-	return payment_entries
+		tds_documents.append(d.voucher_no)
 
-@frappe.whitelist()
-def get_tds_invoices_and_orders():
-	# fetch tds applicable supplier and fetch invoices for these suppliers
-	suppliers = [d.name for d in frappe.db.get_list("Supplier",
-		{"tax_withholding_category": ["!=", ""]}, ["name"])]
+	if purchase_invoices:
+		get_tax_category_map(purchase_invoices, 'Purchase Invoice', tax_category_map)
 
-	invoices = frappe.db.get_list("Purchase Invoice",
-		{"supplier": ["in", suppliers]}, ["name", "supplier"])
+	if payment_entries:
+		get_tax_category_map(payment_entries, 'Payment Entry', tax_category_map)
 
-	orders = frappe.db.get_list("Purchase Order",
-		{"supplier": ["in", suppliers]}, ["name", "supplier"])
+	if journal_entries:
+		get_tax_category_map(journal_entries, 'Journal Entry', tax_category_map)
 
-	invoices = invoices + orders
-	invoices = [d for d in invoices if d.supplier]
+	return tds_documents, tds_accounts, tax_category_map
 
-	frappe.cache().hset("invoices", frappe.session.user, invoices)
+def get_tax_category_map(vouchers, doctype, tax_category_map):
+	tax_category_map.update(frappe._dict(frappe.get_all(doctype,
+		filters = {'name': ('in', vouchers)}, fields=['name', 'tax_withholding_category'], as_list=1)))
 
-	return invoices
+def get_tax_rate_map(filters):
+	rate_map = frappe.get_all('Tax Withholding Rate', filters={
+		'from_date': ('<=', filters.get('from_date')),
+		'to_date': ('>=', filters.get('to_date'))
+	}, fields=['parent', 'tax_withholding_rate'], as_list=1)
+
+	return frappe._dict(rate_map)
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 8ff4f97..39f102e 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -394,10 +394,6 @@
 			if cint(self.number_of_depreciations_booked) > cint(row.total_number_of_depreciations):
 				frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations"))
 
-		if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(nowdate()):
-			frappe.msgprint(_("Depreciation Row {0}: Depreciation Start Date is entered as past date")
-				.format(row.idx), title=_('Warning'), indicator='red')
-
 		if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(self.purchase_date):
 			frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Purchase Date")
 				.format(row.idx))
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 4cc9be5..7183ee7 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -645,12 +645,18 @@
 		pr = make_purchase_receipt(item_code="Macbook Pro",
 			qty=1, rate=8000.0, location="Test Location")
 
+		finance_book = frappe.new_doc('Finance Book')
+		finance_book.finance_book_name = 'Income Tax'
+		finance_book.for_income_tax = 1
+		finance_book.insert(ignore_if_duplicate=1)
+
 		asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
 		asset = frappe.get_doc('Asset', asset_name)
 		asset.calculate_depreciation = 1
 		asset.available_for_use_date = '2030-07-12'
 		asset.purchase_date = '2030-01-01'
 		asset.append("finance_books", {
+			"finance_book": finance_book.name,
 			"expected_value_after_useful_life": 1000,
 			"depreciation_method": "Written Down Value",
 			"total_number_of_depreciations": 3,
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index ef54538..896208f 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1121,6 +1121,7 @@
    "fetch_from": "supplier.represents_company",
    "fieldname": "represents_company",
    "fieldtype": "Link",
+   "ignore_user_permissions": 1,
    "label": "Represents Company",
    "options": "Company",
    "read_only": 1
@@ -1143,7 +1144,7 @@
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-08-30 20:03:14.008804",
+ "modified": "2021-09-28 13:10:47.955401",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 87d5648..e9b531e 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -685,13 +685,17 @@
 							.format(d.reference_name, d.against_order))
 
 	def set_advance_gain_or_loss(self):
-		if not self.get("advances"):
+		if self.get('conversion_rate') == 1 or not self.get("advances"):
+			return
+
+		is_purchase_invoice = self.doctype == 'Purchase Invoice'
+		party_account = self.credit_to if is_purchase_invoice else self.debit_to
+		if get_account_currency(party_account) != self.currency:
 			return
 
 		for d in self.get("advances"):
 			advance_exchange_rate = d.ref_exchange_rate
-			if (d.allocated_amount and self.conversion_rate != 1
-				and self.conversion_rate != advance_exchange_rate):
+			if (d.allocated_amount and self.conversion_rate != advance_exchange_rate):
 
 				base_allocated_amount_in_ref_rate = advance_exchange_rate * d.allocated_amount
 				base_allocated_amount_in_inv_rate = self.conversion_rate * d.allocated_amount
@@ -710,7 +714,7 @@
 
 					gain_loss_account = frappe.db.get_value('Company', self.company, 'exchange_gain_loss_account')
 					if not gain_loss_account:
-						frappe.throw(_("Please set Default Exchange Gain/Loss Account in Company {}")
+						frappe.throw(_("Please set default Exchange Gain/Loss Account in Company {}")
 							.format(self.get('company')))
 					account_currency = get_account_currency(gain_loss_account)
 					if account_currency != self.company_currency:
@@ -729,7 +733,7 @@
 							"against": party,
 							dr_or_cr + "_in_account_currency": abs(d.exchange_gain_loss),
 							dr_or_cr: abs(d.exchange_gain_loss),
-							"cost_center": self.cost_center,
+							"cost_center": self.cost_center or erpnext.get_default_cost_center(self.company),
 							"project": self.project
 						}, item=d)
 					)
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 232e3a0..7cfec97 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -1133,7 +1133,8 @@
 			query_filters["has_variants"] = 0
 
 	if filters and filters.get("is_stock_item"):
-		query_filters["is_stock_item"] = 1
+		or_cond_filters["is_stock_item"] = 1
+		or_cond_filters["has_variants"] = 1
 
 	return frappe.get_list("Item",
 		fields = fields, filters=query_filters,
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 0c36c9f..5091808 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -310,3 +310,5 @@
 erpnext.patches.v13_0.gst_fields_for_pos_invoice
 erpnext.patches.v13_0.create_accounting_dimensions_in_pos_doctypes
 erpnext.patches.v13_0.trim_sales_invoice_custom_field_length
+erpnext.patches.v13_0.create_custom_field_for_finance_book
+erpnext.patches.v13_0.modify_invalid_gain_loss_gl_entries
diff --git a/erpnext/patches/v13_0/create_custom_field_for_finance_book.py b/erpnext/patches/v13_0/create_custom_field_for_finance_book.py
new file mode 100644
index 0000000..313b0e9
--- /dev/null
+++ b/erpnext/patches/v13_0/create_custom_field_for_finance_book.py
@@ -0,0 +1,21 @@
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
+
+
+def execute():
+	company = frappe.get_all('Company', filters = {'country': 'India'})
+	if not company:
+		return
+
+	custom_field = {
+		'Finance Book': [
+			{
+				'fieldname': 'for_income_tax',
+				'label': 'For Income Tax',
+				'fieldtype': 'Check',
+				'insert_after': 'finance_book_name',
+				'description': 'If the asset is put to use for less than 180 days, the first Depreciation Rate will be reduced by 50%.'
+			}
+		]
+	}
+	create_custom_fields(custom_field, update=1)
diff --git a/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py
new file mode 100644
index 0000000..fa8a864
--- /dev/null
+++ b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py
@@ -0,0 +1,49 @@
+from __future__ import unicode_literals
+
+import json
+
+import frappe
+
+
+def execute():
+	frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_advance')
+	frappe.reload_doc('accounts', 'doctype', 'sales_invoice_advance')
+
+	purchase_invoices = frappe.db.sql("""
+		select
+			parenttype as type, parent as name
+		from
+			`tabPurchase Invoice Advance`
+		where
+			ref_exchange_rate = 1
+			and docstatus = 1
+			and ifnull(exchange_gain_loss, '') != ''
+		group by
+			parent
+	""", as_dict=1)
+
+	sales_invoices = frappe.db.sql("""
+		select
+			parenttype as type, parent as name
+		from
+			`tabSales Invoice Advance`
+		where
+			ref_exchange_rate = 1
+			and docstatus = 1
+			and ifnull(exchange_gain_loss, '') != ''
+		group by
+			parent
+	""", as_dict=1)
+
+	if purchase_invoices + sales_invoices:
+		frappe.log_error(json.dumps(purchase_invoices + sales_invoices, indent=2), title="Patch Log")
+
+	for invoice in purchase_invoices + sales_invoices:
+		doc = frappe.get_doc(invoice.type, invoice.name)
+		doc.docstatus = 2
+		doc.make_gl_entries()
+		for advance in doc.advances:
+			if advance.ref_exchange_rate == 1:
+				advance.db_set('exchange_gain_loss', 0, False)
+		doc.docstatus = 1
+		doc.make_gl_entries()
\ No newline at end of file
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 2a8870b..df970f3 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -144,6 +144,9 @@
 		if self.sales_order:
 			frappe.db.set_value("Sales Order", self.sales_order, "project", self.name)
 
+	def on_trash(self):
+		frappe.db.set_value("Sales Order", {"project": self.name}, "project", "")
+
 	def update_percent_complete(self):
 		if self.percent_complete_method == "Manual":
 			if self.status == "Completed":
diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py
index ebc1326..c64ac8d 100644
--- a/erpnext/projects/doctype/project/test_project.py
+++ b/erpnext/projects/doctype/project/test_project.py
@@ -9,6 +9,8 @@
 
 from erpnext.projects.doctype.project_template.test_project_template import make_project_template
 from erpnext.projects.doctype.task.test_task import create_task
+from erpnext.selling.doctype.sales_order.sales_order import make_project as make_project_from_so
+from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
 
 test_records = frappe.get_test_records('Project')
 test_ignore = ["Sales Order"]
@@ -96,6 +98,21 @@
 
 		self.assertEqual(len(tasks), 2)
 
+	def test_project_linking_with_sales_order(self):
+		so = make_sales_order()
+		project = make_project_from_so(so.name)
+
+		project.save()
+		self.assertEqual(project.sales_order, so.name)
+
+		so.reload()
+		self.assertEqual(so.project, project.name)
+
+		project.delete()
+
+		so.reload()
+		self.assertFalse(so.project)
+
 def get_project(name, template):
 
 	project = frappe.get_doc(dict(
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 91b1247..403c498 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -617,6 +617,7 @@
 											me.frm.script_manager.trigger('qty', item.doctype, item.name);
 											if (!me.frm.doc.set_warehouse)
 												me.frm.script_manager.trigger('warehouse', item.doctype, item.name);
+											me.apply_price_list(item, true);
 										}, undefined, !frappe.flags.hide_serial_batch_dialog);
 									}
 								},
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 93cbcca..b5c609a 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -674,6 +674,15 @@
 				'fieldtype': 'Data',
 				'insert_after': 'email'
 			}
+		],
+		'Finance Book': [
+			{
+				'fieldname': 'for_income_tax',
+				'label': 'For Income Tax',
+				'fieldtype': 'Check',
+				'insert_after': 'finance_book_name',
+				'description': 'If the asset is put to use for less than 180 days, the first Depreciation Rate will be reduced by 50%.'
+			}
 		]
 	}
 
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 091cc884..0faf80b 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -857,12 +857,13 @@
 		rate_of_depreciation = row.rate_of_depreciation
 		# if its the first depreciation
 		if depreciable_value == asset.gross_purchase_amount:
-			# as per IT act, if the asset is purchased in the 2nd half of fiscal year, then rate is divided by 2
-			diff = date_diff(row.depreciation_start_date, asset.available_for_use_date)
-			if diff <= 180:
-				rate_of_depreciation = rate_of_depreciation / 2
-				frappe.msgprint(
-					_('As per IT Act, the rate of depreciation for the first depreciation entry is reduced by 50%.'))
+			if row.finance_book and frappe.db.get_value('Finance Book', row.finance_book, 'for_income_tax'):
+				# as per IT act, if the asset is purchased in the 2nd half of fiscal year, then rate is divided by 2
+				diff = date_diff(row.depreciation_start_date, asset.available_for_use_date)
+				if diff <= 180:
+					rate_of_depreciation = rate_of_depreciation / 2
+					frappe.msgprint(
+						_('As per IT Act, the rate of depreciation for the first depreciation entry is reduced by 50%.'))
 
 		depreciation_amount = flt(depreciable_value * (flt(rate_of_depreciation) / 100))
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 85282ca..7c7ed9a 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1480,6 +1480,7 @@
    "fetch_from": "customer.represents_company",
    "fieldname": "represents_company",
    "fieldtype": "Link",
+   "ignore_user_permissions": 1,
    "label": "Represents Company",
    "options": "Company",
    "read_only": 1
@@ -1512,7 +1513,7 @@
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-09-01 15:12:24.115483",
+ "modified": "2021-09-28 13:09:51.515542",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index fdc8763..9bf142c 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -1277,6 +1277,7 @@
    "fetch_from": "customer.represents_company",
    "fieldname": "represents_company",
    "fieldtype": "Link",
+   "ignore_user_permissions": 1,
    "label": "Represents Company",
    "options": "Company",
    "read_only": 1
@@ -1308,7 +1309,7 @@
  "idx": 146,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-08-27 20:14:40.215231",
+ "modified": "2021-09-28 13:10:09.761714",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note",
diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.json b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
index 8665986..805286d 100644
--- a/erpnext/stock/doctype/pick_list_item/pick_list_item.json
+++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
@@ -36,7 +36,8 @@
    "fieldname": "qty",
    "fieldtype": "Float",
    "in_list_view": 1,
-   "label": "Qty"
+   "label": "Qty",
+   "reqd": 1
   },
   {
    "fieldname": "picked_qty",
@@ -180,7 +181,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-24 17:18:57.357120",
+ "modified": "2021-09-28 12:02:16.923056",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick List Item",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 1a59734..112dded 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -1140,6 +1140,7 @@
    "fetch_from": "supplier.represents_company",
    "fieldname": "represents_company",
    "fieldtype": "Link",
+   "ignore_user_permissions": 1,
    "label": "Represents Company",
    "options": "Company",
    "read_only": 1
@@ -1149,7 +1150,7 @@
  "idx": 261,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-08-17 20:16:40.849885",
+ "modified": "2021-09-28 13:11:10.181328",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt",
diff --git a/erpnext/templates/print_formats/includes/total.html b/erpnext/templates/print_formats/includes/total.html
index 8179980..879203b 100644
--- a/erpnext/templates/print_formats/includes/total.html
+++ b/erpnext/templates/print_formats/includes/total.html
@@ -7,7 +7,7 @@
 		</div>
 	{% else %}
 		<div class="col-xs-5 {%- if doc.align_labels_right %} text-right{%- endif -%}">
-			<label>{{ _(doc.meta.get_label('total')) }}</label></div>
+			<label>{{ _(df.label) }}</label></div>
 		<div class="col-xs-7 text-right">
 			{{ doc.get_formatted("total", doc) }}
 		</div>