From c705a93776f765722de21856d0dce2687b041374 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 18 May 2026 10:26:29 +0530 Subject: [PATCH] fix: remove sql procedure method from AR report (cherry picked from commit 63a7142b9b9ffaa3c469ff324f0cc0a53a92fcd4) # Conflicts: # erpnext/accounts/doctype/accounts_settings/accounts_settings.json # erpnext/accounts/doctype/accounts_settings/accounts_settings.py # erpnext/accounts/report/accounts_receivable/accounts_receivable.py # erpnext/patches.txt --- .../accounts_settings/accounts_settings.js | 10 - .../accounts_settings/accounts_settings.json | 14 +- .../accounts_settings/accounts_settings.py | 9 +- .../accounts_receivable.py | 194 ------------------ erpnext/patches.txt | 1 + ...clear_procedures_from_receivable_report.py | 12 ++ 6 files changed, 17 insertions(+), 223 deletions(-) create mode 100644 erpnext/patches/v16_0/clear_procedures_from_receivable_report.py diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js index 931e05a716b..1e4d0bbca7e 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js @@ -30,16 +30,6 @@ frappe.ui.form.on("Accounts Settings", { add_taxes_from_item_tax_template(frm) { toggle_tax_settings(frm, "add_taxes_from_item_tax_template"); }, - - drop_ar_procedures: function (frm) { - frm.call({ - doc: frm.doc, - method: "drop_ar_sql_procedures", - callback: function (r) { - frappe.show_alert(__("Procedures dropped"), 5); - }, - }); - }, }); function toggle_tax_settings(frm, field_name) { diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 25e62e20f3e..18a0a86fd52 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -95,7 +95,6 @@ "receivable_payable_fetch_method", "default_ageing_range", "column_break_ntmi", - "drop_ar_procedures", "legacy_section", "ignore_is_opening_check_for_reporting", "payment_request_settings", @@ -561,7 +560,7 @@ "fieldname": "receivable_payable_fetch_method", "fieldtype": "Select", "label": "Data Fetch Method", - "options": "Buffered Cursor\nUnBuffered Cursor\nRaw SQL" + "options": "Buffered Cursor\nUnBuffered Cursor" }, { "fieldname": "accounts_receivable_payable_tuning_section", @@ -623,13 +622,6 @@ "fieldname": "column_break_ntmi", "fieldtype": "Column Break" }, - { - "depends_on": "eval:doc.receivable_payable_fetch_method == \"Raw SQL\"", - "description": "Drops existing SQL Procedures and Function setup by Accounts Receivable report", - "fieldname": "drop_ar_procedures", - "fieldtype": "Button", - "label": "Drop Procedures" - }, { "default": "0", "fieldname": "fetch_valuation_rate_for_internal_transaction", @@ -671,7 +663,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2026-03-06 14:49:11.467716", + "modified": "2026-05-18 12:16:33.679345", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", @@ -701,4 +693,4 @@ "sort_order": "ASC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index 0f096155949..5cd4955cdd7 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -60,7 +60,7 @@ class AccountsSettings(Document): merge_similar_account_heads: DF.Check over_billing_allowance: DF.Currency post_change_gl_entries: DF.Check - receivable_payable_fetch_method: DF.Literal["Buffered Cursor", "UnBuffered Cursor", "Raw SQL"] + receivable_payable_fetch_method: DF.Literal["Buffered Cursor", "UnBuffered Cursor"] receivable_payable_remarks_length: DF.Int reconciliation_queue_size: DF.Int role_allowed_to_over_bill: DF.Link | None @@ -170,10 +170,3 @@ class AccountsSettings(Document): ), title=_("Auto Tax Settings Error"), ) - - @frappe.whitelist() - def drop_ar_sql_procedures(self): - from erpnext.accounts.report.accounts_receivable.accounts_receivable import InitSQLProceduresForAR - - frappe.db.sql(f"drop procedure if exists {InitSQLProceduresForAR.init_procedure_name}") - frappe.db.sql(f"drop procedure if exists {InitSQLProceduresForAR.allocate_procedure_name}") diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index da05fce3d3e..d28f886a4fd 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -129,8 +129,6 @@ class ReceivablePayableReport: self.fetch_ple_in_buffered_cursor() elif self.ple_fetch_method == "UnBuffered Cursor": self.fetch_ple_in_unbuffered_cursor() - elif self.ple_fetch_method == "Raw SQL": - self.fetch_ple_in_sql_procedures() # Build delivery note map against all sales invoices self.build_delivery_note_map() @@ -321,81 +319,6 @@ class ReceivablePayableReport: row.paid -= amount row.paid_in_account_currency -= amount_in_account_currency - def fetch_ple_in_sql_procedures(self): - self.proc = InitSQLProceduresForAR() - - build_balance = f""" - begin not atomic - declare done boolean default false; - declare rec1 row type of `{self.proc._row_def_table_name}`; - declare ple cursor for {self.ple_query.get_sql()}; - declare continue handler for not found set done = true; - - open ple; - fetch ple into rec1; - while not done do - call {self.proc.init_procedure_name}(rec1); - fetch ple into rec1; - end while; - close ple; - - set done = false; - open ple; - fetch ple into rec1; - while not done do - call {self.proc.allocate_procedure_name}(rec1); - fetch ple into rec1; - end while; - close ple; - end; - """ - frappe.db.sql(build_balance) - - balances = frappe.db.sql( - f"""select - name, - voucher_type, - voucher_no, - party, - party_account `account`, - posting_date, - account_currency, - cost_center, - project, - sum(invoiced) `invoiced`, - sum(paid) `paid`, - sum(credit_note) `credit_note`, - sum(invoiced) - sum(paid) - sum(credit_note) `outstanding`, - sum(invoiced_in_account_currency) `invoiced_in_account_currency`, - sum(paid_in_account_currency) `paid_in_account_currency`, - sum(credit_note_in_account_currency) `credit_note_in_account_currency`, - sum(invoiced_in_account_currency) - sum(paid_in_account_currency) - sum(credit_note_in_account_currency) `outstanding_in_account_currency` - from `{self.proc._voucher_balance_name}` group by name order by posting_date;""", - as_dict=True, - ) - for x in balances: - if self.filters.get("ignore_accounts"): - key = (x.voucher_type, x.voucher_no, x.party) - else: - key = (x.account, x.voucher_type, x.voucher_no, x.party) - - _d = self.build_voucher_dict(x) - for field in [ - "invoiced", - "paid", - "credit_note", - "outstanding", - "invoiced_in_account_currency", - "paid_in_account_currency", - "credit_note_in_account_currency", - "outstanding_in_account_currency", - "cost_center", - "project", - ]: - _d[field] = x.get(field) - - self.voucher_balance[key] = _d - def update_sub_total_row(self, row, party): total_row = self.total_row_map.get(party) @@ -1390,120 +1313,3 @@ def get_party_group_with_children(party, party_groups): frappe.throw(_("{0}: {1} does not exist").format(group_dtype, d)) return list(set(all_party_groups)) - - -class InitSQLProceduresForAR: - """ - Initialize SQL Procedures, Functions and Temporary tables to build Receivable / Payable report - """ - - _varchar_type = get_definition("Data") - _currency_type = get_definition("Currency") - # Temporary Tables - _voucher_balance_name = "_ar_voucher_balance" - _voucher_balance_definition = f""" - create temporary table `{_voucher_balance_name}`( - name {_varchar_type}, - voucher_type {_varchar_type}, - voucher_no {_varchar_type}, - party {_varchar_type}, - party_account {_varchar_type}, - posting_date date, - account_currency {_varchar_type}, - cost_center {_varchar_type}, - project {_varchar_type}, - invoiced {_currency_type}, - paid {_currency_type}, - credit_note {_currency_type}, - invoiced_in_account_currency {_currency_type}, - paid_in_account_currency {_currency_type}, - credit_note_in_account_currency {_currency_type}) engine=memory; - """ - - _row_def_table_name = "_ar_ple_row" - _row_def_table_definition = f""" - create temporary table `{_row_def_table_name}`( - name {_varchar_type}, - account {_varchar_type}, - voucher_type {_varchar_type}, - voucher_no {_varchar_type}, - against_voucher_type {_varchar_type}, - against_voucher_no {_varchar_type}, - party_type {_varchar_type}, - cost_center {_varchar_type}, - project {_varchar_type}, - party {_varchar_type}, - posting_date date, - due_date date, - account_currency {_varchar_type}, - amount {_currency_type}, - amount_in_account_currency {_currency_type}) engine=memory; - """ - - # Procedures - init_procedure_name = "ar_init_tmp_table" - init_procedure_sql = f""" - create procedure ar_init_tmp_table(in ple row type of `{_row_def_table_name}`) - begin - if not exists (select name from `{_voucher_balance_name}` where name = sha1(concat_ws(',', ple.account, ple.against_voucher_type, ple.against_voucher_no, ple.party))) - then - insert into `{_voucher_balance_name}` values (sha1(concat_ws(',', ple.account, ple.against_voucher_type, ple.against_voucher_no, ple.party)), ple.voucher_type, ple.voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency, ple.cost_center, 0, 0, 0, 0, 0, 0); - end if; - end; - """ - - allocate_procedure_name = "ar_allocate_to_tmp_table" - allocate_procedure_sql = f""" - create procedure ar_allocate_to_tmp_table(in ple row type of `{_row_def_table_name}`) - begin - declare invoiced {_currency_type} default 0; - declare invoiced_in_account_currency {_currency_type} default 0; - declare paid {_currency_type} default 0; - declare paid_in_account_currency {_currency_type} default 0; - declare credit_note {_currency_type} default 0; - declare credit_note_in_account_currency {_currency_type} default 0; - - - if ple.amount > 0 then - if (ple.voucher_type in ("Journal Entry", "Payment Entry") and (ple.voucher_no != ple.against_voucher_no)) then - set paid = -1 * ple.amount; - set paid_in_account_currency = -1 * ple.amount_in_account_currency; - else - set invoiced = ple.amount; - set invoiced_in_account_currency = ple.amount_in_account_currency; - end if; - else - - if ple.voucher_type in ("Sales Invoice", "Purchase Invoice") then - if (ple.voucher_no = ple.against_voucher_no) then - set paid = -1 * ple.amount; - set paid_in_account_currency = -1 * ple.amount_in_account_currency; - else - set credit_note = -1 * ple.amount; - set credit_note_in_account_currency = -1 * ple.amount_in_account_currency; - end if; - else - set paid = -1 * ple.amount; - set paid_in_account_currency = -1 * ple.amount_in_account_currency; - end if; - - end if; - - insert into `{_voucher_balance_name}` values (sha1(concat_ws(',', ple.account, ple.voucher_type, ple.voucher_no, ple.party)), ple.against_voucher_type, ple.against_voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency,'', invoiced, paid, 0, invoiced_in_account_currency, paid_in_account_currency, 0); - end; - """ - - def __init__(self): - existing_procedures = frappe.db.get_routines() - - if self.init_procedure_name not in existing_procedures: - frappe.db.sql(self.init_procedure_sql) - - if self.allocate_procedure_name not in existing_procedures: - frappe.db.sql(self.allocate_procedure_sql) - - frappe.db.sql(f"drop table if exists `{self._voucher_balance_name}`") - frappe.db.sql(self._voucher_balance_definition) - - frappe.db.sql(f"drop table if exists `{self._row_def_table_name}`") - frappe.db.sql(self._row_def_table_definition) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 2dcee807fec..acb500e940f 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -433,3 +433,4 @@ erpnext.patches.v15_0.replace_http_with_https_in_sales_partner erpnext.patches.v16_0.add_portal_redirects erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po erpnext.patches.v16_0.depends_on_inv_dimensions +erpnext.patches.v16_0.clear_procedures_from_receivable_report diff --git a/erpnext/patches/v16_0/clear_procedures_from_receivable_report.py b/erpnext/patches/v16_0/clear_procedures_from_receivable_report.py new file mode 100644 index 00000000000..5eaf0f14fc8 --- /dev/null +++ b/erpnext/patches/v16_0/clear_procedures_from_receivable_report.py @@ -0,0 +1,12 @@ +import frappe + + +def execute(): + if frappe.db.get_single_value("Accounts Settings", "receivable_payable_fetch_method") == "Raw SQL": + frappe.db.set_single_value( + "Accounts Settings", "receivable_payable_fetch_method", "UnBuffered Cursor" + ) + + frappe.db.sql("drop function if exists ar_genkey") + frappe.db.sql("drop procedure if exists ar_init_tmp_table") + frappe.db.sql("drop procedure if exists ar_allocate_to_tmp_table")