perf: optimize account balance data fetching for Chart Of Accounts

This commit is contained in:
Shllokkk
2026-03-09 20:09:03 +05:30
committed by GitHub
parent 5ca8641488
commit 2e844a58fb
2 changed files with 118 additions and 51 deletions

View File

@@ -52,60 +52,55 @@ frappe.treeview_settings["Account"] = {
],
root_label: "Accounts",
get_tree_nodes: "erpnext.accounts.utils.get_children",
on_get_node: function (nodes, deep = false) {
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
on_node_render: function (node, deep) {
const render_balances = () => {
for (let account of cur_tree.account_balance_data) {
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
let accounts = [];
if (deep) {
// in case of `get_all_nodes`
accounts = nodes.reduce((acc, node) => [...acc, ...node.data], []);
} else {
accounts = nodes;
}
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? __("Dr") : __("Cr");
const format = (value, currency) => format_currency(Math.abs(value), currency);
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if (value) {
const get_balances = frappe.call({
method: "erpnext.accounts.utils.get_account_balances",
args: {
accounts: accounts,
company: cur_tree.args.company,
include_default_fb_balances: true,
},
});
get_balances.then((r) => {
if (!r.message || r.message.length == 0) return;
for (let account of r.message) {
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? __("Dr") : __("Cr");
const format = (value, currency) => format_currency(Math.abs(value), currency);
if (account.balance !== undefined) {
node.parent && node.parent.find(".balance-area").remove();
$(
'<span class="balance-area pull-right">' +
(account.balance_in_account_currency
? format(
account.balance_in_account_currency,
account.account_currency
) + " / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
}
}
});
if (account.balance !== undefined) {
node.parent && node.parent.find(".balance-area").remove();
$(
'<span class="balance-area pull-right">' +
(account.account_currency != account.company_currency
? format(account.balance_in_account_currency, account.account_currency) +
" / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
}
}
});
};
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
if (!cur_tree.account_balance_data) {
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if (value) {
frappe.call({
method: "erpnext.accounts.utils.get_account_balances_coa",
args: {
company: cur_tree.args.company,
include_default_fb_balances: true,
},
callback: function (r) {
if (!r.message || r.message.length === 0) return;
cur_tree.account_balance_data = r.message || [];
render_balances();
},
});
}
});
} else {
render_balances();
}
},
add_tree_node: "erpnext.accounts.utils.add_ac",
menu_items: [

View File

@@ -1414,6 +1414,78 @@ def get_account_balances(
return accounts
@frappe.whitelist()
def get_account_balances_coa(company: str, include_default_fb_balances: bool = False):
company_currency = frappe.get_cached_value("Company", company, "default_currency")
Account = DocType("Account")
account_list = (
frappe.qb.from_(Account)
.select(Account.name, Account.parent_account, Account.account_currency)
.where(Account.company == company)
.orderby(Account.lft)
.run(as_dict=True)
)
account_balances_cc = {account.get("name"): 0 for account in account_list}
account_balances_ac = {account.get("name"): 0 for account in account_list}
GLEntry = DocType("GL Entry")
precision = get_currency_precision()
get_ledger_balances_query = (
frappe.qb.from_(GLEntry)
.select(
GLEntry.account,
(Sum(Round(GLEntry.debit, precision)) - Sum(Round(GLEntry.credit, precision))).as_("balance"),
(
Sum(Round(GLEntry.debit_in_account_currency, precision))
- Sum(Round(GLEntry.credit_in_account_currency, precision))
).as_("balance_in_account_currency"),
)
.groupby(GLEntry.account)
)
condition_list = [GLEntry.company == company, GLEntry.is_cancelled == 0]
default_finance_book = None
if include_default_fb_balances:
default_finance_book = frappe.get_cached_value("Company", company, "default_finance_book")
if default_finance_book:
condition_list.append(
(GLEntry.finance_book == default_finance_book) | (GLEntry.finance_book.isnull())
)
for condition in condition_list:
get_ledger_balances_query = get_ledger_balances_query.where(condition)
ledger_balances = get_ledger_balances_query.run(as_dict=True)
for ledger_entry in ledger_balances:
account_balances_cc[ledger_entry.get("account")] = ledger_entry.get("balance")
account_balances_ac[ledger_entry.get("account")] = ledger_entry.get("balance_in_account_currency")
for account in reversed(account_list):
parent = account.get("parent_account")
if parent:
account_balances_cc[parent] += account_balances_cc.get(account.get("name"))
accounts_data = [
{
"value": account.get("name"),
"company_currency": company_currency,
"balance": account_balances_cc.get(account.get("name")),
"account_currency": account.get("account_currency"),
"balance_in_account_currency": account_balances_ac.get(account.get("name")),
}
for account in account_list
]
return accounts_data
def create_payment_gateway_account(gateway, payment_channel="Email", company=None):
from erpnext.setup.setup_wizard.operations.install_fixtures import create_bank_account