From 836fd8fbc4a873e4dde27d130b0006ad3eb354d5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:07:36 +0530 Subject: [PATCH] fix: consider journal entry and return invoice in paid_amount calculation (backport #46129) (#46319) fix: consider journal entry and return invoice in paid_amount calculation (#46129) * fix: consider journal entry and return invoice in paid_amount calculation * test: add new unit test to consider journal entry and return invoice in paid_amount calculation (cherry picked from commit 425fb12e9162f06b7868738d94e6df68c27d99a0) Co-authored-by: Sugesh G <73237300+Sugesh393@users.noreply.github.com> --- .../payment_request/payment_request.py | 40 ++++++++++++------- .../payment_request/test_payment_request.py | 28 +++++++++++++ 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 84e44621784..4f6205a2445 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -768,29 +768,39 @@ def get_existing_payment_request_amount(ref_dt, ref_dn, statuses: list | None = def get_existing_paid_amount(doctype, name): - PL = frappe.qb.DocType("Payment Ledger Entry") + PLE = frappe.qb.DocType("Payment Ledger Entry") PER = frappe.qb.DocType("Payment Entry Reference") query = ( - frappe.qb.from_(PL) + frappe.qb.from_(PLE) .left_join(PER) .on( - (PL.against_voucher_type == PER.reference_doctype) - & (PL.against_voucher_no == PER.reference_name) - & (PL.voucher_type == PER.parenttype) - & (PL.voucher_no == PER.parent) + (PLE.against_voucher_type == PER.reference_doctype) + & (PLE.against_voucher_no == PER.reference_name) + & (PLE.voucher_type == PER.parenttype) + & (PLE.voucher_no == PER.parent) + ) + .select( + Abs(Sum(PLE.amount)).as_("total_amount"), + Abs(Sum(frappe.qb.terms.Case().when(PER.payment_request.isnotnull(), PLE.amount).else_(0))).as_( + "request_paid_amount" + ), + ) + .where( + (PLE.voucher_type.isin([doctype, "Journal Entry", "Payment Entry"])) + & (PLE.against_voucher_type == doctype) + & (PLE.against_voucher_no == name) + & (PLE.delinked == 0) + & (PLE.docstatus == 1) + & (PLE.amount < 0) ) - .select(Abs(Sum(PL.amount)).as_("total_paid_amount")) - .where(PL.against_voucher_type.eq(doctype)) - .where(PL.against_voucher_no.eq(name)) - .where(PL.amount < 0) - .where(PL.delinked == 0) - .where(PER.docstatus == 1) - .where(PER.payment_request.isnull()) ) - response = query.run() - return response[0][0] if response[0] else 0 + result = query.run() + ledger_amount = flt(result[0][0]) if result else 0 + request_paid_amount = flt(result[0][1]) if result else 0 + + return ledger_amount - request_paid_amount def get_gateway_details(args): # nosemgrep diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py index 7ce6cc0b7b7..02ecb85ac4d 100644 --- a/erpnext/accounts/doctype/payment_request/test_payment_request.py +++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py @@ -581,6 +581,34 @@ class TestPaymentRequest(FrappeTestCase): pi.load_from_db() self.assertEqual(pr_2.grand_total, pi.outstanding_amount) + def test_consider_journal_entry_and_return_invoice(self): + from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry + + si = create_sales_invoice(currency="INR", qty=5, rate=500) + + je = make_journal_entry("_Test Cash - _TC", "Debtors - _TC", 500, save=False) + je.accounts[1].party_type = "Customer" + je.accounts[1].party = si.customer + je.accounts[1].reference_type = "Sales Invoice" + je.accounts[1].reference_name = si.name + je.accounts[1].credit_in_account_currency = 500 + je.submit() + + pe = get_payment_entry("Sales Invoice", si.name) + pe.paid_amount = 500 + pe.references[0].allocated_amount = 500 + pe.save() + pe.submit() + + cr_note = create_sales_invoice(qty=-1, rate=500, is_return=1, return_against=si.name, do_not_save=1) + cr_note.update_outstanding_for_self = 0 + cr_note.save() + cr_note.submit() + + si.load_from_db() + pr = make_payment_request(dt="Sales Invoice", dn=si.name, mute_email=1) + self.assertEqual(pr.grand_total, si.outstanding_amount) + def test_partial_paid_invoice_with_submitted_payment_entry(self): pi = make_purchase_invoice(currency="INR", qty=1, rate=5000)