From cc0a4785590b86852dbbcc89b1fc1d953b44b406 Mon Sep 17 00:00:00 2001 From: vishakhdesai Date: Thu, 19 Dec 2024 12:27:06 +0530 Subject: [PATCH 1/3] fix: refactor query in get_total_allocated_amount in bank_transaction (cherry picked from commit 6b847cdb623322a64096337dcbe86cdbdc60bb6b) # Conflicts: # erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py # erpnext/accounts/doctype/bank_transaction/bank_transaction.py --- .../bank_reconciliation_tool.py | 9 ++++ .../bank_transaction/bank_transaction.py | 41 +++++++++++++------ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 2987bac677c..2a65792cc15 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -455,13 +455,22 @@ def get_linked_payments( def subtract_allocations(gl_account, vouchers): "Look up & subtract any existing Bank Transaction allocations" 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: +<<<<<<< HEAD rows = get_total_allocated_amount(voucher[1], voucher[2]) amount = None for row in rows: if row["gl_account"] == gl_account: amount = row["total"] 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: l = list(voucher) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 89565e9908b..b67478a7f3d 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -93,10 +93,20 @@ class BankTransaction(StatusUpdater): - clear means: set the latest transaction date as clearance date """ 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: if payment_entry.allocated_amount == 0.0: 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: @@ -182,7 +192,7 @@ def get_doctypes_for_bank_reconciliation(): 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. 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") 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( transaction.unallocated_amount, @@ -247,44 +256,52 @@ def get_related_bank_gl_entries(doctype, docname): 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 along with the latest bank transaction name & date 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 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 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.date) OVER w AS latest_date, - ba.account AS gl_account + ba.account AS gl_account, + btp.payment_document, + btp.payment_entry FROM `tabBank Transaction Payments` btp LEFT JOIN `tabBank Transaction` bt ON bt.name=btp.parent LEFT JOIN `tabBank Account` ba ON ba.name=bt.bank_account WHERE - btp.payment_document = %(doctype)s - AND btp.payment_entry = %(docname)s + (btp.payment_document, btp.payment_entry) IN %(docs)s 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 WHERE rownum = 1 """, - dict(doctype=doctype, docname=docname), + dict(docs=docs), as_dict=True, ) + + payment_allocation_details = {} for row in result: # Why is this *sometimes* a byte string? if isinstance(row["latest_name"], bytes): row["latest_name"] = row["latest_name"].decode() 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): From 498abf7c83e77ad4bde13b81c09a8a86e5c55f8d Mon Sep 17 00:00:00 2001 From: vishakhdesai Date: Thu, 19 Dec 2024 12:55:11 +0530 Subject: [PATCH 2/3] fix: failing tests fixed (cherry picked from commit 2ce07865d36d74ef058d613dfe4714ddfd6b58e6) # Conflicts: # erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py --- .../bank_reconciliation_tool/bank_reconciliation_tool.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 2a65792cc15..55ea4414f30 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -460,6 +460,7 @@ def subtract_allocations(gl_account, vouchers): voucher_allocated_amounts = get_total_allocated_amount(voucher_docs) for voucher in vouchers: +<<<<<<< HEAD <<<<<<< HEAD rows = get_total_allocated_amount(voucher[1], voucher[2]) amount = None @@ -469,6 +470,9 @@ def subtract_allocations(gl_account, vouchers): break ======= rows = voucher_allocated_amounts.get((voucher.get("doctype"), voucher.get("name"))) +======= + rows = voucher_allocated_amounts.get((voucher.get("doctype"), voucher.get("name"))) or [] +>>>>>>> 2ce07865d3 (fix: failing tests fixed) 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) From 443a0b81f9abad0bc7425bfe647d3feb14541a77 Mon Sep 17 00:00:00 2001 From: vishakhdesai Date: Mon, 30 Dec 2024 12:27:14 +0530 Subject: [PATCH 3/3] fix: resolve conflicts --- .../bank_reconciliation_tool.py | 13 ++----------- .../doctype/bank_transaction/bank_transaction.py | 4 ---- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 55ea4414f30..316fc8564c1 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -456,25 +456,16 @@ def subtract_allocations(gl_account, vouchers): "Look up & subtract any existing Bank Transaction allocations" copied = [] - voucher_docs = [(voucher.get("doctype"), voucher.get("name")) for voucher in vouchers] + voucher_docs = [(voucher[1], voucher[2]) for voucher in vouchers] voucher_allocated_amounts = get_total_allocated_amount(voucher_docs) for voucher in vouchers: -<<<<<<< HEAD -<<<<<<< HEAD - rows = get_total_allocated_amount(voucher[1], voucher[2]) + rows = voucher_allocated_amounts.get((voucher[1], voucher[2])) or [] amount = None for row in rows: if row["gl_account"] == gl_account: amount = row["total"] break -======= - rows = voucher_allocated_amounts.get((voucher.get("doctype"), voucher.get("name"))) -======= - rows = voucher_allocated_amounts.get((voucher.get("doctype"), voucher.get("name"))) or [] ->>>>>>> 2ce07865d3 (fix: failing tests fixed) - 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: l = list(voucher) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index b67478a7f3d..6c1beb16d5d 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -93,13 +93,9 @@ class BankTransaction(StatusUpdater): - clear means: set the latest transaction date as clearance date """ 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: if payment_entry.allocated_amount == 0.0: unallocated_amount, should_clear, latest_transaction = get_clearance_details(