Merge branch 'develop' into fix_test_scrap_asset
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 986fc03..3020e6d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -98,7 +98,6 @@
   "section_break_44",
   "apply_discount_on",
   "base_discount_amount",
-  "additional_discount_account",
   "column_break_46",
   "additional_discount_percentage",
   "discount_amount",
@@ -1388,12 +1387,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "additional_discount_account",
-   "fieldtype": "Link",
-   "label": "Additional Discount Account",
-   "options": "Account"
-  },
-  {
    "default": "0",
    "fieldname": "ignore_default_payment_terms_template",
    "fieldtype": "Check",
@@ -1445,7 +1438,7 @@
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-09-13 23:39:54.525037",
+ "modified": "2022-09-27 11:07:55.766844",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index d185300..2b633cb 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -669,9 +669,6 @@
 
 		exchange_rate_map, net_rate_map = get_purchase_document_details(self)
 
-		enable_discount_accounting = cint(
-			frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
-		)
 		provisional_accounting_for_non_stock_items = cint(
 			frappe.db.get_value(
 				"Company", self.company, "enable_provisional_accounting_for_non_stock_items"
@@ -1159,9 +1156,6 @@
 	def make_tax_gl_entries(self, gl_entries):
 		# tax table gl entries
 		valuation_tax = {}
-		enable_discount_accounting = cint(
-			frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
-		)
 
 		for tax in self.get("taxes"):
 			amount, base_amount = self.get_tax_amounts(tax, None)
@@ -1249,15 +1243,6 @@
 						)
 					)
 
-	@property
-	def enable_discount_accounting(self):
-		if not hasattr(self, "_enable_discount_accounting"):
-			self._enable_discount_accounting = cint(
-				frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
-			)
-
-		return self._enable_discount_accounting
-
 	def make_internal_transfer_gl_entries(self, gl_entries):
 		if self.is_internal_transfer() and flt(self.base_total_taxes_and_charges):
 			account_currency = get_account_currency(self.unrealized_profit_loss_account)
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 7fa2fe2..fca7e3a 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -74,7 +74,6 @@
   "manufacturer_part_no",
   "accounting",
   "expense_account",
-  "discount_account",
   "col_break5",
   "is_fixed_asset",
   "asset_location",
@@ -861,12 +860,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "discount_account",
-   "fieldtype": "Link",
-   "label": "Discount Account",
-   "options": "Account"
-  },
-  {
    "fieldname": "product_bundle",
    "fieldtype": "Link",
    "label": "Product Bundle",
@@ -877,7 +870,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2022-06-17 05:31:10.520171",
+ "modified": "2022-09-27 10:54:23.980713",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice Item",
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 0b5df9e..84c2c9a 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -335,6 +335,9 @@
 		"party": ["in", parties],
 	}
 
+	if party_type == "Customer":
+		filters.update({"against_voucher": ["is", "not set"]})
+
 	if company:
 		filters["company"] = company
 	if from_date and to_date:
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index 33bd3c7..06e3c61 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -370,7 +370,7 @@
 				where parent=`tabSales Invoice`.name
 					and ifnull(`tab{table}`.{field}, '') = %({field})s)"""
 
-	conditions += get_sales_invoice_item_field_condition("mode_of_payments", "Sales Invoice Payment")
+	conditions += get_sales_invoice_item_field_condition("mode_of_payment", "Sales Invoice Payment")
 	conditions += get_sales_invoice_item_field_condition("cost_center")
 	conditions += get_sales_invoice_item_field_condition("warehouse")
 	conditions += get_sales_invoice_item_field_condition("brand")
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index aad2607..28158a3 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -20,7 +20,6 @@
   "maintain_same_rate",
   "allow_multiple_items",
   "bill_for_rejected_quantity_in_purchase_invoice",
-  "enable_discount_accounting",
   "subcontract",
   "backflush_raw_materials_of_subcontract_based_on",
   "column_break_11",
@@ -134,13 +133,6 @@
   {
    "fieldname": "column_break_12",
    "fieldtype": "Column Break"
-  },
-  {
-   "default": "0",
-   "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account",
-   "fieldname": "enable_discount_accounting",
-   "fieldtype": "Check",
-   "label": "Enable Discount Accounting for Buying"
   }
  ],
  "icon": "fa fa-cog",
@@ -148,7 +140,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2022-09-01 18:01:34.994657",
+ "modified": "2022-09-27 10:50:27.050252",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying Settings",
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py
index 7b18cdb..be1ebde 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.py
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.py
@@ -5,15 +5,10 @@
 
 
 import frappe
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
 from frappe.model.document import Document
-from frappe.utils import cint
 
 
 class BuyingSettings(Document):
-	def on_update(self):
-		self.toggle_discount_accounting_fields()
-
 	def validate(self):
 		for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
 			frappe.db.set_default(key, self.get(key, ""))
@@ -26,60 +21,3 @@
 			self.get("supp_master_name") == "Naming Series",
 			hide_name_field=False,
 		)
-
-	def toggle_discount_accounting_fields(self):
-		enable_discount_accounting = cint(self.enable_discount_accounting)
-
-		make_property_setter(
-			"Purchase Invoice Item",
-			"discount_account",
-			"hidden",
-			not (enable_discount_accounting),
-			"Check",
-			validate_fields_for_doctype=False,
-		)
-		if enable_discount_accounting:
-			make_property_setter(
-				"Purchase Invoice Item",
-				"discount_account",
-				"mandatory_depends_on",
-				"eval: doc.discount_amount",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
-		else:
-			make_property_setter(
-				"Purchase Invoice Item",
-				"discount_account",
-				"mandatory_depends_on",
-				"",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
-
-		make_property_setter(
-			"Purchase Invoice",
-			"additional_discount_account",
-			"hidden",
-			not (enable_discount_accounting),
-			"Check",
-			validate_fields_for_doctype=False,
-		)
-		if enable_discount_accounting:
-			make_property_setter(
-				"Purchase Invoice",
-				"additional_discount_account",
-				"mandatory_depends_on",
-				"eval: doc.discount_amount",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
-		else:
-			make_property_setter(
-				"Purchase Invoice",
-				"additional_discount_account",
-				"mandatory_depends_on",
-				"",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index fc99d77..ddf81ca 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -33,6 +33,7 @@
 		frm.set_query("fg_item", "items", function() {
 			return {
 				filters: {
+					'is_stock_item': 1,
 					'is_sub_contracted_item': 1,
 					'default_bom': ['!=', '']
 				}
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 4f8b5c7..8eae0a0 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -212,21 +212,15 @@
 	meta = frappe.get_meta(doctype, cached=True)
 	searchfields = meta.get_search_fields()
 
-	# these are handled separately
-	ignored_search_fields = ("item_name", "description")
-	for ignored_field in ignored_search_fields:
-		if ignored_field in searchfields:
-			searchfields.remove(ignored_field)
-
 	columns = ""
-	extra_searchfields = [
-		field
-		for field in searchfields
-		if not field in ["name", "item_group", "description", "item_name"]
-	]
+	extra_searchfields = [field for field in searchfields if not field in ["name", "description"]]
 
 	if extra_searchfields:
-		columns = ", " + ", ".join(extra_searchfields)
+		columns += ", " + ", ".join(extra_searchfields)
+
+	if "description" in searchfields:
+		columns += """, if(length(tabItem.description) > 40, \
+			concat(substr(tabItem.description, 1, 40), "..."), description) as description"""
 
 	searchfields = searchfields + [
 		field
@@ -266,12 +260,10 @@
 	if frappe.db.count(doctype, cache=True) < 50000:
 		# scan description only if items are less than 50000
 		description_cond = "or tabItem.description LIKE %(txt)s"
+
 	return frappe.db.sql(
 		"""select
-			tabItem.name, tabItem.item_name, tabItem.item_group,
-		if(length(tabItem.description) > 40, \
-			concat(substr(tabItem.description, 1, 40), "..."), description) as description
-		{columns}
+			tabItem.name {columns}
 		from tabItem
 		where tabItem.docstatus < 2
 			and tabItem.disabled=0
diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py
index 6bc88d1..aa4468c 100644
--- a/erpnext/controllers/subcontracting_controller.py
+++ b/erpnext/controllers/subcontracting_controller.py
@@ -69,9 +69,18 @@
 
 	def validate_items(self):
 		for item in self.items:
-			if not frappe.get_value("Item", item.item_code, "is_sub_contracted_item"):
+			is_stock_item, is_sub_contracted_item = frappe.get_value(
+				"Item", item.item_code, ["is_stock_item", "is_sub_contracted_item"]
+			)
+
+			if not is_stock_item:
+				msg = f"Item {item.item_name} must be a stock item."
+				frappe.throw(_(msg))
+
+			if not is_sub_contracted_item:
 				msg = f"Item {item.item_name} must be a subcontracted item."
 				frappe.throw(_(msg))
+
 			if item.bom:
 				bom = frappe.get_doc("BOM", item.bom)
 				if not bom.is_active:
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 6ef77f3..b8f51f8 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -508,6 +508,7 @@
 	"Landed Cost Item",
 	"Asset Value Adjustment",
 	"Asset Repair",
+	"Asset Capitalization",
 	"Loyalty Program",
 	"Stock Reconciliation",
 	"POS Profile",
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 2a0ca8c..fc63f12 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -315,3 +315,4 @@
 erpnext.patches.v14_0.create_accounting_dimensions_in_subcontracting_doctypes
 erpnext.patches.v14_0.fix_subcontracting_receipt_gl_entries
 erpnext.patches.v14_0.migrate_remarks_from_gl_to_payment_ledger
+erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization
diff --git a/erpnext/patches/v14_0/create_accounting_dimensions_for_asset_capitalization.py b/erpnext/patches/v14_0/create_accounting_dimensions_for_asset_capitalization.py
new file mode 100644
index 0000000..09e20a9
--- /dev/null
+++ b/erpnext/patches/v14_0/create_accounting_dimensions_for_asset_capitalization.py
@@ -0,0 +1,31 @@
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_field
+
+
+def execute():
+	accounting_dimensions = frappe.db.get_all(
+		"Accounting Dimension", fields=["fieldname", "label", "document_type", "disabled"]
+	)
+
+	if not accounting_dimensions:
+		return
+
+	doctype = "Asset Capitalization"
+
+	for d in accounting_dimensions:
+		field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
+
+		if field:
+			continue
+
+		df = {
+			"fieldname": d.fieldname,
+			"label": d.label,
+			"fieldtype": "Link",
+			"options": d.document_type,
+			"insert_after": "accounting_dimensions_section",
+		}
+
+		create_custom_field(doctype, df, ignore_validate=True)
+
+	frappe.clear_cache(doctype=doctype)
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 7e1476d..e61f0f5 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -10,6 +10,31 @@
 		frm.add_fetch('attribute', 'to_range', 'to_range');
 		frm.add_fetch('attribute', 'increment', 'increment');
 		frm.add_fetch('tax_type', 'tax_rate', 'tax_rate');
+
+		frm.make_methods = {
+			'Sales Order': () => {
+				open_form(frm, "Sales Order", "Sales Order Item", "items");
+			},
+			'Delivery Note': () => {
+				open_form(frm, "Delivery Note", "Delivery Note Item", "items");
+			},
+			'Sales Invoice': () => {
+				open_form(frm, "Sales Invoice", "Sales Invoice Item", "items");
+			},
+			'Purchase Order': () => {
+				open_form(frm, "Purchase Order", "Purchase Order Item", "items");
+			},
+			'Purchase Receipt': () => {
+				open_form(frm, "Purchase Receipt", "Purchase Receipt Item", "items");
+			},
+			'Purchase Invoice': () => {
+				open_form(frm, "Purchase Invoice", "Purchase Invoice Item", "items");
+			},
+			'Material Request': () => {
+				open_form(frm, "Material Request", "Material Request Item", "items");
+			},
+		};
+
 	},
 	onload: function(frm) {
 		erpnext.item.setup_queries(frm);
@@ -858,3 +883,17 @@
 
 
 ];
+
+function open_form(frm, doctype, child_doctype, parentfield) {
+	frappe.model.with_doctype(doctype, () => {
+		let new_doc = frappe.model.get_new_doc(doctype);
+
+		let new_child_doc = frappe.model.add_child(new_doc, child_doctype, parentfield);
+		new_child_doc.item_code = frm.doc.name;
+		new_child_doc.item_name = frm.doc.item_name;
+		new_child_doc.uom = frm.doc.stock_uom;
+		new_child_doc.description = frm.doc.description;
+
+		frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
+	});
+}
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 143fe40..c8bb1b9 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -937,17 +937,21 @@
 				"Purchase Order Item",
 				"Material Request Item",
 				"Product Bundle",
+				"BOM",
 			]
 
 		for doctype in linked_doctypes:
 			filters = {"item_code": self.name, "docstatus": 1}
 
-			if doctype == "Product Bundle":
-				filters = {"new_item_code": self.name}
+			if doctype in ("Product Bundle", "BOM"):
+				if doctype == "Product Bundle":
+					filters = {"new_item_code": self.name}
+					fieldname = "new_item_code as docname"
+				else:
+					filters = {"item": self.name, "docstatus": 1}
+					fieldname = "name as docname"
 
-				if linked_doc := frappe.db.get_value(
-					doctype, filters, ["new_item_code as docname"], as_dict=True
-				):
+				if linked_doc := frappe.db.get_value(doctype, filters, fieldname, as_dict=True):
 					return linked_doc.update({"doctype": doctype})
 
 			elif doctype in (
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 1cee553..e35c8bf 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -5,6 +5,7 @@
 import json
 
 import frappe
+from frappe.custom.doctype.property_setter.property_setter import make_property_setter
 from frappe.test_runner import make_test_objects
 from frappe.tests.utils import FrappeTestCase, change_settings
 from frappe.utils import add_days, today
@@ -816,6 +817,30 @@
 		item.reload()
 		self.assertEqual(item.is_stock_item, 1)
 
+	def test_serach_fields_for_item(self):
+		from erpnext.controllers.queries import item_query
+
+		make_property_setter("Item", None, "search_fields", "item_name", "Data", for_doctype="Doctype")
+
+		item = make_item(properties={"item_name": "Test Item", "description": "Test Description"})
+		data = item_query(
+			"Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True
+		)
+		self.assertEqual(data[0].name, item.name)
+		self.assertEqual(data[0].item_name, item.item_name)
+		self.assertTrue("description" not in data[0])
+
+		make_property_setter(
+			"Item", None, "search_fields", "item_name, description", "Data", for_doctype="Doctype"
+		)
+		data = item_query(
+			"Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True
+		)
+		self.assertEqual(data[0].name, item.name)
+		self.assertEqual(data[0].item_name, item.item_name)
+		self.assertEqual(data[0].description, item.description)
+		self.assertTrue("description" in data[0])
+
 
 def set_item_variant_settings(fields):
 	doc = frappe.get_doc("Item Variant Settings")
diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html
index a10870d..ec1d497 100644
--- a/erpnext/templates/pages/order.html
+++ b/erpnext/templates/pages/order.html
@@ -18,7 +18,7 @@
 			<b class="caret"></b>
 		</button>
 		<ul class="dropdown-menu dropdown-menu-right" role="menu">
-			{% if doc.doctype == 'Purchase Order' %}
+			{% if doc.doctype == 'Purchase Order' and show_make_pi_button %}
 				<a class="dropdown-item" href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}" data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}</a>
 			{% endif %}
 			<a class="dropdown-item" href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}'
diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py
index 3e6d57a..e1e12bd 100644
--- a/erpnext/templates/pages/order.py
+++ b/erpnext/templates/pages/order.py
@@ -52,6 +52,9 @@
 		)
 		context.available_loyalty_points = int(loyalty_program_details.get("loyalty_points"))
 
+	# show Make Purchase Invoice button based on permission
+	context.show_make_pi_button = frappe.has_permission("Purchase Invoice", "create")
+
 
 def get_attachments(dt, dn):
 	return frappe.get_all(