Merge pull request #38543 from s-aga-r/FIX-6734

fix: don't show non-stock items in Stock Analytics report
diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py
index 4f7eeba..e9cbb33 100644
--- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py
+++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py
@@ -214,7 +214,7 @@
 				# round off balance based on currency precision
 				# and consider debit-credit difference allowance
 				currency_precision = get_currency_precision()
-				rounding_loss_allowance = float(rounding_loss_allowance) or 0.05
+				rounding_loss_allowance = float(rounding_loss_allowance)
 				for acc in account_details:
 					acc.balance_in_account_currency = flt(acc.balance_in_account_currency, currency_precision)
 					if abs(acc.balance_in_account_currency) <= rounding_loss_allowance:
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index dfb5caf..1282ab6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -106,9 +106,17 @@
 		self.set_status()
 
 	def set_liability_account(self):
-		if not self.book_advance_payments_in_separate_party_account:
+		# Auto setting liability account should only be done during 'draft' status
+		if self.docstatus > 0:
 			return
 
+		if not frappe.db.get_value(
+			"Company", self.company, "book_advance_payments_in_separate_party_account"
+		):
+			return
+
+		# Important to set this flag for the gl building logic to work properly
+		self.book_advance_payments_in_separate_party_account = True
 		account_type = frappe.get_value(
 			"Account", {"name": self.party_account, "company": self.company}, "account_type"
 		)
@@ -118,11 +126,13 @@
 		):
 			return
 
-		if self.unallocated_amount == 0:
-			for d in self.references:
-				if d.reference_doctype in ["Sales Order", "Purchase Order"]:
-					break
-			else:
+		if self.references:
+			allowed_types = frozenset(["Sales Order", "Purchase Order"])
+			reference_types = set([x.reference_doctype for x in self.references])
+
+			# If there are referencers other than `allowed_types`, treat this as a normal payment entry
+			if reference_types - allowed_types:
+				self.book_advance_payments_in_separate_party_account = False
 				return
 
 		liability_account = get_party_account(
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 5c18e50..1efe35c 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -195,7 +195,7 @@
 	company_address=None,
 	shipping_address=None,
 	*,
-	ignore_permissions=False
+	ignore_permissions=False,
 ):
 	billing_address_field = (
 		"customer_address" if party_type == "Lead" else party_type.lower() + "_address"
@@ -239,7 +239,7 @@
 				shipping_address_display=render_address(
 					shipping_address, check_permissions=not ignore_permissions
 				),
-				**get_fetch_values(doctype, "shipping_address", shipping_address)
+				**get_fetch_values(doctype, "shipping_address", shipping_address),
 			)
 
 		if party_details.company_address:
@@ -250,7 +250,7 @@
 					party_details.company_address_display
 					or render_address(party_details.company_address, check_permissions=False)
 				),
-				**get_fetch_values(doctype, "billing_address", party_details.company_address)
+				**get_fetch_values(doctype, "billing_address", party_details.company_address),
 			)
 
 			# shipping address - if not already set
@@ -258,7 +258,7 @@
 				party_details.update(
 					shipping_address=party_details.billing_address,
 					shipping_address_display=party_details.billing_address_display,
-					**get_fetch_values(doctype, "shipping_address", party_details.billing_address)
+					**get_fetch_values(doctype, "shipping_address", party_details.billing_address),
 				)
 
 	party_address, shipping_address = (
@@ -981,6 +981,9 @@
 	if party:
 		query = query.where(ple.party == party)
 
+	if invoice_doctypes := frappe.get_hooks("invoice_doctypes"):
+		query = query.where(ple.voucher_type.notin(invoice_doctypes))
+
 	data = query.run()
 	if data:
 		return frappe._dict(data)
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index ad196a9..9c6e2d0 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -319,7 +319,7 @@
 			`tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company,
 			`tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total,
 			`tabPurchase Invoice`.unrealized_profit_loss_account,
-			`tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description,
+			`tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description, `tabPurchase Invoice Item`.`item_group`,
 			`tabPurchase Invoice Item`.`item_name` as pi_item_name, `tabPurchase Invoice Item`.`item_group` as pi_item_group,
 			`tabItem`.`item_name` as i_item_name, `tabItem`.`item_group` as i_item_group,
 			`tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`,
diff --git a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py
index cb6e8a1..9f3ba0d 100644
--- a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py
+++ b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py
@@ -3,7 +3,8 @@
 
 
 import frappe
-from frappe import _, msgprint
+from frappe import _, msgprint, qb
+from frappe.query_builder import Criterion
 
 from erpnext import get_company_currency
 
@@ -214,24 +215,33 @@
 	if items:
 		conditions.append("dt_item.item_code in (%s)" % ", ".join(["%s"] * len(items)))
 		values += items
+	else:
+		# return empty result, if no items are fetched after filtering on 'item group' and 'brand'
+		conditions.append("dt_item.item_code = Null")
 
 	return " and ".join(conditions), values
 
 
 def get_items(filters):
+	item = qb.DocType("Item")
+
+	item_query_conditions = []
 	if filters.get("item_group"):
-		key = "item_group"
-	elif filters.get("brand"):
-		key = "brand"
-	else:
-		key = ""
-
-	items = []
-	if key:
-		items = frappe.db.sql_list(
-			"""select name from tabItem where %s = %s""" % (key, "%s"), (filters[key])
+		# Handle 'Parent' nodes as well.
+		item_group = qb.DocType("Item Group")
+		lft, rgt = frappe.db.get_all(
+			"Item Group", filters={"name": filters.get("item_group")}, fields=["lft", "rgt"], as_list=True
+		)[0]
+		item_group_query = (
+			qb.from_(item_group)
+			.select(item_group.name)
+			.where((item_group.lft >= lft) & (item_group.rgt <= rgt))
 		)
+		item_query_conditions.append(item.item_group.isin(item_group_query))
+	if filters.get("brand"):
+		item_query_conditions.append(item.brand == filters.get("brand"))
 
+	items = qb.from_(item).select(item.name).where(Criterion.all(item_query_conditions)).run()
 	return items