From 826e18a29f3e7824ce2cef9b1d5f756f23e13e3f Mon Sep 17 00:00:00 2001 From: Chris Ian Fiel Date: Sat, 12 Dec 2015 10:33:01 +0800 Subject: [PATCH 1/3] Cash Flow Report --- erpnext/accounts/doctype/account/account.json | 22 +++++- erpnext/accounts/report/cash_flow/__init__.py | 0 .../accounts/report/cash_flow/cash_flow.js | 6 ++ .../accounts/report/cash_flow/cash_flow.json | 18 +++++ .../accounts/report/cash_flow/cash_flow.py | 72 +++++++++++++++++++ .../accounts/report/financial_statements.py | 32 +++++++++ erpnext/config/accounts.py | 6 ++ 7 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 erpnext/accounts/report/cash_flow/__init__.py create mode 100644 erpnext/accounts/report/cash_flow/cash_flow.js create mode 100644 erpnext/accounts/report/cash_flow/cash_flow.json create mode 100644 erpnext/accounts/report/cash_flow/cash_flow.py diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json index 66e710876a..ce038772c1 100644 --- a/erpnext/accounts/doctype/account/account.json +++ b/erpnext/accounts/doctype/account/account.json @@ -25,6 +25,7 @@ "oldfieldtype": "Section Break", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -46,6 +47,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -71,6 +73,7 @@ "oldfieldtype": "Data", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 1, @@ -95,6 +98,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -120,6 +124,7 @@ "options": "Company", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 1, @@ -143,6 +148,7 @@ "options": "\nAsset\nLiability\nIncome\nExpense\nEquity", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -166,6 +172,7 @@ "options": "\nBalance Sheet\nProfit and Loss", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -191,6 +198,7 @@ "permlevel": 0, "precision": "", "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -212,6 +220,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -238,6 +247,7 @@ "options": "Account", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 1, @@ -261,9 +271,10 @@ "no_copy": 0, "oldfieldname": "account_type", "oldfieldtype": "Select", - "options": "\nBank\nCash\nTax\nChargeable\nWarehouse\nReceivable\nPayable\nEquity\nFixed Asset\nCost of Goods Sold\nExpense Account\nRound Off\nIncome Account\nStock Received But Not Billed\nExpenses Included In Valuation\nStock Adjustment\nStock\nTemporary", + "options": "\nBank\nCash\nDepreciation\nTax\nChargeable\nWarehouse\nReceivable\nPayable\nEquity\nFixed Asset\nCost of Goods Sold\nExpense Account\nRound Off\nIncome Account\nStock Received But Not Billed\nExpenses Included In Valuation\nStock Adjustment\nStock\nTemporary", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -289,6 +300,7 @@ "oldfieldtype": "Currency", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -315,6 +327,7 @@ "options": "No\nYes", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -338,6 +351,7 @@ "options": "Warehouse", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -361,6 +375,7 @@ "options": "\nDebit\nCredit", "permlevel": 0, "print_hide": 0, + "print_hide_if_no_value": 0, "read_only": 0, "report_hide": 0, "reqd": 0, @@ -383,6 +398,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -405,6 +421,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -427,6 +444,7 @@ "no_copy": 0, "permlevel": 0, "print_hide": 1, + "print_hide_if_no_value": 0, "read_only": 1, "report_hide": 0, "reqd": 0, @@ -445,7 +463,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2015-11-16 06:29:41.535663", + "modified": "2015-12-12 10:19:54.365839", "modified_by": "Administrator", "module": "Accounts", "name": "Account", diff --git a/erpnext/accounts/report/cash_flow/__init__.py b/erpnext/accounts/report/cash_flow/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js new file mode 100644 index 0000000000..c8fb04cb9d --- /dev/null +++ b/erpnext/accounts/report/cash_flow/cash_flow.js @@ -0,0 +1,6 @@ +// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.require("assets/erpnext/js/financial_statements.js"); + +frappe.query_reports["Cash Flow"] = erpnext.financial_statements; diff --git a/erpnext/accounts/report/cash_flow/cash_flow.json b/erpnext/accounts/report/cash_flow/cash_flow.json new file mode 100644 index 0000000000..d0f2e048b2 --- /dev/null +++ b/erpnext/accounts/report/cash_flow/cash_flow.json @@ -0,0 +1,18 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2015-12-12 10:22:45.383203", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2015-12-12 10:22:45.383203", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Cash Flow", + "owner": "Administrator", + "ref_doctype": "GL Entry", + "report_name": "Cash Flow", + "report_type": "Script Report" +} \ No newline at end of file diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py new file mode 100644 index 0000000000..8ce19de5fb --- /dev/null +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -0,0 +1,72 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe import _ +from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data, get_data_account_type, add_total_row_account) +from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss + + +def execute(filters=None): + period_list = get_period_list(filters.fiscal_year, filters.periodicity) + + operation_accounts = {"section_name": "Operations", + "section_footer": _("Net Cash from Operations"), + "section_header": _("Cash Flow from Operations"), + "account_types": [{"account_type": "Depreciation", "label": _("Depreciation")}, + {"account_type": "Receivable", "label": _("Net Change in Accounts Receivable")}, + {"account_type": "Payable", "label": _("Net Change in Accounts Payable")}, + {"account_type": "Warehouse", "label": _("Net Change in Inventory")}]} + + investing_accounts = {"section_name": "Investing", + "section_footer": _("Net Cash from Investing"), + "section_header": _("Cash Flow from Investing"), + "account_types": [{"account_type": "Fixed Asset", "label": _("Net Change in Fixed Asset")}, + ]} + + financing_accounts = {"section_name": "Financing", + "section_footer": _("Net Cash from Financing"), + "section_header": _("Cash Flow from Financing"), + "account_types": [{"account_type": "Equity", "label": _("Net Change in Equity")}, + ]} + + # combine all cash flow accounts for iteration + cash_flow_accounts = [] + cash_flow_accounts.append(operation_accounts) + cash_flow_accounts.append(investing_accounts) + cash_flow_accounts.append(financing_accounts) + + # compute net income + income = get_data(filters.company, "Income", "Credit", period_list, ignore_closing_entries=True) + expense = get_data(filters.company, "Expense", "Debit", period_list, ignore_closing_entries=True) + net_profit_loss = get_net_profit_loss(income, expense, period_list) + + data = [] + + for cash_flow_account in cash_flow_accounts: + + section_data = [] + value = {"account_name": cash_flow_account['section_header'], "parent_account": None, + "indent": 0.0, "account": cash_flow_account['section_header']} + data.append(value) + + if not data: + # add first net income in operations section + if net_profit_loss: + net_profit_loss.update({"indent": 1, "parent_account": operation_accounts['section_header']}) + data.append(net_profit_loss) + section_data.append(net_profit_loss) + + for account in cash_flow_account['account_types']: + account_data = get_data_account_type(filters.company, account['account_type'], period_list) + account_data.update({"account_name": account['label'], "indent": 1, + "parent_account": cash_flow_account['section_header']}) + data.append(account_data) + section_data.append(account_data) + + add_total_row_account(data, section_data, cash_flow_account['section_footer'], period_list) + + add_total_row_account(data, data, _("Net Change in Cash"), period_list) + columns = get_columns(period_list) + + return columns, data diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 5cdf553de1..be13ea57f2 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -258,3 +258,35 @@ def get_columns(period_list): }) return columns + + +def get_data_account_type(company, account_type, period_list): + data = {} + for period in period_list: + gl_sum = frappe.db.sql_list("""select sum(credit) - sum(debit) FROM `tabGL Entry` + where company='%s' and posting_date >= '%s' and posting_date <= '%s' and + account in ( SELECT name FROM tabAccount WHERE account_type = '%s')""" % + (company, period['from_date'], period['to_date'], account_type)) + if gl_sum[0]: + amount = gl_sum[0] + else: + amount = 0 + data.update({"from_date": period['from_date'], "to_date": period['to_date'], period["key"]: amount}) + return data + + +def add_total_row_account(out, data, label, period_list): + # print out + total_row = { + "account_name": "'" + _("{0}").format(label) + "'", + "account": None + } + + for row in data: + if row.get("parent_account"): + for period in period_list: + total_row.setdefault(period.key, 0.0) + total_row[period.key] += row.get(period.key, 0.0) + + out.append(total_row) + out.append({}) diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index 7fca256c1a..8a27394509 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -229,6 +229,12 @@ def get_data(): "doctype": "GL Entry", "is_query_report": True }, + { + "type": "report", + "name": "Cash Flow", + "doctype": "GL Entry", + "is_query_report": True + }, { "type": "report", "name": "Profit and Loss Statement", From fde03453e460f04330399f8eb89d704d8b98b2b2 Mon Sep 17 00:00:00 2001 From: Chris Ian Fiel Date: Sat, 12 Dec 2015 10:54:56 +0800 Subject: [PATCH 2/3] Cash Flow Report --- erpnext/accounts/report/cash_flow/cash_flow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index 8ce19de5fb..6435b69694 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -50,7 +50,7 @@ def execute(filters=None): "indent": 0.0, "account": cash_flow_account['section_header']} data.append(value) - if not data: + if len(data) == 1: # add first net income in operations section if net_profit_loss: net_profit_loss.update({"indent": 1, "parent_account": operation_accounts['section_header']}) @@ -66,7 +66,7 @@ def execute(filters=None): add_total_row_account(data, section_data, cash_flow_account['section_footer'], period_list) - add_total_row_account(data, data, _("Net Change in Cash"), period_list) + add_total_row_account(data, data, _("Cash end of period"), period_list) columns = get_columns(period_list) return columns, data From c80796cdd53984edf4d02ffa70c034e265ca0b56 Mon Sep 17 00:00:00 2001 From: Chris Ian Fiel Date: Sat, 12 Dec 2015 11:26:54 +0800 Subject: [PATCH 3/3] Cash Flow Report --- erpnext/accounts/report/cash_flow/cash_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index 6435b69694..3e5efeac8d 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -66,7 +66,7 @@ def execute(filters=None): add_total_row_account(data, section_data, cash_flow_account['section_footer'], period_list) - add_total_row_account(data, data, _("Cash end of period"), period_list) + add_total_row_account(data, data, _("Net Change in Cash"), period_list) columns = get_columns(period_list) return columns, data