From 4bf3e310e1fe32b26b573cbc0fc97ec66992e126 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 31 Jan 2023 09:37:45 +0530 Subject: [PATCH] perf: Timeout while doing payment reconciliation (v13) (#33818) perf: Timeout while doing payment reconciliation --- .../doctype/payment_entry/payment_entry.py | 1 + .../payment_reconciliation.py | 2 +- erpnext/accounts/utils.py | 116 ++++++++++-------- 3 files changed, 66 insertions(+), 53 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 70a5f9e526c..f4367cdafd6 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1255,6 +1255,7 @@ def get_outstanding_reference_documents(args): args.get("party_type"), args.get("party"), args.get("party_account"), + args.get("company"), filters=args, condition=condition, ) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 1e75471c848..1e99e4d791c 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -211,7 +211,7 @@ class PaymentReconciliation(Document): condition += " and cost_center = '{0}' ".format(self.cost_center) non_reconciled_invoices = get_outstanding_invoices( - self.party_type, self.party, self.receivable_payable_account, condition=condition + self.party_type, self.party, self.receivable_payable_account, self.company, condition=condition ) if self.invoice_limit: diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index b0b217684ea..faacc913a41 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -840,7 +840,7 @@ def remove_return_pos_invoices(party_type, party, invoice_list): return invoice_list -def get_outstanding_invoices(party_type, party, account, condition=None, filters=None): +def get_outstanding_invoices(party_type, party, account, company, condition=None, filters=None): outstanding_invoices = [] precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2 @@ -892,61 +892,73 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters invoice_list = remove_return_pos_invoices(party_type, party, invoice_list) - payment_entries = frappe.db.sql( - """ - select against_voucher_type, against_voucher, - ifnull(sum({payment_dr_or_cr}), 0) as payment_amount - from `tabGL Entry` - where party_type = %(party_type)s and party = %(party)s - and account = %(account)s - and {payment_dr_or_cr} > 0 - and against_voucher is not null and against_voucher != '' - and is_cancelled=0 - group by against_voucher_type, against_voucher - """.format( - payment_dr_or_cr=payment_dr_or_cr - ), - {"party_type": party_type, "party": party, "account": account}, - as_dict=True, - ) + if invoice_list: + invoices = [d.voucher_no for d in invoice_list] + payment_entries = frappe.db.sql( + """ + select against_voucher_type, against_voucher, + ifnull(sum({payment_dr_or_cr}), 0) as payment_amount + from `tabGL Entry` + where + company = %(company)s + and party_type = %(party_type)s and party = %(party)s + and account = %(account)s + and {payment_dr_or_cr} > 0 + and ifnull(against_voucher, '') != '' + and is_cancelled=0 + and against_voucher in %(invoices)s + group by against_voucher_type, against_voucher + """.format( + payment_dr_or_cr=payment_dr_or_cr, + ), + { + "company": company, + "party_type": party_type, + "party": party, + "account": account, + "invoices": invoices, + }, + as_dict=True, + ) - pe_map = frappe._dict() - for d in payment_entries: - pe_map.setdefault((d.against_voucher_type, d.against_voucher), d.payment_amount) + pe_map = frappe._dict() + for d in payment_entries: + pe_map.setdefault((d.against_voucher_type, d.against_voucher), d.payment_amount) - for d in invoice_list: - payment_amount = pe_map.get((d.voucher_type, d.voucher_no), 0) - outstanding_amount = flt(d.invoice_amount - payment_amount, precision) - if outstanding_amount > 0.5 / (10**precision): - if ( - filters - and filters.get("outstanding_amt_greater_than") - and not ( - outstanding_amount >= filters.get("outstanding_amt_greater_than") - and outstanding_amount <= filters.get("outstanding_amt_less_than") - ) - ): - continue - - if not d.voucher_type == "Purchase Invoice" or d.voucher_no not in held_invoices: - outstanding_invoices.append( - frappe._dict( - { - "voucher_no": d.voucher_no, - "voucher_type": d.voucher_type, - "posting_date": d.posting_date, - "invoice_amount": flt(d.invoice_amount), - "payment_amount": payment_amount, - "outstanding_amount": outstanding_amount, - "due_date": d.due_date, - "currency": d.currency, - } + for d in invoice_list: + payment_amount = pe_map.get((d.voucher_type, d.voucher_no), 0) + outstanding_amount = flt(d.invoice_amount - payment_amount, precision) + if outstanding_amount > 0.5 / (10**precision): + if ( + filters + and filters.get("outstanding_amt_greater_than") + and not ( + outstanding_amount >= filters.get("outstanding_amt_greater_than") + and outstanding_amount <= filters.get("outstanding_amt_less_than") ) - ) + ): + continue + + if not d.voucher_type == "Purchase Invoice" or d.voucher_no not in held_invoices: + outstanding_invoices.append( + frappe._dict( + { + "voucher_no": d.voucher_no, + "voucher_type": d.voucher_type, + "posting_date": d.posting_date, + "invoice_amount": flt(d.invoice_amount), + "payment_amount": payment_amount, + "outstanding_amount": outstanding_amount, + "due_date": d.due_date, + "currency": d.currency, + } + ) + ) + + outstanding_invoices = sorted( + outstanding_invoices, key=lambda k: k["due_date"] or getdate(nowdate()) + ) - outstanding_invoices = sorted( - outstanding_invoices, key=lambda k: k["due_date"] or getdate(nowdate()) - ) return outstanding_invoices