From 6c2f9a563e8d6b7bec0c846ec755ab7bc8b7a3d2 Mon Sep 17 00:00:00 2001 From: Sugesh393 Date: Tue, 11 Mar 2025 11:49:35 +0530 Subject: [PATCH] fix: add base_outstanding and base_paid_amount in payment schedule table --- .../doctype/payment_entry/payment_entry.py | 42 +++++++++++++++++-- .../payment_schedule/payment_schedule.json | 22 +++++++++- .../payment_schedule/payment_schedule.py | 2 + .../accounts_receivable.py | 26 +++++++----- erpnext/controllers/accounts_controller.py | 3 ++ 5 files changed, 78 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index b4e53b03218..55387232ede 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -7,6 +7,7 @@ from functools import reduce import frappe from frappe import ValidationError, _, qb, scrub, throw +from frappe.model.meta import get_field_precision from frappe.query_builder import Tuple from frappe.query_builder.functions import Count from frappe.utils import cint, comma_or, flt, getdate, nowdate @@ -825,16 +826,39 @@ class PaymentEntry(AccountsController): outstanding = flt(invoice_paid_amount_map.get(key, {}).get("outstanding")) discounted_amt = flt(invoice_paid_amount_map.get(key, {}).get("discounted_amt")) + conversion_rate = frappe.db.get_value(key[2], {"name": key[1]}, "conversion_rate") + base_paid_amount_precision = get_field_precision( + frappe.get_meta("Payment Schedule").get_field("base_paid_amount") + ) + base_outstanding_precision = get_field_precision( + frappe.get_meta("Payment Schedule").get_field("base_outstanding") + ) + + base_paid_amount = flt( + (allocated_amount - discounted_amt) * conversion_rate, base_paid_amount_precision + ) + base_outstanding = flt(allocated_amount * conversion_rate, base_outstanding_precision) + if cancel: frappe.db.sql( """ UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` - %s, + base_paid_amount = `base_paid_amount` - %s, discounted_amount = `discounted_amount` - %s, - outstanding = `outstanding` + %s + outstanding = `outstanding` + %s, + base_outstanding = `base_outstanding` - %s WHERE parent = %s and payment_term = %s""", - (allocated_amount - discounted_amt, discounted_amt, allocated_amount, key[1], key[0]), + ( + allocated_amount - discounted_amt, + base_paid_amount, + discounted_amt, + allocated_amount, + base_outstanding, + key[1], + key[0], + ), ) else: if allocated_amount > outstanding: @@ -850,10 +874,20 @@ class PaymentEntry(AccountsController): UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` + %s, + base_paid_amount = `base_paid_amount` + %s, discounted_amount = `discounted_amount` + %s, - outstanding = `outstanding` - %s + outstanding = `outstanding` - %s, + base_outstanding = `base_outstanding` - %s WHERE parent = %s and payment_term = %s""", - (allocated_amount - discounted_amt, discounted_amt, allocated_amount, key[1], key[0]), + ( + allocated_amount - discounted_amt, + base_paid_amount, + discounted_amt, + allocated_amount, + base_outstanding, + key[1], + key[0], + ), ) def get_allocated_amount_in_transaction_currency( diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json index 6008a6f2d5e..b72281b6314 100644 --- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json +++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json @@ -24,7 +24,9 @@ "paid_amount", "discounted_amount", "column_break_3", - "base_payment_amount" + "base_payment_amount", + "base_outstanding", + "base_paid_amount" ], "fields": [ { @@ -155,18 +157,34 @@ "fieldtype": "Currency", "label": "Payment Amount (Company Currency)", "options": "Company:company:default_currency" + }, + { + "fieldname": "base_outstanding", + "fieldtype": "Currency", + "label": "Outstanding (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "depends_on": "base_paid_amount", + "fieldname": "base_paid_amount", + "fieldtype": "Currency", + "label": "Paid Amount (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-03-27 13:10:11.356171", + "modified": "2025-03-11 11:06:51.792982", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Schedule", "owner": "Administrator", "permissions": [], "quick_entry": 1, + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "DESC", "states": [], diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.py b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py index 8a292fd3aba..a3d1dbe5564 100644 --- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.py +++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py @@ -14,6 +14,8 @@ class PaymentSchedule(Document): if TYPE_CHECKING: from frappe.types import DF + base_outstanding: DF.Currency + base_paid_amount: DF.Currency base_payment_amount: DF.Currency description: DF.SmallText | None discount: DF.Float diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 39615aa14c4..eb174d80b09 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -529,7 +529,7 @@ class ReceivablePayableReport: select si.name, si.party_account_currency, si.currency, si.conversion_rate, si.total_advance, ps.due_date, ps.payment_term, ps.payment_amount, ps.base_payment_amount, - ps.description, ps.paid_amount, ps.discounted_amount + ps.description, ps.paid_amount, ps.base_paid_amount, ps.discounted_amount from `tab{row.voucher_type}` si, `tabPayment Schedule` ps where si.name = ps.parent and @@ -552,20 +552,24 @@ class ReceivablePayableReport: # Deduct that from paid amount pre allocation row.paid -= flt(payment_terms_details[0].total_advance) + company_currency = frappe.get_value("Company", self.filters.get("company"), "default_currency") + # If single payment terms, no need to split the row if len(payment_terms_details) == 1 and payment_terms_details[0].payment_term: - self.append_payment_term(row, payment_terms_details[0], original_row) + self.append_payment_term(row, payment_terms_details[0], original_row, company_currency) return for d in payment_terms_details: term = frappe._dict(original_row) - self.append_payment_term(row, d, term) + self.append_payment_term(row, d, term, company_currency) - def append_payment_term(self, row, d, term): - if d.currency == d.party_account_currency: + def append_payment_term(self, row, d, term, company_currency): + invoiced = d.base_payment_amount + paid_amount = d.base_paid_amount + + if company_currency == d.party_account_currency or self.filters.get("in_party_currency"): invoiced = d.payment_amount - else: - invoiced = d.base_payment_amount + paid_amount = d.paid_amount row.payment_terms.append( term.update( @@ -574,15 +578,15 @@ class ReceivablePayableReport: "invoiced": invoiced, "invoice_grand_total": row.invoiced, "payment_term": d.description or d.payment_term, - "paid": d.paid_amount + d.discounted_amount, + "paid": paid_amount + d.discounted_amount, "credit_note": 0.0, - "outstanding": invoiced - d.paid_amount - d.discounted_amount, + "outstanding": invoiced - paid_amount - d.discounted_amount, } ) ) - if d.paid_amount: - row["paid"] -= d.paid_amount + d.discounted_amount + if paid_amount: + row["paid"] -= paid_amount + d.discounted_amount def allocate_closing_to_term(self, row, term, key): if row[key]: diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 9956d36617b..b61ac3b1fc3 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -2343,6 +2343,9 @@ class AccountsController(TransactionBase): base_grand_total * flt(d.invoice_portion) / 100, d.precision("base_payment_amount") ) d.outstanding = d.payment_amount + d.base_outstanding = flt( + d.payment_amount * self.get("conversion_rate"), d.precision("base_outstanding") + ) elif not d.invoice_portion: d.base_payment_amount = flt( d.payment_amount * self.get("conversion_rate"), d.precision("base_payment_amount")