Merge pull request #23583 from anupamvs/item-price

fix: can't save item price after adding child table 
diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index 3f23ba9..045d8fb 100644
--- a/erpnext/accounts/desk_page/accounting/accounting.json
+++ b/erpnext/accounts/desk_page/accounting/accounting.json
@@ -53,7 +53,7 @@
   {
    "hidden": 0,
    "label": "Goods and Services Tax (GST India)",
-   "links": "[\n    {\n        \"label\": \"GST Settings\",\n        \"name\": \"GST Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"GST HSN Code\",\n        \"name\": \"GST HSN Code\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GSTR-1\",\n        \"name\": \"GSTR-1\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GSTR-2\",\n        \"name\": \"GSTR-2\",\n        \"type\": \"report\"\n    },\n    {\n        \"label\": \"GSTR 3B Report\",\n        \"name\": \"GSTR 3B Report\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Sales Register\",\n        \"name\": \"GST Sales Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Purchase Register\",\n        \"name\": \"GST Purchase Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Itemised Sales Register\",\n        \"name\": \"GST Itemised Sales Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Itemised Purchase Register\",\n        \"name\": \"GST Itemised Purchase Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"country\": \"India\",\n        \"description\": \"C-Form records\",\n        \"label\": \"C-Form\",\n        \"name\": \"C-Form\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"label\": \"GST Settings\",\n        \"name\": \"GST Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"GST HSN Code\",\n        \"name\": \"GST HSN Code\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GSTR-1\",\n        \"name\": \"GSTR-1\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GSTR-2\",\n        \"name\": \"GSTR-2\",\n        \"type\": \"report\"\n    },\n    {\n        \"label\": \"GSTR 3B Report\",\n        \"name\": \"GSTR 3B Report\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Sales Register\",\n        \"name\": \"GST Sales Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Purchase Register\",\n        \"name\": \"GST Purchase Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Itemised Sales Register\",\n        \"name\": \"GST Itemised Sales Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"GST Itemised Purchase Register\",\n        \"name\": \"GST Itemised Purchase Register\",\n        \"type\": \"report\"\n    },\n    {\n        \"country\": \"India\",\n        \"description\": \"C-Form records\",\n        \"label\": \"C-Form\",\n        \"name\": \"C-Form\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"country\": \"India\",\n        \"label\": \"Lower Deduction Certificate\",\n        \"name\": \"Lower Deduction Certificate\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -98,7 +98,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Accounting",
- "modified": "2020-09-09 11:45:33.766400",
+ "modified": "2020-10-08 20:31:46.022470",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounting",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 34c262e..d839478 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -22,8 +22,12 @@
 		return self.voucher_type
 
 	def validate(self):
+		if self.voucher_type == 'Opening Entry':
+			self.is_opening = 'Yes'
+
 		if not self.is_opening:
 			self.is_opening='No'
+
 		self.clearance_date = None
 
 		self.validate_party()
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry_list.js b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
index 7ea60bb..e6d83b9 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
@@ -1,12 +1,14 @@
 frappe.listview_settings['Payment Entry'] = {
 
 	onload: function(listview) {
-		listview.page.fields_dict.party_type.get_query = function() {
-			return {
-				"filters": {
-					"name": ["in", Object.keys(frappe.boot.party_account_types)],
-				}
+		if (listview.page.fields_dict.party_type) {
+			listview.page.fields_dict.party_type.get_query = function() {
+				return {
+					"filters": {
+						"name": ["in", Object.keys(frappe.boot.party_account_types)],
+					}
+				};
 			};
-		};
+		}
 	}
 };
\ No newline at end of file
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/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 2397b7d..cd66f7a 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1825,7 +1825,7 @@
    "fieldtype": "Table",
    "hide_days": 1,
    "hide_seconds": 1,
-   "label": "Sales Team1",
+   "label": "Sales Contributions and Incentives",
    "oldfieldname": "sales_team",
    "oldfieldtype": "Table",
    "options": "Sales Team",
@@ -1946,7 +1946,7 @@
  "idx": 181,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-27 01:56:28.532140",
+ "modified": "2020-10-09 15:59:57.544736",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
index 2980213..f106928 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
@@ -13,8 +13,7 @@
 			'Auto Repeat': 'reference_document',
 		},
 		'internal_links': {
-			'Sales Order': ['items', 'sales_order'],
-			'Delivery Note': ['items', 'delivery_note']
+			'Sales Order': ['items', 'sales_order']
 		},
 		'transactions': [
 			{
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 efdbdb1..fca9559 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/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index bb288c5..1665649 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1319,24 +1319,26 @@
 		validate_quantity(child_item, d)
 
 		child_item.qty = flt(d.get("qty"))
-		precision = child_item.precision("rate") or 2
+		rate_precision = child_item.precision("rate") or 2
+		conv_fac_precision = child_item.precision("conversion_factor") or 2
+		qty_precision = child_item.precision("qty") or 2
 
-		if flt(child_item.billed_amt, precision) > flt(flt(d.get("rate")) * flt(d.get("qty")), precision):
+		if flt(child_item.billed_amt, rate_precision) > flt(flt(d.get("rate"), rate_precision) * flt(d.get("qty"), qty_precision), rate_precision):
 			frappe.throw(_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.")
 						 .format(child_item.idx, child_item.item_code))
 		else:
-			child_item.rate = flt(d.get("rate"))
+			child_item.rate = flt(d.get("rate"), rate_precision)
 
 		if d.get("conversion_factor"):
 			if child_item.stock_uom == child_item.uom:
 				child_item.conversion_factor = 1
 			else:
-				child_item.conversion_factor = flt(d.get('conversion_factor'))
+				child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision)
 
 		if d.get("uom"):
 			child_item.uom = d.get("uom")
 			conversion_factor = flt(get_conversion_factor(child_item.item_code, child_item.uom).get("conversion_factor"))
-			child_item.conversion_factor = flt(d.get('conversion_factor')) or conversion_factor
+			child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision) or conversion_factor
 
 		if d.get("delivery_date") and parent_doctype == 'Sales Order':
 			child_item.delivery_date = d.get('delivery_date')
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index ac567b7..e05c70e 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -847,6 +847,7 @@
 		where
 			t2.parent = t1.name and t1.item = %s
 			and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
+			and t2.sourced_by_supplier = 0
 			and t2.item_code = t3.name""".format(doctype),
 			(item_code, bom), as_dict=1)
 
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index 47b4207..1c4b7a1 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -434,7 +434,8 @@
 				"include_item_in_manufacturing": d.include_item_in_manufacturing,
 				"uom": d.uom,
 				"stock_uom": d.stock_uom,
-				"conversion_factor": d.conversion_factor
+				"conversion_factor": d.conversion_factor,
+				"sourced_by_supplier": d.sourced_by_supplier
 			},
 			callback: function(r) {
 				d = locals[cdt][cdn];
@@ -616,6 +617,22 @@
 	refresh_field("allow_alternative_item", d.name, d.parentfield);
 });
 
+frappe.ui.form.on("BOM Item", "sourced_by_supplier", function(frm, cdt, cdn) {
+	var d = locals[cdt][cdn];
+	if (d.sourced_by_supplier) {
+		d.rate = 0;
+		refresh_field("rate", d.name, d.parentfield);
+	}
+});
+
+frappe.ui.form.on("BOM Item", "rate", function(frm, cdt, cdn) {
+	var d = locals[cdt][cdn];
+	if (d.sourced_by_supplier) {
+		d.rate = 0;
+		refresh_field("rate", d.name, d.parentfield);
+	}
+});
+
 frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) {
 	erpnext.bom.calculate_op_cost(frm.doc);
 	erpnext.bom.calculate_total(frm.doc);
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 3189433..71d49a9 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -137,7 +137,8 @@
 				"qty": item.qty,
 				"uom": item.uom,
 				"stock_uom": item.stock_uom,
-				"conversion_factor": item.conversion_factor
+				"conversion_factor": item.conversion_factor,
+				"sourced_by_supplier": item.sourced_by_supplier
 			})
 			for r in ret:
 				if not item.get(r):
@@ -172,7 +173,8 @@
 			 'qty'			: args.get("qty") or args.get("stock_qty") or 1,
 			 'stock_qty'	: args.get("qty") or args.get("stock_qty") or 1,
 			 'base_rate'	: flt(rate) * (flt(self.conversion_rate) or 1),
-			 'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0
+			 'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0,
+			 'sourced_by_supplier'		: args['sourced_by_supplier'] or 0
 		}
 
 		return ret_item
@@ -191,8 +193,8 @@
 		if arg.get('scrap_items'):
 			rate = get_valuation_rate(arg)
 		elif arg:
-			#Customer Provided parts will have zero rate
-			if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item'):
+			#Customer Provided parts and Supplier sourced parts will have zero rate
+			if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item') and not arg.get('sourced_by_supplier'):
 				if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
 					rate = flt(self.get_bom_unitcost(arg['bom_no'])) * (arg.get("conversion_factor") or 1)
 				else:
@@ -205,7 +207,6 @@
 						else:
 							frappe.msgprint(_("{0} not found for item {1}")
 								.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
-
 		return flt(rate) * flt(self.plc_conversion_rate or 1) / (self.conversion_rate or 1)
 
 	def update_cost(self, update_parent=True, from_child_bom=False, save=True):
@@ -221,7 +222,8 @@
 				"qty": d.qty,
 				"uom": d.uom,
 				"stock_uom": d.stock_uom,
-				"conversion_factor": d.conversion_factor
+				"conversion_factor": d.conversion_factor,
+				"sourced_by_supplier": d.sourced_by_supplier
 			})
 
 			if rate:
@@ -495,7 +497,8 @@
 					'stock_uom'		: d.stock_uom,
 					'stock_qty'		: flt(d.stock_qty),
 					'rate'			: flt(d.base_rate) / (flt(d.conversion_factor) or 1.0),
-					'include_item_in_manufacturing': d.include_item_in_manufacturing
+					'include_item_in_manufacturing': d.include_item_in_manufacturing,
+					'sourced_by_supplier': d.sourced_by_supplier
 				}))
 
 	def company_currency(self):
@@ -521,6 +524,7 @@
 				bom_item.stock_qty,
 				bom_item.rate,
 				bom_item.include_item_in_manufacturing,
+				bom_item.sourced_by_supplier,
 				bom_item.stock_qty / ifnull(bom.quantity, 1) AS qty_consumed_per_unit
 			FROM `tabBOM Explosion Item` bom_item, tabBOM bom
 			WHERE
@@ -539,7 +543,8 @@
 				'stock_uom'				: d['stock_uom'],
 				'stock_qty'				: d['qty_consumed_per_unit'] * stock_qty,
 				'rate'					: flt(d['rate']),
-				'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0)
+				'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0),
+				'sourced_by_supplier': d.get('sourced_by_supplier', 0)
 			}))
 
 	def add_exploded_items(self):
@@ -679,7 +684,7 @@
 			is_stock_item=is_stock_item,
 			qty_field="stock_qty",
 			select_columns = """, bom_item.source_warehouse, bom_item.operation,
-				bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate,
+				bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate, bom_item.sourced_by_supplier,
 				(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
 
 		items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
@@ -692,7 +697,7 @@
 		query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
 			qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty",
 			select_columns = """, bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse,
-				bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing,
+				bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing, bom_item.sourced_by_supplier,
 				bom_item.description, bom_item.base_rate as rate """)
 		items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
 
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index 3dfd03b..eface4d 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -10,6 +10,8 @@
 from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
 from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
 from six import string_types
+from erpnext.stock.doctype.item.test_item import make_item
+from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
 
 test_records = frappe.get_test_records('BOM')
 
@@ -138,6 +140,74 @@
 
 		self.assertEqual(bom.items[0].rate, 20)
 
+	def test_subcontractor_sourced_item(self):
+		item_code = "_Test Subcontracted FG Item 1"
+
+		if not frappe.db.exists('Item', item_code):
+			make_item(item_code, {
+				'is_stock_item': 1,
+				'is_sub_contracted_item': 1,
+				'stock_uom': 'Nos'
+			})
+
+		if not frappe.db.exists('Item', "Test Extra Item 1"):
+			make_item("Test Extra Item 1", {
+				'is_stock_item': 1,
+				'stock_uom': 'Nos'
+			})
+
+		if not frappe.db.exists('Item', "Test Extra Item 2"):
+			make_item("Test Extra Item 2", {
+				'is_stock_item': 1,
+				'stock_uom': 'Nos'
+			})
+
+		if not frappe.db.exists('Item', "Test Extra Item 3"):
+			make_item("Test Extra Item 3", {
+				'is_stock_item': 1,
+				'stock_uom': 'Nos'
+			})
+		bom = frappe.get_doc({
+			'doctype': 'BOM',
+			'is_default': 1,
+			'item': item_code,
+			'currency': 'USD',
+			'quantity': 1,
+			'company': '_Test Company'
+		})
+
+		for item in ["Test Extra Item 1", "Test Extra Item 2"]:
+			item_doc = frappe.get_doc('Item', item)
+
+			bom.append('items', {
+				'item_code': item,
+				'qty': 1,
+				'uom': item_doc.stock_uom,
+				'stock_uom': item_doc.stock_uom,
+				'rate': item_doc.valuation_rate
+			})
+
+		bom.append('items', {
+			'item_code': "Test Extra Item 3",
+			'qty': 1,
+			'uom': item_doc.stock_uom,
+			'stock_uom': item_doc.stock_uom,
+			'rate': 0,
+			'sourced_by_supplier': 1
+		})
+		bom.insert(ignore_permissions=True)
+		bom.update_cost()
+		bom.submit()
+		# test that sourced_by_supplier rate is zero even after updating cost
+		self.assertEqual(bom.items[2].rate, 0)
+		# test in Purchase Order sourced_by_supplier is not added to Supplied Item
+		po = create_purchase_order(item_code=item_code, qty=1,
+			is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
+		bom_items = sorted([d.item_code for d in bom.items if d.sourced_by_supplier != 1])
+		supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
+		self.assertEquals(bom_items, supplied_items)
+
+
 def get_default_bom(item_code="_Test FG Item 2"):
 	return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
 
diff --git a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json
index 9fadbef..f01d856 100644
--- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json
+++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json
@@ -1,626 +1,181 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "hash", 
- "beta": 0, 
- "creation": "2013-03-07 11:42:57", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "autoname": "hash",
+ "creation": "2013-03-07 11:42:57",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "item_code",
+  "item_name",
+  "cb",
+  "source_warehouse",
+  "operation",
+  "section_break_3",
+  "description",
+  "column_break_2",
+  "image",
+  "image_view",
+  "section_break_4",
+  "stock_qty",
+  "rate",
+  "qty_consumed_per_unit",
+  "column_break_8",
+  "stock_uom",
+  "amount",
+  "include_item_in_manufacturing",
+  "sourced_by_supplier"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item_code", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Item Code", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "item_code", 
-   "oldfieldtype": "Link", 
-   "options": "Item", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "in_list_view": 1,
+   "label": "Item Code",
+   "oldfieldname": "item_code",
+   "oldfieldtype": "Link",
+   "options": "Item",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Item Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "item_name",
+   "fieldtype": "Data",
+   "in_global_search": 1,
+   "in_list_view": 1,
+   "label": "Item Name",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "cb", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "cb",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "source_warehouse", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Source Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Warehouse", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "source_warehouse",
+   "fieldtype": "Link",
+   "label": "Source Warehouse",
+   "options": "Warehouse",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "operation", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Operation", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Operation", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "operation",
+   "fieldtype": "Link",
+   "label": "Operation",
+   "options": "Operation",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_3", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_3",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Text Editor", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "description", 
-   "oldfieldtype": "Text", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "300px", 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0, 
+   "fieldname": "description",
+   "fieldtype": "Text Editor",
+   "in_list_view": 1,
+   "label": "Description",
+   "oldfieldname": "description",
+   "oldfieldtype": "Text",
+   "print_width": "300px",
+   "read_only": 1,
    "width": "300px"
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_2", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "image", 
-   "fieldtype": "Attach", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Image", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "image",
+   "fieldtype": "Attach",
+   "hidden": 1,
+   "label": "Image",
+   "print_hide": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "image_view", 
-   "fieldtype": "Image", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Image View", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "image", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "image_view",
+   "fieldtype": "Image",
+   "label": "Image View",
+   "options": "image"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_4", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_4",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "stock_qty", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Stock Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "qty", 
-   "oldfieldtype": "Currency", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "stock_qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Stock Qty",
+   "oldfieldname": "qty",
+   "oldfieldtype": "Currency",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "rate", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Rate", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "standard_rate", 
-   "oldfieldtype": "Currency", 
-   "options": "Company:company:default_currency", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "rate",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Rate",
+   "oldfieldname": "standard_rate",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "qty_consumed_per_unit", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Qty Consumed Per Unit", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "qty_consumed_per_unit",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Qty Consumed Per Unit",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_8", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_8",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "stock_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Stock UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "stock_uom", 
-   "oldfieldtype": "Link", 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "stock_uom",
+   "fieldtype": "Link",
+   "label": "Stock UOM",
+   "oldfieldname": "stock_uom",
+   "oldfieldtype": "Link",
+   "options": "UOM",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "amount_as_per_sr", 
-   "oldfieldtype": "Currency", 
-   "options": "Company:company:default_currency", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "oldfieldname": "amount_as_per_sr",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "include_item_in_manufacturing", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Include Item In Manufacturing", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "default": "0",
+   "fieldname": "include_item_in_manufacturing",
+   "fieldtype": "Check",
+   "label": "Include Item In Manufacturing",
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "sourced_by_supplier",
+   "fieldtype": "Check",
+   "label": "Sourced by Supplier",
+   "read_only": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 1, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-20 19:04:59.813773", 
- "modified_by": "Administrator", 
- "module": "Manufacturing", 
- "name": "BOM Explosion Item", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "idx": 1,
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-10-08 16:21:29.386212",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "BOM Explosion Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json
index e34be61..4c9877f 100644
--- a/erpnext/manufacturing/doctype/bom_item/bom_item.json
+++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json
@@ -37,7 +37,9 @@
   "section_break_27",
   "has_variants",
   "include_item_in_manufacturing",
-  "original_item"
+  "original_item",
+  "column_break_33",
+  "sourced_by_supplier"
  ],
  "fields": [
   {
@@ -272,12 +274,23 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "column_break_33",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "sourced_by_supplier",
+   "fieldtype": "Check",
+   "label": "Sourced by Supplier"
   }
  ],
  "idx": 1,
+ "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-04-09 14:30:26.535546",
+ "modified": "2020-10-08 14:19:37.563300",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "BOM Item",
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/public/js/utils.js b/erpnext/public/js/utils.js
index 9ed5009..6d73418 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -452,6 +452,9 @@
 	const frm = opts.frm;
 	const cannot_add_row = (typeof opts.cannot_add_row === 'undefined') ? true : opts.cannot_add_row;
 	const child_docname = (typeof opts.cannot_add_row === 'undefined') ? "items" : opts.child_docname;
+	const child_meta = frappe.get_meta(`${frm.doc.doctype} Item`);
+	const get_precision = (fieldname) => child_meta.fields.find(f => f.fieldname == fieldname).precision;
+
 	this.data = [];
 	const fields = [{
 		fieldtype:'Data',
@@ -499,14 +502,16 @@
 		default: 0,
 		read_only: 0,
 		in_list_view: 1,
-		label: __('Qty')
+		label: __('Qty'),
+		precision: get_precision("qty")
 	}, {
 		fieldtype:'Currency',
 		fieldname:"rate",
 		default: 0,
 		read_only: 0,
 		in_list_view: 1,
-		label: __('Rate')
+		label: __('Rate'),
+		precision: get_precision("rate")
 	}];
 
 	if (frm.doc.doctype == 'Sales Order' || frm.doc.doctype == 'Purchase Order' ) {
@@ -521,7 +526,8 @@
 			fieldtype: 'Float',
 			fieldname: "conversion_factor",
 			in_list_view: 1,
-			label: __("Conversion Factor")
+			label: __("Conversion Factor"),
+			precision: get_precision('conversion_factor')
 		})
 	}
 
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 1f955fc..0172d9c 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -132,7 +132,7 @@
 				address = frappe.get_doc('Address', address_name.get('name'))
 				if not address.has_link('Customer', self.name):
 					address.append('links', dict(link_doctype='Customer', link_name=self.name))
-					address.save()
+					address.save(ignore_permissions=self.flags.ignore_permissions)
 
 			lead = frappe.db.get_value("Lead", self.lead_name, ["organization_lead", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True)
 
@@ -150,7 +150,7 @@
 					contact = frappe.get_doc('Contact', contact_name.get('name'))
 					if not contact.has_link('Customer', self.name):
 						contact.append('links', dict(link_doctype='Customer', link_name=self.name))
-						contact.save()
+						contact.save(ignore_permissions=self.flags.ignore_permissions)
 
 			else:
 				lead.lead_name = lead.lead_name.lstrip().split(" ")
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 5aef096..1ce36dd 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -403,6 +403,22 @@
 
 		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 2, 'docname': so.items[0].name}])
 		self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
+	
+	def test_update_child_with_precision(self):
+		from frappe.model.meta import get_field_precision
+		from frappe.custom.doctype.property_setter.property_setter import make_property_setter
+
+		precision = get_field_precision(frappe.get_meta("Sales Order Item").get_field("rate"))
+
+		make_property_setter("Sales Order Item", "rate", "precision", 7, "Currency")
+		so = make_sales_order(item_code= "_Test Item", qty=4, rate=200.34664)
+
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200.34669, 'qty' : 4, 'docname': so.items[0].name}])
+		update_child_qty_rate('Sales Order', trans_item, so.name)
+
+		so.reload()
+		self.assertEqual(so.items[0].rate, 200.34669)
+		make_property_setter("Sales Order Item", "rate", "precision", precision, "Currency")
 
 	def test_update_child_perm(self):
 		so = make_sales_order(item_code= "_Test Item", qty=4)
diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json
index 2fba5fa..390fcd9 100644
--- a/erpnext/stock/desk_page/stock/stock.json
+++ b/erpnext/stock/desk_page/stock/stock.json
@@ -3,7 +3,7 @@
   {
    "hidden": 0,
    "label": "Items and Pricing",
-   "links": "[\n    {\n        \"label\": \"Item\",\n        \"name\": \"Item\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Item Group\",\n        \"link\": \"Tree/Item Group\",\n        \"name\": \"Item Group\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Product Bundle\",\n        \"name\": \"Product Bundle\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Price List\",\n        \"name\": \"Price List\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Price\",\n        \"name\": \"Item Price\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Shipping Rule\",\n        \"name\": \"Shipping Rule\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Pricing Rule\",\n        \"name\": \"Pricing Rule\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Alternative\",\n        \"name\": \"Item Alternative\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Manufacturer\",\n        \"name\": \"Item Manufacturer\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Item\",\n        \"name\": \"Item\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Item Group\",\n        \"link\": \"Tree/Item Group\",\n        \"name\": \"Item Group\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Product Bundle\",\n        \"name\": \"Product Bundle\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Price List\",\n        \"name\": \"Price List\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Price\",\n        \"name\": \"Item Price\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Shipping Rule\",\n        \"name\": \"Shipping Rule\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Pricing Rule\",\n        \"name\": \"Pricing Rule\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Alternative\",\n        \"name\": \"Item Alternative\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Manufacturer\",\n        \"name\": \"Item Manufacturer\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Customs Tariff Number\",\n        \"name\": \"Customs Tariff Number\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -18,7 +18,7 @@
   {
    "hidden": 0,
    "label": "Settings",
-   "links": "[\n    {\n        \"label\": \"Stock Settings\",\n        \"name\": \"Stock Settings\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Warehouse\",\n        \"name\": \"Warehouse\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Unit of Measure (UOM)\",\n        \"name\": \"UOM\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Variant Settings\",\n        \"name\": \"Item Variant Settings\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Brand\",\n        \"name\": \"Brand\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Attribute\",\n        \"name\": \"Item Attribute\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Stock Settings\",\n        \"name\": \"Stock Settings\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Warehouse\",\n        \"name\": \"Warehouse\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Unit of Measure (UOM)\",\n        \"name\": \"UOM\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Variant Settings\",\n        \"name\": \"Item Variant Settings\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Brand\",\n        \"name\": \"Brand\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Item Attribute\",\n        \"name\": \"Item Attribute\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"UOM Conversion Factor\",\n        \"name\": \"UOM Conversion Factor\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -58,7 +58,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Stock",
- "modified": "2020-08-11 17:29:32.626067",
+ "modified": "2020-10-07 18:40:17.130207",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index d22fda8..bfdddbb 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -984,9 +984,7 @@
 				if self.stock_ledger_created():
 					return True
 
-			elif frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}) or \
-				frappe.db.get_value("Production Order",
-					filters={"production_item": self.name, "docstatus": 1}):
+			elif frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}):
 				return True
 
 	def validate_auto_reorder_enabled_in_stock_settings(self):
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index c8e3330..298e111 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -5,7 +5,7 @@
 import frappe
 import frappe.share
 from frappe import _
-from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_datetime, get_link_to_form
+from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_datetime, get_link_to_form, date_diff, nowdate
 from erpnext.controllers.status_updater import StatusUpdater
 from erpnext.accounts.utils import get_fiscal_year
 
@@ -29,7 +29,27 @@
 			except ValueError:
 				frappe.throw(_('Invalid Posting Time'))
 
+		self.validate_future_posting()
 		self.validate_with_last_transaction_posting_time()
+	
+	def is_stock_transaction(self):
+		if self.doctype not in ["Sales Invoice", "Purchase Invoice", "Stock Entry", "Stock Reconciliation",
+			"Delivery Note", "Purchase Receipt", "Fees"]:
+				return False
+
+		if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
+			if not (self.get("update_stock") or self.get("is_pos")):
+				return False
+
+		return True
+	
+	def validate_future_posting(self):
+		if not self.is_stock_transaction():
+			return
+
+		if getattr(self, 'set_posting_time', None) and date_diff(self.posting_date, nowdate()) > 0:
+			msg = _("Posting future transactions are not allowed due to Immutable Ledger")
+			frappe.throw(msg, title=_("Future Posting Not Allowed"))
 
 	def add_calendar_event(self, opts, force=False):
 		if cstr(self.contact_by) != cstr(self._prev.contact_by) or \
@@ -162,13 +182,8 @@
 
 	def validate_with_last_transaction_posting_time(self):
 
-		if self.doctype not in ["Sales Invoice", "Purchase Invoice", "Stock Entry", "Stock Reconciliation",
-			"Delivery Note", "Purchase Receipt", "Fees"]:
-				return
-
-		if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
-			if not (self.get("update_stock") or self.get("is_pos")):
-				return
+		if not self.is_stock_transaction():
+			return
 
 		for item in self.get('items'):
 			last_transaction_time = frappe.db.sql("""