fix: Clean and fixes in Dimension-wise Accounts Balance Report

(cherry picked from commit 08a06ce5c68023c41f53b584082b5e1c4ddb1f59)
This commit is contained in:
Deepesh Garg 2022-03-17 12:56:43 +05:30 committed by mergify-bot
parent da16ee159a
commit 2dd0e20003
2 changed files with 76 additions and 83 deletions

View File

@ -39,12 +39,14 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"label": __("From Date"), "label": __("From Date"),
"fieldtype": "Date", "fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"), "default": frappe.defaults.get_user_default("year_start_date"),
"reqd": 1
}, },
{ {
"fieldname": "to_date", "fieldname": "to_date",
"label": __("To Date"), "label": __("To Date"),
"fieldtype": "Date", "fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date"), "default": frappe.defaults.get_user_default("year_end_date"),
"reqd": 1
}, },
{ {
"fieldname": "finance_book", "fieldname": "finance_book",
@ -56,6 +58,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"fieldname": "dimension", "fieldname": "dimension",
"label": __("Select Dimension"), "label": __("Select Dimension"),
"fieldtype": "Select", "fieldtype": "Select",
"default": "Cost Center",
"options": get_accounting_dimension_options(), "options": get_accounting_dimension_options(),
"reqd": 1, "reqd": 1,
}, },
@ -70,7 +73,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
}); });
function get_accounting_dimension_options() { function get_accounting_dimension_options() {
let options =["", "Cost Center", "Project"]; let options =["Cost Center", "Project"];
frappe.db.get_list('Accounting Dimension', frappe.db.get_list('Accounting Dimension',
{fields:['document_type']}).then((res) => { {fields:['document_type']}).then((res) => {
res.forEach((dimension) => { res.forEach((dimension) => {

View File

@ -15,20 +15,22 @@ from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
def execute(filters=None): def execute(filters=None):
validate_filters(filters)
dimension_items_list = get_dimension_items_list(filters.dimension, filters.company)
if not dimension_items_list: validate_filters(filters)
dimension_list = get_dimensions(filters)
if not dimension_list:
return [], [] return [], []
dimension_items_list = [''.join(d) for d in dimension_items_list] # dimension_items_list = [''.join(d) for d in dimension_items_list]
columns = get_columns(dimension_items_list) columns = get_columns(dimension_list)
data = get_data(filters, dimension_items_list) data = get_data(filters, dimension_list)
return columns, data return columns, data
def get_data(filters, dimension_items_list): def get_data(filters, dimension_list):
company_currency = erpnext.get_company_currency(filters.company) company_currency = erpnext.get_company_currency(filters.company)
acc = frappe.db.sql(""" acc = frappe.db.sql("""
select select
name, account_number, parent_account, lft, rgt, root_type, name, account_number, parent_account, lft, rgt, root_type,
@ -51,17 +53,18 @@ def get_data(filters, dimension_items_list):
where lft >= %s and rgt <= %s and company = %s""", (min_lft, max_rgt, filters.company)) where lft >= %s and rgt <= %s and company = %s""", (min_lft, max_rgt, filters.company))
gl_entries_by_account = {} gl_entries_by_account = {}
set_gl_entries_by_account(dimension_items_list, filters, account, gl_entries_by_account) set_gl_entries_by_account(dimension_list, filters, account, gl_entries_by_account)
format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_items_list) format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_list,
accumulate_values_into_parents(accounts, accounts_by_name, dimension_items_list) frappe.scrub(filters.get('dimension')))
out = prepare_data(accounts, filters, parent_children_map, company_currency, dimension_items_list) accumulate_values_into_parents(accounts, accounts_by_name, dimension_list)
out = prepare_data(accounts, filters, company_currency, dimension_list)
out = filter_out_zero_value_rows(out, parent_children_map) out = filter_out_zero_value_rows(out, parent_children_map)
return out return out
def set_gl_entries_by_account(dimension_items_list, filters, account, gl_entries_by_account): def set_gl_entries_by_account(dimension_list, filters, account, gl_entries_by_account):
for item in dimension_items_list: condition = get_condition(filters.get('dimension'))
condition = get_condition(filters.from_date, item, filters.dimension)
if account: if account:
condition += " and account in ({})"\ condition += " and account in ({})"\
.format(", ".join([frappe.db.escape(d) for d in account])) .format(", ".join([frappe.db.escape(d) for d in account]))
@ -73,38 +76,31 @@ def set_gl_entries_by_account(dimension_items_list, filters, account, gl_entries
"finance_book": cstr(filters.get("finance_book")) "finance_book": cstr(filters.get("finance_book"))
} }
gl_filters['item'] = ''.join(item) gl_filters['dimensions'] = set(dimension_list)
if filters.get("include_default_book_entries"): if filters.get("include_default_book_entries"):
gl_filters["company_fb"] = frappe.db.get_value("Company", gl_filters["company_fb"] = frappe.db.get_value("Company",
filters.company, 'default_finance_book') filters.company, 'default_finance_book')
for key, value in filters.items():
if value:
gl_filters.update({
key: value
})
gl_entries = frappe.db.sql(""" gl_entries = frappe.db.sql("""
select select
posting_date, account, debit, credit, is_opening, fiscal_year, posting_date, account, {dimension}, debit, credit, is_opening, fiscal_year,
debit_in_account_currency, credit_in_account_currency, account_currency debit_in_account_currency, credit_in_account_currency, account_currency
from from
`tabGL Entry` `tabGL Entry`
where where
company=%(company)s company=%(company)s
{condition} {condition}
and posting_date >= %(from_date)s
and posting_date <= %(to_date)s and posting_date <= %(to_date)s
and is_cancelled = 0 and is_cancelled = 0
order by account, posting_date""".format( order by account, posting_date""".format(
condition=condition), dimension = frappe.scrub(filters.get('dimension')), condition=condition), gl_filters, as_dict=True) #nosec
gl_filters, as_dict=True) #nosec
for entry in gl_entries: for entry in gl_entries:
entry['dimension_item'] = ''.join(item)
gl_entries_by_account.setdefault(entry.account, []).append(entry) gl_entries_by_account.setdefault(entry.account, []).append(entry)
def format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_items_list): def format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_list, dimension_type):
for entries in gl_entries_by_account.values(): for entries in gl_entries_by_account.values():
for entry in entries: for entry in entries:
@ -114,11 +110,12 @@ def format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_items_l
_("Could not retrieve information for {0}.").format(entry.account), title="Error", _("Could not retrieve information for {0}.").format(entry.account), title="Error",
raise_exception=1 raise_exception=1
) )
for item in dimension_items_list:
if item == entry.dimension_item:
d[frappe.scrub(item)] = d.get(frappe.scrub(item), 0.0) + flt(entry.debit) - flt(entry.credit)
def prepare_data(accounts, filters, parent_children_map, company_currency, dimension_items_list): for dimension in dimension_list:
if dimension == entry.get(dimension_type):
d[frappe.scrub(dimension)] = d.get(frappe.scrub(dimension), 0.0) + flt(entry.debit) - flt(entry.credit)
def prepare_data(accounts, filters, company_currency, dimension_list):
data = [] data = []
for d in accounts: for d in accounts:
@ -135,13 +132,13 @@ def prepare_data(accounts, filters, parent_children_map, company_currency, dimen
if d.account_number else d.account_name) if d.account_number else d.account_name)
} }
for item in dimension_items_list: for dimension in dimension_list:
row[frappe.scrub(item)] = flt(d.get(frappe.scrub(item), 0.0), 3) row[frappe.scrub(dimension)] = flt(d.get(frappe.scrub(dimension), 0.0), 3)
if abs(row[frappe.scrub(item)]) >= 0.005: if abs(row[frappe.scrub(dimension)]) >= 0.005:
# ignore zero values # ignore zero values
has_value = True has_value = True
total += flt(d.get(frappe.scrub(item), 0.0), 3) total += flt(d.get(frappe.scrub(dimension), 0.0), 3)
row["has_value"] = has_value row["has_value"] = has_value
row["total"] = total row["total"] = total
@ -149,62 +146,55 @@ def prepare_data(accounts, filters, parent_children_map, company_currency, dimen
return data return data
def accumulate_values_into_parents(accounts, accounts_by_name, dimension_items_list): def accumulate_values_into_parents(accounts, accounts_by_name, dimension_list):
"""accumulate children's values in parent accounts""" """accumulate children's values in parent accounts"""
for d in reversed(accounts): for d in reversed(accounts):
if d.parent_account: if d.parent_account:
for item in dimension_items_list: for dimension in dimension_list:
accounts_by_name[d.parent_account][frappe.scrub(item)] = \ accounts_by_name[d.parent_account][frappe.scrub(dimension)] = \
accounts_by_name[d.parent_account].get(frappe.scrub(item), 0.0) + d.get(frappe.scrub(item), 0.0) accounts_by_name[d.parent_account].get(frappe.scrub(dimension), 0.0) + d.get(frappe.scrub(dimension), 0.0)
def get_condition(from_date, item, dimension): def get_condition(dimension):
conditions = [] conditions = []
if from_date: conditions.append("{0} in %(dimensions)s".format(frappe.scrub(dimension)))
conditions.append("posting_date >= %(from_date)s")
if dimension:
if dimension not in ['Cost Center', 'Project']:
if dimension in ['Customer', 'Supplier']:
dimension = 'Party'
else:
dimension = 'Voucher No'
txt = "{0} = %(item)s".format(frappe.scrub(dimension))
conditions.append(txt)
return " and {}".format(" and ".join(conditions)) if conditions else "" return " and {}".format(" and ".join(conditions)) if conditions else ""
def get_dimension_items_list(dimension, company): def get_dimensions(filters):
meta = frappe.get_meta(dimension, cached=False) meta = frappe.get_meta(filters.get('dimension'), cached=False)
fieldnames = [d.fieldname for d in meta.get("fields")] query_filters = {}
filters = {}
if 'company' in fieldnames:
filters['company'] = company
return frappe.get_all(dimension, filters, as_list=True)
def get_columns(dimension_items_list, accumulated_values=1, company=None): if meta.has_field('company'):
query_filters = {'company': filters.get('company')}
return frappe.get_all(filters.get('dimension'), filters=query_filters, pluck='name')
def get_columns(dimension_list):
columns = [{ columns = [{
"fieldname": "account", "fieldname": "account",
"label": _("Account"), "label": _("Account"),
"fieldtype": "Link", "fieldtype": "Link",
"options": "Account", "options": "Account",
"width": 300 "width": 300
}] },
if company: {
columns.append({
"fieldname": "currency", "fieldname": "currency",
"label": _("Currency"), "label": _("Currency"),
"fieldtype": "Link", "fieldtype": "Link",
"options": "Currency", "options": "Currency",
"hidden": 1 "hidden": 1
}) }]
for item in dimension_items_list:
for dimension in dimension_list:
columns.append({ columns.append({
"fieldname": frappe.scrub(item), "fieldname": frappe.scrub(dimension),
"label": item, "label": dimension,
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "currency", "options": "currency",
"width": 150 "width": 150
}) })
columns.append({ columns.append({
"fieldname": "total", "fieldname": "total",
"label": "Total", "label": "Total",