Merge pull request #39525 from rohitwaghchaure/fixed-auto-mr-email-with-user-permissions-issue

fix: email list for auto reorder material request
diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py
index 3e44049..48397a3 100644
--- a/erpnext/stock/doctype/material_request/test_material_request.py
+++ b/erpnext/stock/doctype/material_request/test_material_request.py
@@ -774,6 +774,62 @@
 		self.assertEqual(mr.per_ordered, 100)
 		self.assertEqual(existing_requested_qty, current_requested_qty)
 
+	def test_auto_email_users_with_company_user_permissions(self):
+		from erpnext.stock.reorder_item import get_email_list
+
+		comapnywise_users = {
+			"_Test Company": "test_auto_email_@example.com",
+			"_Test Company 1": "test_auto_email_1@example.com",
+		}
+
+		permissions = []
+
+		for company, user in comapnywise_users.items():
+			if not frappe.db.exists("User", user):
+				frappe.get_doc(
+					{
+						"doctype": "User",
+						"email": user,
+						"first_name": user,
+						"send_notifications": 0,
+						"enabled": 1,
+						"user_type": "System User",
+						"roles": [{"role": "Purchase Manager"}],
+					}
+				).insert(ignore_permissions=True)
+
+			if not frappe.db.exists(
+				"User Permission", {"user": user, "allow": "Company", "for_value": company}
+			):
+				perm_doc = frappe.get_doc(
+					{
+						"doctype": "User Permission",
+						"user": user,
+						"allow": "Company",
+						"for_value": company,
+						"apply_to_all_doctypes": 1,
+					}
+				).insert(ignore_permissions=True)
+
+				permissions.append(perm_doc)
+
+		comapnywise_mr_list = frappe._dict({})
+		mr1 = make_material_request()
+		comapnywise_mr_list.setdefault(mr1.company, []).append(mr1.name)
+
+		mr2 = make_material_request(
+			company="_Test Company 1", warehouse="Stores - _TC1", cost_center="Main - _TC1"
+		)
+		comapnywise_mr_list.setdefault(mr2.company, []).append(mr2.name)
+
+		for company, mr_list in comapnywise_mr_list.items():
+			emails = get_email_list(company)
+
+			self.assertTrue(comapnywise_users[company] in emails)
+
+		for perm in permissions:
+			perm.delete()
+
 
 def get_in_transit_warehouse(company):
 	if not frappe.db.exists("Warehouse Type", "Transit"):
diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py
index 1f5f41a..276531a 100644
--- a/erpnext/stock/reorder_item.py
+++ b/erpnext/stock/reorder_item.py
@@ -145,6 +145,7 @@
 
 		mr.log_error("Unable to create material request")
 
+	company_wise_mr = frappe._dict({})
 	for request_type in material_requests:
 		for company in material_requests[request_type]:
 			try:
@@ -206,17 +207,19 @@
 				mr.submit()
 				mr_list.append(mr)
 
+				company_wise_mr.setdefault(company, []).append(mr)
+
 			except Exception:
 				_log_exception(mr)
 
-	if mr_list:
+	if company_wise_mr:
 		if getattr(frappe.local, "reorder_email_notify", None) is None:
 			frappe.local.reorder_email_notify = cint(
 				frappe.db.get_single_value("Stock Settings", "reorder_email_notify")
 			)
 
 		if frappe.local.reorder_email_notify:
-			send_email_notification(mr_list)
+			send_email_notification(company_wise_mr)
 
 	if exceptions_list:
 		notify_errors(exceptions_list)
@@ -224,20 +227,56 @@
 	return mr_list
 
 
-def send_email_notification(mr_list):
+def send_email_notification(company_wise_mr):
 	"""Notify user about auto creation of indent"""
 
-	email_list = frappe.db.sql_list(
-		"""select distinct r.parent
-		from `tabHas Role` r, tabUser p
-		where p.name = r.parent and p.enabled = 1 and p.docstatus < 2
-		and r.role in ('Purchase Manager','Stock Manager')
-		and p.name not in ('Administrator', 'All', 'Guest')"""
+	for company, mr_list in company_wise_mr.items():
+		email_list = get_email_list(company)
+
+		if not email_list:
+			continue
+
+		msg = frappe.render_template("templates/emails/reorder_item.html", {"mr_list": mr_list})
+
+		frappe.sendmail(
+			recipients=email_list, subject=_("Auto Material Requests Generated"), message=msg
+		)
+
+
+def get_email_list(company):
+	users = get_comapny_wise_users(company)
+	user_table = frappe.qb.DocType("User")
+	role_table = frappe.qb.DocType("Has Role")
+
+	query = (
+		frappe.qb.from_(user_table)
+		.inner_join(role_table)
+		.on(user_table.name == role_table.parent)
+		.select(user_table.email)
+		.where(
+			(role_table.role.isin(["Purchase Manager", "Stock Manager"]))
+			& (user_table.name.notin(["Administrator", "All", "Guest"]))
+			& (user_table.enabled == 1)
+			& (user_table.docstatus < 2)
+		)
 	)
 
-	msg = frappe.render_template("templates/emails/reorder_item.html", {"mr_list": mr_list})
+	if users:
+		query = query.where(user_table.name.isin(users))
 
-	frappe.sendmail(recipients=email_list, subject=_("Auto Material Requests Generated"), message=msg)
+	emails = query.run(as_dict=True)
+
+	return list(set([email.email for email in emails]))
+
+
+def get_comapny_wise_users(company):
+	users = frappe.get_all(
+		"User Permission",
+		filters={"allow": "Company", "for_value": company, "apply_to_all_doctypes": 1},
+		fields=["user"],
+	)
+
+	return [user.user for user in users]
 
 
 def notify_errors(exceptions_list):