From c64420036853b979225fa018eaebe70fbc5b5cad Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 4 Mar 2020 21:37:12 +0530 Subject: [PATCH 1/5] feat: Add report summary API for Balance Sheet and PL report --- .../report/balance_sheet/balance_sheet.py | 38 ++++++++++++++++++- .../profit_and_loss_statement.py | 23 +++++------ 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 97ce4f21e855..e5db484bbae8 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -58,7 +58,11 @@ def execute(filters=None): chart = get_chart_data(filters, columns, asset, liability, equity) - return columns, data, message, chart + if data: + report_summary = get_report_summary(asset[-2], liability[-2], equity[-2], provisional_profit_loss, + total_credit, columns[-1].get('fieldname')) + + return columns, data, message, chart, report_summary def get_provisional_profit_loss(asset, liability, equity, period_list, company, currency=None, consolidated=False): provisional_profit_loss = {} @@ -120,6 +124,38 @@ def check_opening_balance(asset, liability, equity): return _("Previous Financial Year is not closed"),opening_balance return None,None +def get_report_summary(asset, liability, equity, provisional_profit_loss, total_credit, key): + return [ + { + "value": asset.get(key), + "label": "Total Asset", + "indicator": "Green", + "datatype": "Currency", + "currency": asset.get('currency') + }, + { + "value": liability.get(key), + "label": "Total Liability", + "datatype": "Currency", + "indicator": "Red", + "currency": liability.get('currency') + }, + { + "value": equity.get(key), + "label": "Total Equity", + "datatype": "Currency", + "indicator": "Blue", + "currency": equity.get('currency') + }, + { + "value": provisional_profit_loss.get(key), + "label": "Provisional Profit / Loss (Credit)", + "indicator": "Green" if provisional_profit_loss.get(key) > 0 else "Red", + "datatype": "Currency", + "currency": provisional_profit_loss.get('currency') + } + ] + def get_chart_data(filters, columns, asset, liability, equity): labels = [d.get("label") for d in columns[2:]] diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index b96fe69ba89a..d212008a8bdf 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -31,20 +31,21 @@ def execute(filters=None): chart = get_chart_data(filters, columns, income, expense, net_profit_loss) - report_summary = get_report_summary(columns, income, expense, net_profit_loss, filters.periodicity, period_list) + report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss) return columns, data, None, chart, report_summary -def get_report_summary(columns, income, expense, net_profit_loss, period_list, periodicity): - income_data, expense_data, net_profit = [], [], [] +def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, consolidated=False): + net_income, net_expense, net_profit = 0.0, 0.0, 0.0 - for p in columns[2:]: + for period in period_list: + key = period if consolidated else period.key if income: - income_data.append(income[-2].get(p.get("fieldname"))) + net_income += income[-2].get(key) if expense: - expense_data.append(expense[-2].get(p.get("fieldname"))) + net_expense += expense[-2].get(key) if net_profit_loss: - net_profit.append(net_profit_loss.get(p.get("fieldname"))) + net_profit += net_profit_loss.get(key) if (len(period_list) == 1 and periodicity== 'Yearly'): profit_label = _("Profit This Year") @@ -57,20 +58,20 @@ def get_report_summary(columns, income, expense, net_profit_loss, period_list, p return [ { - "value": net_profit[-1], - "indicator": "Green" if net_profit[-1] > 0 else "Red", + "value": net_profit, + "indicator": "Green" if net_profit > 0 else "Red", "label": profit_label, "datatype": "Currency", "currency": net_profit_loss.get("currency") }, { - "value": income_data[-1], + "value": net_income, "label": income_label, "datatype": "Currency", "currency": income[-1].get('currency') }, { - "value": expense_data[-1], + "value": net_expense, "label": expense_label, "datatype": "Currency", "currency": expense[-1].get('currency') From 3cac99c2c6bebf18b5d696fdf06e0c862afe49bf Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 8 Mar 2020 19:05:33 +0530 Subject: [PATCH 2/5] fix: Add summary cards in Cash flow report --- .../report/balance_sheet/balance_sheet.py | 42 +++++++++++++------ .../accounts/report/cash_flow/cash_flow.py | 30 +++++++++++-- .../accounts/report/financial_statements.py | 6 +-- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index e5db484bbae8..6a1cdff6dad0 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -59,8 +59,12 @@ def execute(filters=None): chart = get_chart_data(filters, columns, asset, liability, equity) if data: - report_summary = get_report_summary(asset[-2], liability[-2], equity[-2], provisional_profit_loss, - total_credit, columns[-1].get('fieldname')) + if filters.get('accumulated_values'): + report_summary = get_report_summary([period_list[-1]], asset, liability, equity, provisional_profit_loss, + total_credit, currency) + else: + report_summary = get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, + total_credit, currency) return columns, data, message, chart, report_summary @@ -124,35 +128,49 @@ def check_opening_balance(asset, liability, equity): return _("Previous Financial Year is not closed"),opening_balance return None,None -def get_report_summary(asset, liability, equity, provisional_profit_loss, total_credit, key): +def get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, total_credit, currency, consolidated=False): + + net_asset, net_liability, net_equity, net_provisional_profit_loss = 0.0, 0.0, 0.0, 0.0 + + for period in period_list: + key = period if consolidated else period.key + if asset: + net_asset += asset[-2].get(key) + if liability: + net_liability += liability[-2].get(key) + if equity: + net_equity += equity[-2].get(key) + if provisional_profit_loss: + net_provisional_profit_loss += provisional_profit_loss.get(key) + return [ { - "value": asset.get(key), + "value": net_asset, "label": "Total Asset", "indicator": "Green", "datatype": "Currency", - "currency": asset.get('currency') + "currency": currency }, { - "value": liability.get(key), + "value": net_liability, "label": "Total Liability", "datatype": "Currency", "indicator": "Red", - "currency": liability.get('currency') + "currency": currency }, { - "value": equity.get(key), + "value": net_equity, "label": "Total Equity", "datatype": "Currency", "indicator": "Blue", - "currency": equity.get('currency') + "currency": currency }, { - "value": provisional_profit_loss.get(key), + "value": net_provisional_profit_loss, "label": "Provisional Profit / Loss (Credit)", - "indicator": "Green" if provisional_profit_loss.get(key) > 0 else "Red", + "indicator": "Green" if net_provisional_profit_loss > 0 else "Red", "datatype": "Currency", - "currency": provisional_profit_loss.get('currency') + "currency": currency } ] diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index e349a6aaaf04..be6e93cae0b3 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -8,6 +8,7 @@ from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data) from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss from erpnext.accounts.utils import get_fiscal_year +from six import iteritems def execute(filters=None): @@ -29,6 +30,7 @@ def execute(filters=None): net_profit_loss = get_net_profit_loss(income, expense, period_list, filters.company) data = [] + summary_data = {} company_currency = frappe.get_cached_value('Company', filters.company, "default_currency") for cash_flow_account in cash_flow_accounts: @@ -64,14 +66,16 @@ def execute(filters=None): section_data.append(account_data) add_total_row_account(data, section_data, cash_flow_account['section_footer'], - period_list, company_currency) + period_list, company_currency, summary_data) - add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency) + add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency, summary_data) columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) chart = get_chart_data(columns, data) - return columns, data, None, chart + report_summary = get_report_summary(summary_data, company_currency) + + return columns, data, None, chart, report_summary def get_cash_flow_accounts(): operation_accounts = { @@ -157,7 +161,7 @@ def get_start_date(period, accumulated_values, company): return start_date -def add_total_row_account(out, data, label, period_list, currency, consolidated = False): +def add_total_row_account(out, data, label, period_list, currency, summary_data, consolidated = False): total_row = { "account_name": "'" + _("{0}").format(label) + "'", "account": "'" + _("{0}").format(label) + "'", @@ -176,6 +180,24 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated out.append(total_row) out.append({}) + summary_data[label] = total_row["total"] + +def get_report_summary(summary_data, currency): + report_summary = [] + + for label, value in iteritems(summary_data): + report_summary.append( + { + "value": value, + "label": label, + "datatype": "Currency", + "currency": currency + } + ) + + return report_summary + + def get_chart_data(columns, data): labels = [d.get("label") for d in columns[2:]] datasets = [{'name':account.get('account').replace("'", ""), 'values': [account.get('total')]} for account in data if account.get('parent_account') == None and account.get('currency')] diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 35915d0fc64d..4b752601136a 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -151,7 +151,7 @@ def get_data( calculate_values( accounts_by_name, gl_entries_by_account, period_list, accumulated_values, ignore_accumulated_values_for_fy) - accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values) + accumulate_values_into_parents(accounts, accounts_by_name, period_list) out = prepare_data(accounts, balance_must_be, period_list, company_currency) out = filter_out_zero_value_rows(out, parent_children_map) @@ -191,7 +191,7 @@ def calculate_values( d["opening_balance"] = d.get("opening_balance", 0.0) + flt(entry.debit) - flt(entry.credit) -def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values): +def accumulate_values_into_parents(accounts, accounts_by_name, period_list): """accumulate children's values in parent accounts""" for d in reversed(accounts): if d.parent_account: @@ -412,7 +412,7 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters): additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)") else: additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") - + if accounting_dimensions: for dimension in accounting_dimensions: if filters.get(dimension): From e20a8aefcfcc8d5551302d12374d91e17d9b4347 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 8 Mar 2020 21:21:01 +0530 Subject: [PATCH 3/5] feat: Add report summary in consolidated financial statements --- .../report/balance_sheet/balance_sheet.py | 15 ++++----- .../consolidated_financial_statement.js | 14 +++++++- .../consolidated_financial_statement.py | 32 ++++++++++++------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 6a1cdff6dad0..cb1fdc1a79a5 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -58,13 +58,8 @@ def execute(filters=None): chart = get_chart_data(filters, columns, asset, liability, equity) - if data: - if filters.get('accumulated_values'): - report_summary = get_report_summary([period_list[-1]], asset, liability, equity, provisional_profit_loss, - total_credit, currency) - else: - report_summary = get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, - total_credit, currency) + report_summary = get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, + total_credit, currency, filters) return columns, data, message, chart, report_summary @@ -128,10 +123,14 @@ def check_opening_balance(asset, liability, equity): return _("Previous Financial Year is not closed"),opening_balance return None,None -def get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, total_credit, currency, consolidated=False): +def get_report_summary(period_list, asset, liability, equity, provisional_profit_loss, total_credit, currency, + filters, consolidated=False): net_asset, net_liability, net_equity, net_provisional_profit_loss = 0.0, 0.0, 0.0, 0.0 + if filters.get('accumulated_values'): + period_list = [period_list[-1]] + for period in period_list: key = period if consolidated else period.key if asset: diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js index 48a030a99ed3..92c5ee9124c3 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js @@ -61,5 +61,17 @@ frappe.query_reports["Consolidated Financial Statement"] = { "fieldtype": "Check", "default": 1 } - ] + ], + "formatter": function(value, row, column, data, default_formatter) { + value = default_formatter(value, row, column, data); + + if (!data.parent_account) { + value = $(`${value}`); + + var $value = $(value).css("font-weight", "bold"); + + value = $value.wrap("

").parent().html(); + } + return value; + } } diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index 4a79b6a340e8..461291b4531a 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -8,11 +8,11 @@ from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency from erpnext.accounts.report.financial_statements import get_fiscal_year_data, sort_accounts from erpnext.accounts.report.balance_sheet.balance_sheet import (get_provisional_profit_loss, - check_opening_balance, get_chart_data) + check_opening_balance, get_chart_data, get_report_summary as get_bs_summary) from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import (get_net_profit_loss, - get_chart_data as get_pl_chart_data) + get_chart_data as get_pl_chart_data, get_report_summary as get_pl_summary) from erpnext.accounts.report.cash_flow.cash_flow import (get_cash_flow_accounts, get_account_type_based_gl_data, - add_total_row_account) + add_total_row_account, get_report_summary as get_cash_flow_summary) def execute(filters=None): columns, data, message, chart = [], [], [], [] @@ -25,17 +25,17 @@ def execute(filters=None): columns = get_columns(companies_column) if filters.get('report') == "Balance Sheet": - data, message, chart = get_balance_sheet_data(fiscal_year, companies, columns, filters) + data, message, chart, report_summary = get_balance_sheet_data(fiscal_year, companies, columns, filters) elif filters.get('report') == "Profit and Loss Statement": - data, message, chart = get_profit_loss_data(fiscal_year, companies, columns, filters) + data, message, chart, report_summary = get_profit_loss_data(fiscal_year, companies, columns, filters) else: if cint(frappe.db.get_single_value('Accounts Settings', 'use_custom_cash_flow')): from erpnext.accounts.report.cash_flow.custom_cash_flow import execute as execute_custom return execute_custom(filters=filters) - data = get_cash_flow_data(fiscal_year, companies, filters) + data, report_summary = get_cash_flow_data(fiscal_year, companies, filters) - return columns, data, message, chart + return columns, data, message, chart, report_summary def get_balance_sheet_data(fiscal_year, companies, columns, filters): asset = get_data(companies, "Asset", "Debit", fiscal_year, filters=filters) @@ -75,9 +75,12 @@ def get_balance_sheet_data(fiscal_year, companies, columns, filters): if total_credit: data.append(total_credit) + report_summary = get_bs_summary(companies, asset, liability, equity, provisional_profit_loss, total_credit, + company_currency, filters, True) + chart = get_chart_data(filters, columns, asset, liability, equity) - return data, message, chart + return data, message, chart, report_summary def get_profit_loss_data(fiscal_year, companies, columns, filters): income, expense, net_profit_loss = get_income_expense_data(companies, fiscal_year, filters) @@ -90,7 +93,9 @@ def get_profit_loss_data(fiscal_year, companies, columns, filters): chart = get_pl_chart_data(filters, columns, income, expense, net_profit_loss) - return data, None, chart + report_summary = get_pl_summary(companies, '', income, expense, net_profit_loss, True) + + return data, None, chart, report_summary def get_income_expense_data(companies, fiscal_year, filters): company_currency = get_company_currency(filters) @@ -108,6 +113,7 @@ def get_cash_flow_data(fiscal_year, companies, filters): income, expense, net_profit_loss = get_income_expense_data(companies, fiscal_year, filters) data = [] + summary_data = {} company_currency = get_company_currency(filters) for cash_flow_account in cash_flow_accounts: @@ -142,11 +148,13 @@ def get_cash_flow_data(fiscal_year, companies, filters): section_data.append(account_data) add_total_row_account(data, section_data, cash_flow_account['section_footer'], - companies, company_currency, True) + companies, company_currency, summary_data, True) - add_total_row_account(data, data, _("Net Change in Cash"), companies, company_currency, True) + add_total_row_account(data, data, _("Net Change in Cash"), companies, company_currency, summary_data, True) - return data + report_summary = get_cash_flow_summary(summary_data, company_currency) + + return data, report_summary def get_account_type_based_data(account_type, companies, fiscal_year, filters): data = {} From bb98b7c151fc3ba15e09e58d54192b2f9c76fc54 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 17 Mar 2020 15:28:05 +0530 Subject: [PATCH 4/5] fix: Remove accumulated values filter from P&L and cashflow report --- erpnext/accounts/report/cash_flow/cash_flow.js | 5 ----- .../profit_and_loss_statement/profit_and_loss_statement.js | 5 ----- 2 files changed, 10 deletions(-) diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js index 89244c3781ad..904874f64591 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.js +++ b/erpnext/accounts/report/cash_flow/cash_flow.js @@ -12,11 +12,6 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { frappe.query_reports["Cash Flow"]["filters"].splice(5, 1); frappe.query_reports["Cash Flow"]["filters"].push( - { - "fieldname": "accumulated_values", - "label": __("Accumulated Values"), - "fieldtype": "Check" - }, { "fieldname": "include_default_book_entries", "label": __("Include Default Book Entries"), diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js index baa0bda70050..2b946c05401e 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js @@ -15,11 +15,6 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { return frappe.db.get_link_options('Project', txt); } }, - { - "fieldname": "accumulated_values", - "label": __("Accumulated Values"), - "fieldtype": "Check" - }, { "fieldname": "include_default_book_entries", "label": __("Include Default Book Entries"), From afdefaff08af71eb1a6d847e0df2f09df8f61f68 Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 18 Mar 2020 18:05:30 +0530 Subject: [PATCH 5/5] fix: set company default currency in profit and loss statement if no data --- .../profit_and_loss_statement.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index d212008a8bdf..81fb1e012e26 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -31,11 +31,12 @@ def execute(filters=None): chart = get_chart_data(filters, columns, income, expense, net_profit_loss) - report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss) + default_currency = frappe.get_cached_value('Company', filters.company, "default_currency") + report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss, default_currency) return columns, data, None, chart, report_summary -def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, consolidated=False): +def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, default_currency, consolidated=False): net_income, net_expense, net_profit = 0.0, 0.0, 0.0 for period in period_list: @@ -62,19 +63,19 @@ def get_report_summary(period_list, periodicity, income, expense, net_profit_los "indicator": "Green" if net_profit > 0 else "Red", "label": profit_label, "datatype": "Currency", - "currency": net_profit_loss.get("currency") + "currency": net_profit_loss.get("currency") if net_profit_loss else default_currency }, { "value": net_income, "label": income_label, "datatype": "Currency", - "currency": income[-1].get('currency') + "currency": income[-1].get('currency') if income else default_currency }, { "value": net_expense, "label": expense_label, "datatype": "Currency", - "currency": expense[-1].get('currency') + "currency": expense[-1].get('currency') if expense else default_currency } ]