fix: refactor query in get_total_allocated_amount in bank_transaction

(cherry picked from commit 6b847cdb62)

# Conflicts:
#	erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
#	erpnext/accounts/doctype/bank_transaction/bank_transaction.py
This commit is contained in:
vishakhdesai
2024-12-19 12:27:06 +05:30
committed by Mergify
parent 07947eb3f4
commit cc0a478559
2 changed files with 38 additions and 12 deletions

View File

@@ -455,13 +455,22 @@ def get_linked_payments(
def subtract_allocations(gl_account, vouchers): def subtract_allocations(gl_account, vouchers):
"Look up & subtract any existing Bank Transaction allocations" "Look up & subtract any existing Bank Transaction allocations"
copied = [] copied = []
voucher_docs = [(voucher.get("doctype"), voucher.get("name")) for voucher in vouchers]
voucher_allocated_amounts = get_total_allocated_amount(voucher_docs)
for voucher in vouchers: for voucher in vouchers:
<<<<<<< HEAD
rows = get_total_allocated_amount(voucher[1], voucher[2]) rows = get_total_allocated_amount(voucher[1], voucher[2])
amount = None amount = None
for row in rows: for row in rows:
if row["gl_account"] == gl_account: if row["gl_account"] == gl_account:
amount = row["total"] amount = row["total"]
break break
=======
rows = voucher_allocated_amounts.get((voucher.get("doctype"), voucher.get("name")))
filtered_row = list(filter(lambda row: row.get("gl_account") == gl_account, rows))
>>>>>>> 6b847cdb62 (fix: refactor query in get_total_allocated_amount in bank_transaction)
if amount: if amount:
l = list(voucher) l = list(voucher)

View File

@@ -93,10 +93,20 @@ class BankTransaction(StatusUpdater):
- clear means: set the latest transaction date as clearance date - clear means: set the latest transaction date as clearance date
""" """
remaining_amount = self.unallocated_amount remaining_amount = self.unallocated_amount
<<<<<<< HEAD
=======
to_remove = []
payment_entry_docs = [(pe.payment_document, pe.payment_entry) for pe in self.payment_entries]
pe_bt_allocations = get_total_allocated_amount(payment_entry_docs)
>>>>>>> 6b847cdb62 (fix: refactor query in get_total_allocated_amount in bank_transaction)
for payment_entry in self.payment_entries: for payment_entry in self.payment_entries:
if payment_entry.allocated_amount == 0.0: if payment_entry.allocated_amount == 0.0:
unallocated_amount, should_clear, latest_transaction = get_clearance_details( unallocated_amount, should_clear, latest_transaction = get_clearance_details(
self, payment_entry self,
payment_entry,
pe_bt_allocations.get((payment_entry.payment_document, payment_entry.payment_entry))
or [],
) )
if 0.0 == unallocated_amount: if 0.0 == unallocated_amount:
@@ -182,7 +192,7 @@ def get_doctypes_for_bank_reconciliation():
return frappe.get_hooks("bank_reconciliation_doctypes") return frappe.get_hooks("bank_reconciliation_doctypes")
def get_clearance_details(transaction, payment_entry): def get_clearance_details(transaction, payment_entry, bt_allocations):
""" """
There should only be one bank gle for a voucher. There should only be one bank gle for a voucher.
Could be none for a Bank Transaction. Could be none for a Bank Transaction.
@@ -191,7 +201,6 @@ def get_clearance_details(transaction, payment_entry):
""" """
gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account") gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry) gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry)
bt_allocations = get_total_allocated_amount(payment_entry.payment_document, payment_entry.payment_entry)
unallocated_amount = min( unallocated_amount = min(
transaction.unallocated_amount, transaction.unallocated_amount,
@@ -247,44 +256,52 @@ def get_related_bank_gl_entries(doctype, docname):
return result return result
def get_total_allocated_amount(doctype, docname): def get_total_allocated_amount(docs):
""" """
Gets the sum of allocations for a voucher on each bank GL account Gets the sum of allocations for a voucher on each bank GL account
along with the latest bank transaction name & date along with the latest bank transaction name & date
NOTE: query may also include just saved vouchers/payments but with zero allocated_amount NOTE: query may also include just saved vouchers/payments but with zero allocated_amount
""" """
if not docs:
return {}
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql # nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
result = frappe.db.sql( result = frappe.db.sql(
""" """
SELECT total, latest_name, latest_date, gl_account FROM ( SELECT total, latest_name, latest_date, gl_account, payment_document, payment_entry FROM (
SELECT SELECT
ROW_NUMBER() OVER w AS rownum, ROW_NUMBER() OVER w AS rownum,
SUM(btp.allocated_amount) OVER(PARTITION BY ba.account) AS total, SUM(btp.allocated_amount) OVER(PARTITION BY ba.account, btp.payment_document, btp.payment_entry) AS total,
FIRST_VALUE(bt.name) OVER w AS latest_name, FIRST_VALUE(bt.name) OVER w AS latest_name,
FIRST_VALUE(bt.date) OVER w AS latest_date, FIRST_VALUE(bt.date) OVER w AS latest_date,
ba.account AS gl_account ba.account AS gl_account,
btp.payment_document,
btp.payment_entry
FROM FROM
`tabBank Transaction Payments` btp `tabBank Transaction Payments` btp
LEFT JOIN `tabBank Transaction` bt ON bt.name=btp.parent LEFT JOIN `tabBank Transaction` bt ON bt.name=btp.parent
LEFT JOIN `tabBank Account` ba ON ba.name=bt.bank_account LEFT JOIN `tabBank Account` ba ON ba.name=bt.bank_account
WHERE WHERE
btp.payment_document = %(doctype)s (btp.payment_document, btp.payment_entry) IN %(docs)s
AND btp.payment_entry = %(docname)s
AND bt.docstatus = 1 AND bt.docstatus = 1
WINDOW w AS (PARTITION BY ba.account ORDER BY bt.date desc) WINDOW w AS (PARTITION BY ba.account, btp.payment_document, btp.payment_entry ORDER BY bt.date DESC)
) temp ) temp
WHERE WHERE
rownum = 1 rownum = 1
""", """,
dict(doctype=doctype, docname=docname), dict(docs=docs),
as_dict=True, as_dict=True,
) )
payment_allocation_details = {}
for row in result: for row in result:
# Why is this *sometimes* a byte string? # Why is this *sometimes* a byte string?
if isinstance(row["latest_name"], bytes): if isinstance(row["latest_name"], bytes):
row["latest_name"] = row["latest_name"].decode() row["latest_name"] = row["latest_name"].decode()
row["latest_date"] = frappe.utils.getdate(row["latest_date"]) row["latest_date"] = frappe.utils.getdate(row["latest_date"])
return result payment_allocation_details.setdefault((row["payment_document"], row["payment_entry"]), []).append(row)
return payment_allocation_details
def get_paid_amount(payment_entry, currency, gl_bank_account): def get_paid_amount(payment_entry, currency, gl_bank_account):