fix: mode of payment not fetched if no account is set (#23334)

Co-authored-by: Sagar Vora <sagar@resilient.tech>
diff --git a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py
index 15f23b6..b9e07b8 100644
--- a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py
+++ b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py
@@ -5,13 +5,14 @@
 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
 from erpnext.controllers.status_updater import StatusUpdater
 
 class POSOpeningEntry(StatusUpdater):
 	def validate(self):
 		self.validate_pos_profile_and_cashier()
+		self.validate_payment_method_account()
 		self.set_status()
 
 	def validate_pos_profile_and_cashier(self):
@@ -20,6 +21,14 @@
 
 		if not cint(frappe.db.get_value("User", self.user, "enabled")):
 			frappe.throw(_("User {} has been disabled. Please select valid user/cashier".format(self.user)))
+	
+	def validate_payment_method_account(self):
+		for d in self.balance_details:
+			account = frappe.db.get_value("Mode of Payment Account", 
+				{"parent": d.mode_of_payment, "company": self.company}, "default_account")
+			if not account:
+				frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
+					.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
 
 	def on_submit(self):
 		self.set_status(update=True)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 789b4c3..1386b70 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import msgprint, _
-from frappe.utils import cint, now
+from frappe.utils import cint, now, get_link_to_form
 from six import iteritems
 from frappe.model.document import Document
 
@@ -13,7 +13,7 @@
 		self.validate_default_profile()
 		self.validate_all_link_fields()
 		self.validate_duplicate_groups()
-		self.check_default_payment()
+		self.validate_payment_methods()
 
 	def validate_default_profile(self):
 		for row in self.applicable_for_users:
@@ -52,14 +52,23 @@
 		if len(customer_groups) != len(set(customer_groups)):
 			frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
 
-	def check_default_payment(self):
-		if self.payments:
-			default_mode_of_payment = [d.default for d in self.payments if d.default]
-			if not default_mode_of_payment:
-				frappe.throw(_("Set default mode of payment"))
+	def validate_payment_methods(self):
+		if not self.payments:
+			frappe.throw(_("Payment methods are mandatory. Please add at least one payment method."))
 
-			if len(default_mode_of_payment) > 1:
-				frappe.throw(_("Multiple default mode of payment is not allowed"))
+		default_mode_of_payment = [d.default for d in self.payments if d.default]
+		if not default_mode_of_payment:
+			frappe.throw(_("Please select a default mode of payment"))
+
+		if len(default_mode_of_payment) > 1:
+			frappe.throw(_("You can only select one mode of payment as default"))
+		
+		for d in self.payments:
+			account = frappe.db.get_value("Mode of Payment Account", 
+				{"parent": d.mode_of_payment, "company": self.company}, "default_account")
+			if not account:
+				frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
+					.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
 
 	def on_update(self):
 		self.set_defaults()
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 71f2e12..92e49d5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe, erpnext
 import frappe.defaults
-from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
+from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate, get_link_to_form
 from frappe import _, msgprint, throw
 from erpnext.accounts.party import get_party_account, get_due_date
 from frappe.model.mapper import get_mapped_doc
@@ -1372,7 +1372,7 @@
 		{"parent": mode_of_payment, "company": company}, "default_account")
 	if not account:
 		frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
-			.format(mode_of_payment))
+			.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
 	return {
 		"account": account
 	}
@@ -1612,18 +1612,16 @@
 		payment.type = payment_mode.type
 
 	doc.set('payments', [])
-	if not pos_profile or not pos_profile.get('payments'):
-		for payment_mode in get_all_mode_of_payments(doc):
-			append_payment(payment_mode)
-		return
-
 	for pos_payment_method in pos_profile.get('payments'):
 		pos_payment_method = pos_payment_method.as_dict()
 
 		payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
-		if payment_mode:
-			payment_mode[0].default = pos_payment_method.default
-			append_payment(payment_mode[0])
+		if not payment_mode:
+			frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
+				.format(get_link_to_form("Mode of Payment", pos_payment_method.mode_of_payment)), title=_("Missing Account"))
+
+		payment_mode[0].default = pos_payment_method.default
+		append_payment(payment_mode[0])
 
 def get_all_mode_of_payments(doc):
 	return frappe.db.sql("""