Merge pull request #23588 from kevingdc/fix/asset-update-maintenance-status

fix: Asset status after maintenance or repair
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 079f599..c5260a1 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -711,7 +711,8 @@
 									item.item_tax_amount / self.conversion_rate)
 						}, item=item))
 				else:
-					cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company)
+					cwip_account = get_asset_account("capital_work_in_progress_account",
+						asset_category=item.asset_category,company=self.company)
 
 					cwip_account_currency = get_account_currency(cwip_account)
 					gl_entries.append(self.get_gl_dict({
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 9a666bf..2e5a714 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1002,7 +1002,8 @@
 		"cost_center": args.cost_center or "_Test Cost Center - _TC",
 		"project": args.project,
 		"rejected_warehouse": args.rejected_warehouse or "",
-		"rejected_serial_no": args.rejected_serial_no or ""
+		"rejected_serial_no": args.rejected_serial_no or "",
+		"asset_location": args.location or ""
 	})
 
 	if args.get_taxes_and_charges:
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 83d7967..8b5e68b 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -106,6 +106,7 @@
 			from `tabGL Entry`
 			where company = %s and
 			party in %s and fiscal_year=%s and credit > 0
+			and is_opening = 'No'
 		""", (company, tuple(suppliers), fiscal_year), as_dict=1)
 
 	vouchers = [d.voucher_no for d in entries]
@@ -192,6 +193,7 @@
 		select distinct voucher_no
 		from `tabGL Entry`
 		where party in %s and %s and debit > 0
+		and is_opening = 'No'
 	""", (tuple(suppliers), condition)) or []
 
 def get_debit_note_amount(suppliers, year_start_date, year_end_date, company=None):
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 45fdc93..30abc66 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -466,50 +466,63 @@
 
 	def validate_make_gl_entry(self):
 		purchase_document = self.get_purchase_document()
-		asset_bought_with_invoice = purchase_document == self.purchase_invoice
-		fixed_asset_account, cwip_account = self.get_asset_accounts()
-		cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
-		# check if expense already has been booked in case of cwip was enabled after purchasing asset
-		expense_booked = False
-		cwip_booked = False
-
-		if asset_bought_with_invoice:
-			expense_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
-				(purchase_document, fixed_asset_account), as_dict=1)
-		else:
-			cwip_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
-				(purchase_document, cwip_account), as_dict=1)
-
-		if cwip_enabled and (expense_booked or not cwip_booked):
-			# if expense has already booked from invoice or cwip is booked from receipt
+		if not purchase_document:
 			return False
-		elif not cwip_enabled and (not expense_booked or cwip_booked):
-			# if cwip is disabled but expense hasn't been booked yet
-			return True
-		elif cwip_enabled:
-			# default condition
-			return True
+
+		asset_bought_with_invoice = (purchase_document == self.purchase_invoice)
+		fixed_asset_account = self.get_fixed_asset_account()
+		
+		cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
+		cwip_account = self.get_cwip_account(cwip_enabled=cwip_enabled)
+
+		query = """SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s"""
+		if asset_bought_with_invoice:
+			# with invoice purchase either expense or cwip has been booked
+			expense_booked = frappe.db.sql(query, (purchase_document, fixed_asset_account), as_dict=1)
+			if expense_booked:
+				# if expense is already booked from invoice then do not make gl entries regardless of cwip enabled/disabled
+				return False
+
+			cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
+			if cwip_booked:
+				# if cwip is booked from invoice then make gl entries regardless of cwip enabled/disabled
+				return True
+		else:
+			# with receipt purchase either cwip has been booked or no entries have been made
+			if not cwip_account:
+				# if cwip account isn't available do not make gl entries
+				return False
+
+			cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
+			# if cwip is not booked from receipt then do not make gl entries
+			# if cwip is booked from receipt then make gl entries
+			return cwip_booked
 
 	def get_purchase_document(self):
 		asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')
 		purchase_document = self.purchase_invoice if asset_bought_with_invoice else self.purchase_receipt
 
 		return purchase_document
+	
+	def get_fixed_asset_account(self):
+		return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
+	
+	def get_cwip_account(self, cwip_enabled=False):
+		cwip_account = None
+		try:
+			cwip_account = get_asset_account("capital_work_in_progress_account", self.name, self.asset_category, self.company)
+		except:
+			# if no cwip account found in category or company and "cwip is enabled" then raise else silently pass
+			if cwip_enabled:
+				raise
 
-	def get_asset_accounts(self):
-		fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name,
-					asset_category = self.asset_category, company = self.company)
-
-		cwip_account = get_asset_account("capital_work_in_progress_account",
-			self.name, self.asset_category, self.company)
-
-		return fixed_asset_account, cwip_account
+		return cwip_account
 
 	def make_gl_entries(self):
 		gl_entries = []
 
 		purchase_document = self.get_purchase_document()
-		fixed_asset_account, cwip_account = self.get_asset_accounts()
+		fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
 
 		if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
 
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 52039c1..a0d7603 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -9,6 +9,7 @@
 from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
 from erpnext.assets.doctype.asset.asset import make_sales_invoice
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
 from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice
 
 class TestAsset(unittest.TestCase):
@@ -558,81 +559,6 @@
 
 		self.assertEqual(gle, expected_gle)
 
-	def test_gle_with_cwip_toggling(self):
-		# TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset
-		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
-
-		pr = make_purchase_receipt(item_code="Macbook Pro",
-			qty=1, rate=5000, do_not_submit=True, location="Test Location")
-		pr.set('taxes', [{
-			'category': 'Total',
-			'add_deduct_tax': 'Add',
-			'charge_type': 'On Net Total',
-			'account_head': '_Test Account Service Tax - _TC',
-			'description': '_Test Account Service Tax',
-			'cost_center': 'Main - _TC',
-			'rate': 5.0
-		}, {
-			'category': 'Valuation and Total',
-			'add_deduct_tax': 'Add',
-			'charge_type': 'On Net Total',
-			'account_head': '_Test Account Shipping Charges - _TC',
-			'description': '_Test Account Shipping Charges',
-			'cost_center': 'Main - _TC',
-			'rate': 5.0
-		}])
-		pr.submit()
-		expected_gle = (
-			("Asset Received But Not Billed - _TC", 0.0, 5250.0),
-			("CWIP Account - _TC", 5250.0, 0.0)
-		)
-		pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
-			where voucher_type='Purchase Receipt' and voucher_no = %s
-			order by account""", pr.name)
-		self.assertEqual(pr_gle, expected_gle)
-
-		pi = make_invoice(pr.name)
-		pi.submit()
-		expected_gle = (
-			("_Test Account Service Tax - _TC", 250.0, 0.0),
-			("_Test Account Shipping Charges - _TC", 250.0, 0.0),
-			("Asset Received But Not Billed - _TC", 5250.0, 0.0),
-			("Creditors - _TC", 0.0, 5500.0),
-			("Expenses Included In Asset Valuation - _TC", 0.0, 250.0),
-		)
-		pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
-			where voucher_type='Purchase Invoice' and voucher_no = %s
-			order by account""", pi.name)
-		self.assertEqual(pi_gle, expected_gle)
-
-		asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
-		asset_doc = frappe.get_doc('Asset', asset)
-		month_end_date = get_last_day(nowdate())
-		asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
-		self.assertEqual(asset_doc.gross_purchase_amount, 5250.0)
-		asset_doc.append("finance_books", {
-			"expected_value_after_useful_life": 200,
-			"depreciation_method": "Straight Line",
-			"total_number_of_depreciations": 3,
-			"frequency_of_depreciation": 10,
-			"depreciation_start_date": month_end_date
-		})
-
-		# disable cwip and try submitting
-		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
-		asset_doc.submit()
-		# asset should have gl entries even if cwip is disabled
-		expected_gle = (
-			("_Test Fixed Asset - _TC", 5250.0, 0.0),
-			("CWIP Account - _TC", 0.0, 5250.0)
-		)
-		gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
-			where voucher_type='Asset' and voucher_no = %s
-			order by account""", asset_doc.name)
-		self.assertEqual(gle, expected_gle)
-
-		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
-
 	def test_expense_head(self):
 		pr = make_purchase_receipt(item_code="Macbook Pro",
 			qty=2, rate=200000.0, location="Test Location")
@@ -640,6 +566,74 @@
 		doc = make_invoice(pr.name)
 
 		self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
+	
+	def test_asset_cwip_toggling_cases(self):
+		cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
+		name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
+		cwip_acc = "CWIP Account - _TC"
+
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+		frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "")
+		frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", "")
+
+		# case 0 -- PI with cwip disable, Asset with cwip disabled, No cwip account set
+		pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+		asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+		asset_doc = frappe.get_doc('Asset', asset)
+		asset_doc.available_for_use_date = nowdate()
+		asset_doc.calculate_depreciation = 0
+		asset_doc.submit()
+		gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+		self.assertFalse(gle)
+
+		# case 1 -- PR with cwip disabled, Asset with cwip enabled
+		pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+		frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
+		asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
+		asset_doc = frappe.get_doc('Asset', asset)
+		asset_doc.available_for_use_date = nowdate()
+		asset_doc.calculate_depreciation = 0
+		asset_doc.submit()
+		gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+		self.assertFalse(gle)
+
+		# case 2 -- PR with cwip enabled, Asset with cwip disabled
+		pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+		asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
+		asset_doc = frappe.get_doc('Asset', asset)
+		asset_doc.available_for_use_date = nowdate()
+		asset_doc.calculate_depreciation = 0
+		asset_doc.submit()
+		gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+		self.assertTrue(gle)
+
+		# case 3 -- PI with cwip disabled, Asset with cwip enabled
+		pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+		asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+		asset_doc = frappe.get_doc('Asset', asset)
+		asset_doc.available_for_use_date = nowdate()
+		asset_doc.calculate_depreciation = 0
+		asset_doc.submit()
+		gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+		self.assertFalse(gle)
+
+		# case 4 -- PI with cwip enabled, Asset with cwip disabled
+		pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+		asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+		asset_doc = frappe.get_doc('Asset', asset)
+		asset_doc.available_for_use_date = nowdate()
+		asset_doc.calculate_depreciation = 0
+		asset_doc.submit()
+		gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+		self.assertTrue(gle)
+
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", cwip)
+		frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
+		frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc)
 
 def create_asset_data():
 	if not frappe.db.exists("Asset Category", "Computers"):
diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 9a33fc1..46620d5 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -5,7 +5,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import cint
+from frappe.utils import cint, get_link_to_form
 from frappe.model.document import Document
 
 class AssetCategory(Document):
@@ -13,6 +13,7 @@
 		self.validate_finance_books()
 		self.validate_account_types()
 		self.validate_account_currency()
+		self.valide_cwip_account()
 
 	def validate_finance_books(self):
 		for d in self.finance_books:
@@ -58,6 +59,21 @@
 						frappe.throw(_("Row #{}: {} of {} should be {}. Please modify the account or select a different account.")
 							.format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)),
 							title=_("Invalid Account"))
+	
+	def valide_cwip_account(self):
+		if self.enable_cwip_accounting:
+			missing_cwip_accounts_for_company = []
+			for d in self.accounts:
+				if (not d.capital_work_in_progress_account and 
+					not frappe.db.get_value("Company", d.company_name, "capital_work_in_progress_account")):
+					missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name))
+
+			if missing_cwip_accounts_for_company:
+				msg = _("""To enable Capital Work in Progress Accounting, """)
+				msg += _("""you must select Capital Work in Progress Account in accounts table""")
+				msg += "<br><br>"
+				msg += _("You can also set default CWIP account in Company {}").format(", ".join(missing_cwip_accounts_for_company))
+				frappe.throw(msg, title=_("Missing Account"))
 
 
 @frappe.whitelist()
diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py
index b32f9b5..39b79d6 100644
--- a/erpnext/assets/doctype/asset_category/test_asset_category.py
+++ b/erpnext/assets/doctype/asset_category/test_asset_category.py
@@ -26,4 +26,22 @@
 			asset_category.insert()
 		except frappe.DuplicateEntryError:
 			pass
-			
\ No newline at end of file
+
+	def test_cwip_accounting(self):
+		company_cwip_acc = frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account")
+		frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "")
+
+		asset_category = frappe.new_doc("Asset Category")
+		asset_category.asset_category_name = "Computers"
+		asset_category.enable_cwip_accounting = 1
+
+		asset_category.total_number_of_depreciations = 3
+		asset_category.frequency_of_depreciation = 3
+		asset_category.append("accounts", {
+			"company_name": "_Test Company",
+			"fixed_asset_account": "_Test Fixed Asset - _TC",
+			"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
+			"depreciation_expense_account": "_Test Depreciations - _TC"
+		})
+
+		self.assertRaises(frappe.ValidationError, asset_category.insert)
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index c889237..5b14d05 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -381,7 +381,6 @@
 					"transaction_date": nowdate(),
 					"status": "Draft",
 					"company": self.company,
-					"requested_by": frappe.session.user,
 					'material_request_type': material_request_type,
 					'customer': item_doc.customer or ''
 				})
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index b7d968e..3173b6c 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -434,7 +434,7 @@
 			elif flt(d.completed_qty) <= max_allowed_qty_for_wo:
 				d.status = "Completed"
 			else:
-				frappe.throw(_("Completed Qty can not be greater than 'Qty to Manufacture'"))
+				frappe.throw(_("Completed Qty cannot be greater than 'Qty to Manufacture'"))
 
 	def set_actual_dates(self):
 		if self.get("operations"):
diff --git a/erpnext/payroll/doctype/salary_component/salary_component.json b/erpnext/payroll/doctype/salary_component/salary_component.json
index 225b048..c97e45c 100644
--- a/erpnext/payroll/doctype/salary_component/salary_component.json
+++ b/erpnext/payroll/doctype/salary_component/salary_component.json
@@ -217,7 +217,7 @@
    "fieldname": "help",
    "fieldtype": "HTML",
    "label": "Help",
-   "options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
+   "options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condition. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
   },
   {
    "default": "0",
@@ -238,14 +238,13 @@
    "depends_on": "eval:doc.type == \"Deduction\"",
    "fieldname": "is_income_tax_component",
    "fieldtype": "Check",
-   "label": "Is Income Tax Component",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Is Income Tax Component"
   }
  ],
  "icon": "fa fa-flag",
+ "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2020-06-22 15:39:20.826565",
+ "modified": "2020-10-07 20:38:33.795853",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Component",
diff --git a/erpnext/payroll/doctype/salary_detail/salary_detail.json b/erpnext/payroll/doctype/salary_detail/salary_detail.json
index cc87cae..eedb56e 100644
--- a/erpnext/payroll/doctype/salary_detail/salary_detail.json
+++ b/erpnext/payroll/doctype/salary_detail/salary_detail.json
@@ -117,7 +117,7 @@
    "depends_on": "eval:doc.is_flexible_benefit != 1",
    "fieldname": "section_break_2",
    "fieldtype": "Section Break",
-   "label": "Condtion and formula"
+   "label": "Condition and formula"
   },
   {
    "allow_on_submit": 1,
@@ -206,38 +206,28 @@
    "collapsible": 1,
    "fieldname": "section_break_5",
    "fieldtype": "Section Break",
-   "label": "Component properties and references ",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Component properties and references "
   },
   {
    "fieldname": "column_break_11",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "section_break_19",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "column_break_18",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "column_break_24",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   }
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-07-01 12:13:41.956495",
+ "modified": "2020-10-07 20:39:41.619283",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Detail",
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation.js b/erpnext/selling/doctype/quotation/tests/test_quotation.js
index d69d799..ad942fe 100644
--- a/erpnext/selling/doctype/quotation/tests/test_quotation.js
+++ b/erpnext/selling/doctype/quotation/tests/test_quotation.js
@@ -46,7 +46,7 @@
 			assert.ok(cur_frm.doc.items[0].rate == 200, "Price Changed Manually");
 			assert.equal(cur_frm.doc.total, 1000, "New Total Calculated");
 
-			// Check Terms and Condtions
+			// Check Terms and Conditions
 			assert.ok(cur_frm.doc.tc_name == "Test Term 1", "Terms and Conditions Checked");
 
 			assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index f882898..62a5d4e 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -989,7 +989,6 @@
 		doctype = 'Material Request',
 		transaction_date = nowdate(),
 		company = company,
-		requested_by = frappe.session.user,
 		material_request_type = 'Purchase'
 	))
 	for item in raw_materials:
diff --git a/erpnext/stock/doctype/item_attribute/item_attribute.py b/erpnext/stock/doctype/item_attribute/item_attribute.py
index 7f00201..3764738 100644
--- a/erpnext/stock/doctype/item_attribute/item_attribute.py
+++ b/erpnext/stock/doctype/item_attribute/item_attribute.py
@@ -29,9 +29,18 @@
 		'''Validate that if there are existing items with attributes, they are valid'''
 		attributes_list = [d.attribute_value for d in self.item_attribute_values]
 
-		for item in frappe.db.sql('''select i.name, iva.attribute_value as value
-			from `tabItem Variant Attribute` iva, `tabItem` i where iva.attribute = %s
-			and iva.parent = i.name and i.has_variants = 0''', self.name, as_dict=1):
+		# Get Item Variant Attribute details of variant items
+		items = frappe.db.sql("""
+			select
+				i.name, iva.attribute_value as value
+			from
+				`tabItem Variant Attribute` iva, `tabItem` i
+			where
+				iva.attribute = %(attribute)s
+				and iva.parent = i.name and
+				i.variant_of is not null and i.variant_of != ''""", {"attribute" : self.name}, as_dict=1)
+
+		for item in items:
 			if self.numeric_values:
 				validate_is_incremental(self, self.name, item.value, item.name)
 			else:
diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py
index 8e39eb5..51b47c5 100644
--- a/erpnext/stock/doctype/item_price/item_price.py
+++ b/erpnext/stock/doctype/item_price/item_price.py
@@ -50,16 +50,18 @@
 
 	def check_duplicates(self):
 		conditions = "where item_code=%(item_code)s and price_list=%(price_list)s and name != %(name)s"
+		condition_data_dict = dict(item_code=self.item_code, price_list=self.price_list, name=self.name)
 
 		for field in ['uom', 'valid_from',
 			'valid_upto', 'packing_unit', 'customer', 'supplier']:
 			if self.get(field):
 				conditions += " and {0} = %({1})s".format(field, field)
+				condition_data_dict[field] = self.get(field)
 
 		price_list_rate = frappe.db.sql("""
 			SELECT price_list_rate
 			FROM `tabItem Price`
-			  {conditions} """.format(conditions=conditions), self.as_dict())
+			  {conditions} """.format(conditions=conditions), condition_data_dict)
 
 		if price_list_rate :
 			frappe.throw(_("Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, UOM, Qty and Dates."), ItemPriceDuplicateItem)
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 3c4e353..8c47098 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -280,7 +280,8 @@
 				fieldname:'default_supplier',
 				fieldtype: 'Link',
 				options: 'Supplier',
-				description: __('Select a Supplier from the Default Supplier List of the items below.'),
+				description: __('Select a Supplier from the Default Suppliers of the items below. \
+					On selection, a Purchase Order will be made against items belonging to the selected Supplier only.'),
 				get_query: () => {
 					return{
 						query: "erpnext.stock.doctype.material_request.material_request.get_default_supplier_query",
diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json
index 44503d2..d73349d 100644
--- a/erpnext/stock/doctype/material_request/material_request.json
+++ b/erpnext/stock/doctype/material_request/material_request.json
@@ -13,7 +13,9 @@
   "material_request_type",
   "transfer_status",
   "customer",
+  "status",
   "column_break_2",
+  "transaction_date",
   "schedule_date",
   "company",
   "amended_from",
@@ -25,11 +27,8 @@
   "scan_barcode",
   "items",
   "more_info",
-  "requested_by",
-  "transaction_date",
-  "column_break2",
-  "status",
   "per_ordered",
+  "column_break2",
   "per_received",
   "printing_details",
   "letter_head",
@@ -82,7 +81,8 @@
    "fieldname": "customer",
    "fieldtype": "Link",
    "label": "Customer",
-   "options": "Customer"
+   "options": "Customer",
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_2",
@@ -92,12 +92,12 @@
    "allow_on_submit": 1,
    "fieldname": "schedule_date",
    "fieldtype": "Date",
+   "in_list_view": 1,
    "label": "Required By"
   },
   {
    "fieldname": "company",
    "fieldtype": "Link",
-   "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Company",
    "oldfieldname": "company",
@@ -154,17 +154,9 @@
    "options": "fa fa-file-text"
   },
   {
-   "fieldname": "requested_by",
-   "fieldtype": "Data",
-   "in_standard_filter": 1,
-   "label": "Requested For",
-   "options": "Email"
-  },
-  {
    "default": "Today",
    "fieldname": "transaction_date",
    "fieldtype": "Date",
-   "in_list_view": 1,
    "label": "Transaction Date",
    "no_copy": 1,
    "oldfieldname": "transaction_date",
@@ -197,7 +189,7 @@
    "width": "100px"
   },
   {
-   "depends_on": "eval:doc.docstatus==1",
+   "depends_on": "eval:doc.per_ordered > 0",
    "fieldname": "per_ordered",
    "fieldtype": "Percent",
    "label": "% Ordered",
@@ -208,7 +200,7 @@
    "read_only": 1
   },
   {
-   "depends_on": "eval:doc.docstatus==1",
+   "depends_on": "eval:doc.per_received > 0",
    "fieldname": "per_received",
    "fieldtype": "Percent",
    "label": "% Received",
@@ -282,13 +274,15 @@
   },
   {
    "fieldname": "warehouse_section",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Warehouse"
   },
   {
-   "description": "Sets 'For Warehouse' in each row of the Items table.",
+   "description": "Sets 'Target Warehouse' in each row of the Items table.",
    "fieldname": "set_warehouse",
    "fieldtype": "Link",
-   "label": "Set Warehouse",
+   "in_list_view": 1,
+   "label": "Set Target Warehouse",
    "options": "Warehouse"
   },
   {
@@ -300,9 +294,10 @@
   },
   {
    "depends_on": "eval:doc.material_request_type == 'Material Transfer'",
+   "description": "Sets 'Source Warehouse' in each row of the Items table.",
    "fieldname": "set_from_warehouse",
    "fieldtype": "Link",
-   "label": "Set From Warehouse",
+   "label": "Set Source Warehouse",
    "options": "Warehouse"
   },
   {
@@ -319,7 +314,7 @@
  "idx": 70,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-10 13:27:54.891058",
+ "modified": "2020-09-19 01:04:09.285862",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request",
diff --git a/erpnext/stock/doctype/material_request/material_request_dashboard.py b/erpnext/stock/doctype/material_request/material_request_dashboard.py
index 0e4fb7a..f3e5e5d 100644
--- a/erpnext/stock/doctype/material_request/material_request_dashboard.py
+++ b/erpnext/stock/doctype/material_request/material_request_dashboard.py
@@ -7,7 +7,7 @@
 		'fieldname': 'material_request',
 		'transactions': [
 			{
-				'label': _('Related'),
+				'label': _('Reference'),
 				'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order']
 			},
 			{
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json
index 32bd4a0..25bbbbd 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -13,12 +13,10 @@
   "schedule_date",
   "section_break_4",
   "description",
+  "column_break_12",
   "item_group",
   "brand",
-  "image_section",
   "image",
-  "column_break_12",
-  "manufacturer_part_no",
   "quantity_and_warehouse",
   "qty",
   "stock_uom",
@@ -28,12 +26,26 @@
   "uom",
   "conversion_factor",
   "stock_qty",
+  "qty_info_sec_break",
+  "min_order_qty",
+  "projected_qty",
+  "qty_info_col_break",
+  "actual_qty",
+  "ordered_qty",
+  "received_qty",
   "rate_and_amount_section_break",
   "rate",
   "col_break3",
   "amount",
   "manufacture_details",
   "manufacturer",
+  "manufacturer_part_no",
+  "col_break_mfg",
+  "bom_no",
+  "accounting_dimensions_section",
+  "project",
+  "dimension_col_break",
+  "cost_center",
   "more_info",
   "lead_time_date",
   "sales_order",
@@ -41,19 +53,7 @@
   "production_plan",
   "material_request_plan_item",
   "col_break4",
-  "min_order_qty",
-  "projected_qty",
-  "actual_qty",
-  "ordered_qty",
-  "received_qty",
-  "accounting_details",
   "expense_account",
-  "accounting_dimensions_section",
-  "project",
-  "dimension_col_break",
-  "cost_center",
-  "section_break_37",
-  "bom_no",
   "section_break_46",
   "page_break"
  ],
@@ -164,7 +164,7 @@
    "fieldname": "warehouse",
    "fieldtype": "Link",
    "in_list_view": 1,
-   "label": "For Warehouse",
+   "label": "Target Warehouse",
    "oldfieldname": "warehouse",
    "oldfieldtype": "Link",
    "options": "Warehouse",
@@ -191,12 +191,14 @@
   {
    "fieldname": "rate",
    "fieldtype": "Currency",
-   "label": "Rate"
+   "label": "Rate",
+   "print_hide": 1
   },
   {
    "fieldname": "amount",
    "fieldtype": "Currency",
    "label": "Amount",
+   "print_hide": 1,
    "read_only": 1
   },
   {
@@ -326,6 +328,7 @@
    "report_hide": 1
   },
   {
+   "depends_on": "eval:doc.docstatus==1",
    "fieldname": "ordered_qty",
    "fieldtype": "Float",
    "label": "Completed Qty",
@@ -336,12 +339,6 @@
    "read_only": 1
   },
   {
-   "collapsible": 1,
-   "fieldname": "accounting_details",
-   "fieldtype": "Section Break",
-   "label": "Accounting Details"
-  },
-  {
    "fieldname": "expense_account",
    "fieldtype": "Link",
    "label": "Expense Account",
@@ -367,21 +364,10 @@
    "print_hide": 1
   },
   {
-   "collapsible": 1,
-   "fieldname": "image_section",
-   "fieldtype": "Section Break",
-   "label": "Image"
-  },
-  {
-   "depends_on": "eval:parent.material_request_type == \"Manufacture\"",
-   "fieldname": "section_break_37",
-   "fieldtype": "Section Break",
-   "label": "Manufacturing"
-  },
-  {
+   "depends_on": "eval:doc.docstatus==1",
    "fieldname": "received_qty",
    "fieldtype": "Float",
-   "label": "Received Quantity",
+   "label": "Received Qty",
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
@@ -398,6 +384,7 @@
   },
   {
    "collapsible": 1,
+   "depends_on": "eval:in_list([\"Manufacture\", \"Purchase\"], parent.material_request_type)",
    "fieldname": "manufacture_details",
    "fieldtype": "Section Break",
    "label": "Manufacture"
@@ -430,10 +417,11 @@
    "depends_on": "eval:parent.material_request_type == \"Material Transfer\"",
    "fieldname": "from_warehouse",
    "fieldtype": "Link",
-   "label": "Source Warehouse (Material Transfer)",
+   "label": "Source Warehouse",
    "options": "Warehouse"
   },
   {
+   "allow_on_submit": 1,
    "fieldname": "bom_no",
    "fieldtype": "Link",
    "label": "BOM No",
@@ -444,12 +432,25 @@
   {
    "fieldname": "section_break_46",
    "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "col_break_mfg",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "qty_info_sec_break",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "qty_info_col_break",
+   "fieldtype": "Column Break"
   }
  ],
  "idx": 1,
+ "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-05-15 09:00:00.992835",
+ "modified": "2020-10-02 11:44:36.553064",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request Item",