fix(General Ledger): include Accounting Dimension columns in report

Prior to this commit, custom Accounting Dimensions are not
  (by default) shown or even considered in generating a General
  Ledger report. Moreover, as they are not considered, they are
  not used to distinguish GL Entry lines in the same voucher
  with the same Account when the "Group By" value is
  "Group by Voucher (Consolidated)". This situation leads to
  lines with different values for the accounting dimension
  to be ganged together in the General Ledger view of a Journal
  entry, making the entry difficult for an accountant to read.

  This commit alleviates the problem by adding a checkbox
  to control whether Accounting Dimension columns are considered
  in the General Ledger report. When they are considered, they
  are displayed and also included in the key that distinguishes
  lines in the "Group by Voucher (Consolidated)" mode.

  Resolves #23033.
This commit is contained in:
Glen Whitney 2020-08-14 06:42:54 +00:00
parent 8ca57eb5dd
commit b2604d1f77
2 changed files with 44 additions and 13 deletions

View File

@ -146,6 +146,12 @@ frappe.query_reports["General Ledger"] = {
return frappe.db.get_link_options('Project', txt); return frappe.db.get_link_options('Project', txt);
} }
}, },
{
"fieldname": "include_dimensions",
"label": __("Consider Accounting Dimensions"),
"fieldtype": "Check",
"default": 0
},
{ {
"fieldname": "show_opening_entries", "fieldname": "show_opening_entries",
"label": __("Show Opening Entries"), "label": __("Show Opening Entries"),

View File

@ -106,15 +106,20 @@ def set_account_currency(filters):
return filters return filters
def get_result(filters, account_details): def get_result(filters, account_details):
gl_entries = get_gl_entries(filters) accounting_dimensions = []
if filters.get("include_dimensions"):
accounting_dimensions = get_accounting_dimensions()
data = get_data_with_opening_closing(filters, account_details, gl_entries) gl_entries = get_gl_entries(filters, accounting_dimensions)
data = get_data_with_opening_closing(filters, account_details,
accounting_dimensions, gl_entries)
result = get_result_as_list(data, filters) result = get_result_as_list(data, filters)
return result return result
def get_gl_entries(filters): def get_gl_entries(filters, accounting_dimensions):
currency_map = get_currency(filters) currency_map = get_currency(filters)
select_fields = """, debit, credit, debit_in_account_currency, select_fields = """, debit, credit, debit_in_account_currency,
credit_in_account_currency """ credit_in_account_currency """
@ -128,6 +133,10 @@ def get_gl_entries(filters):
filters['company_fb'] = frappe.db.get_value("Company", filters['company_fb'] = frappe.db.get_value("Company",
filters.get("company"), 'default_finance_book') filters.get("company"), 'default_finance_book')
dimension_fields = ""
if accounting_dimensions:
dimension_fields = ', '.join(accounting_dimensions) + ','
distributed_cost_center_query = "" distributed_cost_center_query = ""
if filters and filters.get('cost_center'): if filters and filters.get('cost_center'):
select_fields_with_percentage = """, debit*(DCC_allocation.percentage_allocation/100) as debit, credit*(DCC_allocation.percentage_allocation/100) as credit, debit_in_account_currency*(DCC_allocation.percentage_allocation/100) as debit_in_account_currency, select_fields_with_percentage = """, debit*(DCC_allocation.percentage_allocation/100) as debit, credit*(DCC_allocation.percentage_allocation/100) as credit, debit_in_account_currency*(DCC_allocation.percentage_allocation/100) as debit_in_account_currency,
@ -141,7 +150,7 @@ def get_gl_entries(filters):
party_type, party_type,
party, party,
voucher_type, voucher_type,
voucher_no, voucher_no, {dimension_fields}
cost_center, project, cost_center, project,
against_voucher_type, against_voucher_type,
against_voucher, against_voucher,
@ -160,13 +169,14 @@ def get_gl_entries(filters):
{conditions} {conditions}
AND posting_date <= %(to_date)s AND posting_date <= %(to_date)s
AND cost_center = DCC_allocation.parent AND cost_center = DCC_allocation.parent
""".format(select_fields_with_percentage=select_fields_with_percentage, conditions=get_conditions(filters).replace("and cost_center in %(cost_center)s ", '')) """.format(dimension_fields=dimension_fields,select_fields_with_percentage=select_fields_with_percentage, conditions=get_conditions(filters).replace("and cost_center in %(cost_center)s ", ''))
gl_entries = frappe.db.sql( gl_entries = frappe.db.sql(
""" """
select select
name as gl_entry, posting_date, account, party_type, party, name as gl_entry, posting_date, account, party_type, party,
voucher_type, voucher_no, cost_center, project, voucher_type, voucher_no, {dimension_fields}
cost_center, project,
against_voucher_type, against_voucher, account_currency, against_voucher_type, against_voucher, account_currency,
remarks, against, is_opening, creation {select_fields} remarks, against, is_opening, creation {select_fields}
from `tabGL Entry` from `tabGL Entry`
@ -174,7 +184,7 @@ def get_gl_entries(filters):
{distributed_cost_center_query} {distributed_cost_center_query}
{order_by_statement} {order_by_statement}
""".format( """.format(
select_fields=select_fields, conditions=get_conditions(filters), distributed_cost_center_query=distributed_cost_center_query, dimension_fields=dimension_fields, select_fields=select_fields, conditions=get_conditions(filters), distributed_cost_center_query=distributed_cost_center_query,
order_by_statement=order_by_statement order_by_statement=order_by_statement
), ),
filters, as_dict=1) filters, as_dict=1)
@ -247,12 +257,12 @@ def get_conditions(filters):
return "and {}".format(" and ".join(conditions)) if conditions else "" return "and {}".format(" and ".join(conditions)) if conditions else ""
def get_data_with_opening_closing(filters, account_details, gl_entries): def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries):
data = [] data = []
gle_map = initialize_gle_map(gl_entries, filters) gle_map = initialize_gle_map(gl_entries, filters)
totals, entries = get_accountwise_gle(filters, gl_entries, gle_map) totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map)
# Opening for filtered account # Opening for filtered account
data.append(totals.opening) data.append(totals.opening)
@ -318,7 +328,7 @@ def initialize_gle_map(gl_entries, filters):
return gle_map return gle_map
def get_accountwise_gle(filters, gl_entries, gle_map): def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map):
totals = get_totals_dict() totals = get_totals_dict()
entries = [] entries = []
consolidated_gle = OrderedDict() consolidated_gle = OrderedDict()
@ -350,8 +360,11 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
if filters.get("group_by") != _('Group by Voucher (Consolidated)'): if filters.get("group_by") != _('Group by Voucher (Consolidated)'):
gle_map[gle.get(group_by)].entries.append(gle) gle_map[gle.get(group_by)].entries.append(gle)
elif filters.get("group_by") == _('Group by Voucher (Consolidated)'): elif filters.get("group_by") == _('Group by Voucher (Consolidated)'):
key = (gle.get("voucher_type"), gle.get("voucher_no"), keylist = [gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account")]
gle.get("account"), gle.get("cost_center")) for dim in accounting_dimensions:
keylist.append(gle.get(dim))
keylist.append(gle.get("cost_center"))
key = tuple(keylist)
if key not in consolidated_gle: if key not in consolidated_gle:
consolidated_gle.setdefault(key, gle) consolidated_gle.setdefault(key, gle)
else: else:
@ -478,7 +491,19 @@ def get_columns(filters):
"options": "Project", "options": "Project",
"fieldname": "project", "fieldname": "project",
"width": 100 "width": 100
}, }
])
if filters.get("include_dimensions"):
for dim in get_accounting_dimensions(as_list = False):
columns.append({
"label": _(dim.label),
"options": dim.label,
"fieldname": dim.fieldname,
"width": 100
})
columns.extend([
{ {
"label": _("Cost Center"), "label": _("Cost Center"),
"options": "Cost Center", "options": "Cost Center",