From 006a8c71fd02969511f6124f5558306d97583502 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 4 Jun 2025 14:47:01 +0530 Subject: [PATCH] refactor: utility to drop existing procedures and include cost center (cherry picked from commit da32bb5f514783a9b8e350375d958ede39ca6b72) # Conflicts: # erpnext/accounts/doctype/accounts_settings/accounts_settings.js # erpnext/accounts/doctype/accounts_settings/accounts_settings.json # erpnext/accounts/doctype/accounts_settings/accounts_settings.py --- .../accounts_settings/accounts_settings.js | 40 ++++++++++ .../accounts_settings/accounts_settings.json | 80 +++++++++++++++++++ .../accounts_settings/accounts_settings.py | 35 ++++++++ .../accounts_receivable.py | 23 +++--- 4 files changed, 169 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js index 5b9a52e8f8b..74c623c8acb 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js @@ -3,4 +3,44 @@ frappe.ui.form.on("Accounts Settings", { refresh: function (frm) {}, +<<<<<<< HEAD +======= + enable_immutable_ledger: function (frm) { + if (!frm.doc.enable_immutable_ledger) { + return; + } + + let msg = __("Enabling this will change the way how cancelled transactions are handled."); + msg += " "; + msg += __("Please enable only if the understand the effects of enabling this."); + msg += "
"; + msg += __("Do you still want to enable immutable ledger?"); + + frappe.confirm( + msg, + () => {}, + () => { + frm.set_value("enable_immutable_ledger", 0); + } + ); + }, + + add_taxes_from_taxes_and_charges_template(frm) { + toggle_tax_settings(frm, "add_taxes_from_taxes_and_charges_template"); + }, + + 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); + }, + }); + }, +>>>>>>> da32bb5f51 (refactor: utility to drop existing procedures and include cost center) }); diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 5c20f47749f..a2b75df6b5e 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -77,6 +77,8 @@ "receivable_payable_remarks_length", "accounts_receivable_payable_tuning_section", "receivable_payable_fetch_method", + "column_break_ntmi", + "drop_ar_procedures", "legacy_section", "ignore_is_opening_check_for_reporting" ], @@ -499,6 +501,84 @@ "fieldname": "legacy_section", "fieldtype": "Section Break", "label": "Legacy Fields" +<<<<<<< HEAD +======= + }, + { + "default": "0", + "fieldname": "maintain_same_internal_transaction_rate", + "fieldtype": "Check", + "label": "Maintain Same Rate Throughout Internal Transaction" + }, + { + "default": "Stop", + "depends_on": "maintain_same_internal_transaction_rate", + "fieldname": "maintain_same_rate_action", + "fieldtype": "Select", + "label": "Action if Same Rate is Not Maintained Throughout Internal Transaction", + "mandatory_depends_on": "maintain_same_internal_transaction_rate", + "options": "Stop\nWarn" + }, + { + "depends_on": "eval: doc.maintain_same_internal_transaction_rate && doc.maintain_same_rate_action == 'Stop'", + "fieldname": "role_to_override_stop_action", + "fieldtype": "Link", + "label": "Role Allowed to Override Stop Action", + "options": "Role" + }, + { + "fieldname": "budget_settings", + "fieldtype": "Tab Break", + "label": "Budget" + }, + { + "default": "1", + "fieldname": "use_new_budget_controller", + "fieldtype": "Check", + "label": "Use New Budget Controller" + }, + { + "default": "1", + "description": "If enabled, user will be alerted before resetting posting date to current date in relevant transactions", + "fieldname": "confirm_before_resetting_posting_date", + "fieldtype": "Check", + "label": "Confirm before resetting posting date" + }, + { + "fieldname": "item_price_settings_section", + "fieldtype": "Section Break", + "label": "Item Price Settings" + }, + { + "fieldname": "column_break_feyo", + "fieldtype": "Column Break" + }, + { + "default": "0", + "description": "System will do an implicit conversion using the pegged currency.
\nEx: Instead of AED -> INR, system will do AED -> USD -> INR using the pegged exchange rate of AED against USD.", + "documentation_url": "/app/pegged-currencies/Pegged Currencies", + "fieldname": "allow_pegged_currencies_exchange_rates", + "fieldtype": "Check", + "label": "Allow Implicit Pegged Currency Conversion" + }, + { + "default": "0", + "description": "If no taxes are set, and Taxes and Charges Template is selected, the system will automatically apply the taxes from the chosen template.", + "fieldname": "add_taxes_from_taxes_and_charges_template", + "fieldtype": "Check", + "label": "Automatically Add Taxes from Taxes and Charges Template" + }, + { + "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" +>>>>>>> da32bb5f51 (refactor: utility to drop existing procedures and include cost center) } ], "icon": "icon-cog", diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index 1244e19c96d..abfa0abc92f 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -129,3 +129,38 @@ class AccountsSettings(Document): def validate_pending_reposts(self): if self.acc_frozen_upto: check_pending_reposting(self.acc_frozen_upto) +<<<<<<< HEAD +======= + + def validate_and_sync_auto_reconcile_config(self): + if self.has_value_changed("auto_reconciliation_job_trigger"): + if ( + cint(self.auto_reconciliation_job_trigger) > 0 + and cint(self.auto_reconciliation_job_trigger) < 60 + ): + sync_auto_reconcile_config(self.auto_reconciliation_job_trigger) + else: + frappe.throw(_("Cron Interval should be between 1 and 59 Min")) + + if self.has_value_changed("reconciliation_queue_size"): + if cint(self.reconciliation_queue_size) < 5 or cint(self.reconciliation_queue_size) > 100: + frappe.throw(_("Queue Size should be between 5 and 100")) + + def validate_auto_tax_settings(self): + if self.add_taxes_from_item_tax_template and self.add_taxes_from_taxes_and_charges_template: + frappe.throw( + _("You cannot enable both the settings '{0}' and '{1}'.").format( + frappe.bold(_(self.meta.get_label("add_taxes_from_item_tax_template"))), + frappe.bold(_(self.meta.get_label("add_taxes_from_taxes_and_charges_template"))), + ), + 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 function if exists {InitSQLProceduresForAR.genkey_function_name}") + frappe.db.sql(f"drop procedure if exists {InitSQLProceduresForAR.init_procedure_name}") + frappe.db.sql(f"drop procedure if exists {InitSQLProceduresForAR.allocate_procedure_name}") +>>>>>>> da32bb5f51 (refactor: utility to drop existing procedures and include cost center) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 99608e58d25..b8f88f4a4d8 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -351,6 +351,7 @@ class ReceivablePayableReport: party_account `account`, posting_date, account_currency, + cost_center, sum(invoiced) `invoiced`, sum(paid) `paid`, sum(credit_note) `credit_note`, @@ -378,6 +379,7 @@ class ReceivablePayableReport: "paid_in_account_currency", "credit_note_in_account_currency", "outstanding_in_account_currency", + "cost_center", ]: _d[field] = x.get(field) @@ -1333,14 +1335,13 @@ class InitSQLProceduresForAR: party_account varchar(140), posting_date date, account_currency varchar(140), + cost_center varchar(140), invoiced decimal(21,9), paid decimal(21,9), credit_note decimal(21,9), - outstanding decimal(21,9), invoiced_in_account_currency decimal(21,9), paid_in_account_currency decimal(21,9), - credit_note_in_account_currency decimal(21,9), - outstanding_in_account_currency decimal(21,9)) engine=memory; + credit_note_in_account_currency decimal(21,9)) engine=memory; """ _row_def_table_name = "_ple_row" _row_def_table_definition = f""" @@ -1381,7 +1382,7 @@ class InitSQLProceduresForAR: begin if not exists (select name from `{_voucher_balance_name}` where name = genkey(ple, false)) then - insert into `{_voucher_balance_name}` values (genkey(ple, false), ple.voucher_type, ple.voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency, 0, 0, 0, 0, 0, 0, 0, 0); + insert into `{_voucher_balance_name}` values (genkey(ple, false), 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; """ @@ -1423,17 +1424,21 @@ class InitSQLProceduresForAR: end if; - insert into `{_voucher_balance_name}` values (`{genkey_function_name}`(ple, true), ple.against_voucher_type, ple.against_voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency, invoiced, paid, 0, 0, invoiced_in_account_currency, paid_in_account_currency, 0, 0); + insert into `{_voucher_balance_name}` values (`{genkey_function_name}`(ple, true), 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.sql( + def get_existing_procedures(self): + procedures = frappe.db.sql( f"select routine_name from information_schema.routines where routine_type in ('FUNCTION','PROCEDURE') and routine_schema='{frappe.conf.db_name}';" ) - if existing_procedures: + if procedures: # normalize - existing_procedures = [x[0] for x in existing_procedures] + procedures = [x[0] for x in procedures] + return procedures + + def __init__(self): + existing_procedures = self.get_existing_procedures() if self.genkey_function_name not in existing_procedures: frappe.db.sql(self.genkey_function_sql)