diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 2989414ead1..c3d11d34532 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -46,23 +46,27 @@ frappe.ui.form.on("Payment Entry", { }, setup: function (frm) { - frm.set_query("paid_from", function () { + frm.set_query("paid_from", function (doc) { frm.events.validate_company(frm); var account_types = ["Pay", "Internal Transfer"].includes(frm.doc.payment_type) ? ["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]]; + let filters = { + account_type: ["in", account_types], + is_group: 0, + company: doc.company, + }; if (frm.doc.party_type == "Shareholder") { account_types.push("Equity"); } + if (doc.payment_type == "Internal Transfer" && doc.paid_to) { + filters.name = ["!=", doc.paid_to]; + } return { - filters: { - account_type: ["in", account_types], - is_group: 0, - company: frm.doc.company, - }, + filters, }; }); @@ -106,21 +110,25 @@ frappe.ui.form.on("Payment Entry", { } }); - frm.set_query("paid_to", function () { + frm.set_query("paid_to", function (doc) { frm.events.validate_company(frm); var account_types = ["Receive", "Internal Transfer"].includes(frm.doc.payment_type) ? ["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]]; + let filters = { + account_type: ["in", account_types], + is_group: 0, + company: doc.company, + }; if (frm.doc.party_type == "Shareholder") { account_types.push("Equity"); } + if (doc.payment_type == "Internal Transfer" && doc.paid_from) { + filters.name = ["!=", doc.paid_from]; + } return { - filters: { - account_type: ["in", account_types], - is_group: 0, - company: frm.doc.company, - }, + filters, }; }); diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 9c3f5583607..8216b0fe886 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -176,6 +176,7 @@ class PaymentEntry(AccountsController): self.set_liability_account() self.set_missing_ref_details(force=True) self.validate_payment_type() + self.validate_internal_transfer_accounts() self.validate_party_details() self.set_exchange_rate() self.validate_mandatory() @@ -627,6 +628,10 @@ class PaymentEntry(AccountsController): if self.payment_type not in ("Receive", "Pay", "Internal Transfer"): frappe.throw(_("Payment Type must be one of Receive, Pay, or Internal Transfer")) + def validate_internal_transfer_accounts(self): + if self.payment_type == "Internal Transfer" and self.paid_from and self.paid_from == self.paid_to: + frappe.throw(_("Paid From and Paid To accounts must be different for an Internal Transfer.")) + def validate_party_details(self): if self.party and not frappe.db.exists(self.party_type, self.party): frappe.throw(_("{0} {1} does not exist").format(_(self.party_type), self.party)) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 179bbcec97f..5be612f535d 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -782,6 +782,23 @@ class TestPaymentEntry(ERPNextTestSuite): self.validate_gl_entries(pe.name, expected_gle) + def test_internal_transfer_rejects_same_account(self): + pe = frappe.new_doc("Payment Entry") + pe.payment_type = "Internal Transfer" + pe.company = "_Test Company" + pe.paid_from = "_Test Bank - _TC" + pe.paid_to = "_Test Bank - _TC" + pe.paid_amount = 100 + pe.received_amount = 100 + pe.reference_no = "same-account-transfer" + pe.reference_date = nowdate() + + self.assertRaisesRegex( + frappe.ValidationError, + "Paid From and Paid To accounts must be different", + pe.insert, + ) + def test_bank_charges_deduction(self): bank_charges_account = create_account( parent_account="Indirect Expenses - _TC",