843b7f6dd5
Every Financial Report's 2nd column is Currency, which is an implicit requirement to Print them properly. In this case, Income column was not printed. This fixes that.
195 lines
5.6 KiB
Python
195 lines
5.6 KiB
Python
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
|
# For license information, please see license.txt
|
|
|
|
from __future__ import unicode_literals
|
|
import frappe
|
|
from frappe import _
|
|
from frappe.utils import flt, getdate, formatdate, cstr
|
|
from erpnext.accounts.report.financial_statements import filter_accounts, filter_out_zero_value_rows
|
|
from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
|
|
|
|
value_fields = ("income", "expense", "gross_profit_loss")
|
|
|
|
def execute(filters=None):
|
|
if not filters.get('based_on'): filters["based_on"] = 'Cost Center'
|
|
|
|
based_on = filters.based_on.replace(' ', '_').lower()
|
|
validate_filters(filters)
|
|
accounts = get_accounts_data(based_on, filters.get("company"))
|
|
data = get_data(accounts, filters, based_on)
|
|
columns = get_columns(filters)
|
|
return columns, data
|
|
|
|
def get_accounts_data(based_on, company):
|
|
if based_on == 'cost_center':
|
|
return frappe.db.sql("""select name, parent_cost_center as parent_account, cost_center_name as account_name, lft, rgt
|
|
from `tabCost Center` where company=%s order by name""", company, as_dict=True)
|
|
else:
|
|
return frappe.get_all('Project', fields = ["name"], filters = {'company': company}, order_by = 'name')
|
|
|
|
def get_data(accounts, filters, based_on):
|
|
if not accounts:
|
|
return []
|
|
|
|
accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
|
|
|
|
gl_entries_by_account = {}
|
|
|
|
set_gl_entries_by_account(filters.get("company"), filters.get("from_date"),
|
|
filters.get("to_date"), based_on, gl_entries_by_account, ignore_closing_entries=not flt(filters.get("with_period_closing_entry")))
|
|
|
|
total_row = calculate_values(accounts, gl_entries_by_account, filters)
|
|
accumulate_values_into_parents(accounts, accounts_by_name)
|
|
|
|
data = prepare_data(accounts, filters, total_row, parent_children_map, based_on)
|
|
data = filter_out_zero_value_rows(data, parent_children_map,
|
|
show_zero_values=filters.get("show_zero_values"))
|
|
|
|
return data
|
|
|
|
def calculate_values(accounts, gl_entries_by_account, filters):
|
|
init = {
|
|
"income": 0.0,
|
|
"expense": 0.0,
|
|
"gross_profit_loss": 0.0
|
|
}
|
|
|
|
total_row = {
|
|
"cost_center": None,
|
|
"account_name": "'" + _("Total") + "'",
|
|
"warn_if_negative": True,
|
|
"income": 0.0,
|
|
"expense": 0.0,
|
|
"gross_profit_loss": 0.0,
|
|
"account": "'" + _("Total") + "'",
|
|
"parent_account": None,
|
|
"indent": 0,
|
|
"has_value": True
|
|
}
|
|
|
|
for d in accounts:
|
|
d.update(init.copy())
|
|
|
|
# add opening
|
|
|
|
for entry in gl_entries_by_account.get(d.name, []):
|
|
if cstr(entry.is_opening) != "Yes":
|
|
if entry.type == 'Income':
|
|
d["income"] += flt(entry.credit) - flt(entry.debit)
|
|
if entry.type == 'Expense':
|
|
d["expense"] += flt(entry.debit) - flt(entry.credit)
|
|
|
|
d["gross_profit_loss"] = d.get("income") - d.get("expense")
|
|
|
|
total_row["income"] += d["income"]
|
|
total_row["expense"] += d["expense"]
|
|
|
|
total_row["gross_profit_loss"] = total_row.get("income") - total_row.get("expense")
|
|
|
|
return total_row
|
|
|
|
def accumulate_values_into_parents(accounts, accounts_by_name):
|
|
for d in reversed(accounts):
|
|
if d.parent_account:
|
|
for key in value_fields:
|
|
accounts_by_name[d.parent_account][key] += d[key]
|
|
|
|
def prepare_data(accounts, filters, total_row, parent_children_map, based_on):
|
|
data = []
|
|
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency")
|
|
|
|
for d in accounts:
|
|
has_value = False
|
|
row = {
|
|
"account_name": d.account_name or d.name,
|
|
"account": d.name,
|
|
"parent_account": d.parent_account,
|
|
"indent": d.indent,
|
|
"fiscal_year": filters.get("fiscal_year"),
|
|
"currency": company_currency,
|
|
"based_on": based_on
|
|
}
|
|
|
|
for key in value_fields:
|
|
row[key] = flt(d.get(key, 0.0), 3)
|
|
|
|
if abs(row[key]) >= 0.005:
|
|
# ignore zero values
|
|
has_value = True
|
|
|
|
row["has_value"] = has_value
|
|
data.append(row)
|
|
|
|
data.extend([{},total_row])
|
|
|
|
return data
|
|
|
|
def get_columns(filters):
|
|
return [
|
|
{
|
|
"fieldname": "account",
|
|
"label": _(filters.get("based_on")),
|
|
"fieldtype": "Link",
|
|
"options": filters.get("based_on"),
|
|
"width": 300
|
|
},
|
|
{
|
|
"fieldname": "currency",
|
|
"label": _("Currency"),
|
|
"fieldtype": "Link",
|
|
"options": "Currency",
|
|
"hidden": 1
|
|
},
|
|
{
|
|
"fieldname": "income",
|
|
"label": _("Income"),
|
|
"fieldtype": "Currency",
|
|
"options": "currency",
|
|
"width": 120
|
|
},
|
|
{
|
|
"fieldname": "expense",
|
|
"label": _("Expense"),
|
|
"fieldtype": "Currency",
|
|
"options": "currency",
|
|
"width": 120
|
|
},
|
|
{
|
|
"fieldname": "gross_profit_loss",
|
|
"label": _("Gross Profit / Loss"),
|
|
"fieldtype": "Currency",
|
|
"options": "currency",
|
|
"width": 120
|
|
}
|
|
]
|
|
|
|
def set_gl_entries_by_account(company, from_date, to_date, based_on, gl_entries_by_account,
|
|
ignore_closing_entries=False):
|
|
"""Returns a dict like { "account": [gl entries], ... }"""
|
|
additional_conditions = []
|
|
|
|
if ignore_closing_entries:
|
|
additional_conditions.append("and ifnull(voucher_type, '')!='Period Closing Voucher'")
|
|
|
|
if from_date:
|
|
additional_conditions.append("and posting_date >= %(from_date)s")
|
|
|
|
gl_entries = frappe.db.sql("""select posting_date, {based_on} as based_on, debit, credit,
|
|
is_opening, (select root_type from `tabAccount` where name = account) as type
|
|
from `tabGL Entry` where company=%(company)s
|
|
{additional_conditions}
|
|
and posting_date <= %(to_date)s
|
|
and {based_on} is not null
|
|
order by {based_on}, posting_date""".format(additional_conditions="\n".join(additional_conditions), based_on= based_on),
|
|
{
|
|
"company": company,
|
|
"from_date": from_date,
|
|
"to_date": to_date
|
|
},
|
|
as_dict=True)
|
|
|
|
for entry in gl_entries:
|
|
gl_entries_by_account.setdefault(entry.based_on, []).append(entry)
|
|
|
|
return gl_entries_by_account
|