brotherton-erpnext/erpnext/accounts/report/trial_balance/trial_balance.py
Bassam Ramadan 1ff2315899 Trial balance and payable accounts reports and sales return fixes (#15000)
* adding supplier type filter to payable accounts and payable accounts summary reports

adding supplier type filter to payable accounts and payable accounts
summary reports as customer group at receivable accounts and summary
reports as its important and easier to put this filter

* fix trial balance opening and closing values

the removed mathematical operations was causing showing incorrect values
at opening and closing columns where the total row was correct so the
operation deleted to view the correct values to be equal to the total
row and to stop confusing the user due to different values between the
total row and the the values in front of each account

* fix for supplier type filter field on payable accounts reports

rename the supplier type filter field to supplier group in payable
accounts and summary reports

* fix for paid amount in returned sales invoice

the current paid amount not change from source value if you deleted any
item if the invoice contain for example 3 items and you only need to
return on item the current steps is to open the original invoice and
press on make return then you delete the unwanted items but in this case
the paid amount will not change and you will get an alert from the
system until you change it manually but with this modification it works
very well.

* fixing trial balance values and totals

fixing trial balance opening and closing ( DR - CR ) values and totals
2018-08-20 17:58:28 +05:30

304 lines
9.2 KiB
Python

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
from frappe.utils import flt, getdate, formatdate, cstr
from erpnext.accounts.report.financial_statements \
import filter_accounts, set_gl_entries_by_account, filter_out_zero_value_rows
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
def execute(filters=None):
validate_filters(filters)
data = get_data(filters)
columns = get_columns()
return columns, data
def validate_filters(filters):
if not filters.fiscal_year:
frappe.throw(_("Fiscal Year {0} is required").format(filters.fiscal_year))
fiscal_year = frappe.db.get_value("Fiscal Year", filters.fiscal_year, ["year_start_date", "year_end_date"], as_dict=True)
if not fiscal_year:
frappe.throw(_("Fiscal Year {0} does not exist").format(filters.fiscal_year))
else:
filters.year_start_date = getdate(fiscal_year.year_start_date)
filters.year_end_date = getdate(fiscal_year.year_end_date)
if not filters.from_date:
filters.from_date = filters.year_start_date
if not filters.to_date:
filters.to_date = filters.year_end_date
filters.from_date = getdate(filters.from_date)
filters.to_date = getdate(filters.to_date)
if filters.from_date > filters.to_date:
frappe.throw(_("From Date cannot be greater than To Date"))
if (filters.from_date < filters.year_start_date) or (filters.from_date > filters.year_end_date):
frappe.msgprint(_("From Date should be within the Fiscal Year. Assuming From Date = {0}")\
.format(formatdate(filters.year_start_date)))
filters.from_date = filters.year_start_date
if (filters.to_date < filters.year_start_date) or (filters.to_date > filters.year_end_date):
frappe.msgprint(_("To Date should be within the Fiscal Year. Assuming To Date = {0}")\
.format(formatdate(filters.year_end_date)))
filters.to_date = filters.year_end_date
def get_data(filters):
accounts = frappe.db.sql("""select name, account_number, parent_account, account_name, root_type, report_type, lft, rgt
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
company_currency = erpnext.get_company_currency(filters.company)
if not accounts:
return None
accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount`
where company=%s""", (filters.company,))[0]
gl_entries_by_account = {}
set_gl_entries_by_account(filters.company, filters.from_date,
filters.to_date, min_lft, max_rgt, filters, gl_entries_by_account, ignore_closing_entries=not flt(filters.with_period_closing_entry))
opening_balances = get_opening_balances(filters)
total_row = calculate_values(accounts, gl_entries_by_account, opening_balances, filters, company_currency)
accumulate_values_into_parents(accounts, accounts_by_name)
data = prepare_data(accounts, filters, total_row, parent_children_map, company_currency)
data = filter_out_zero_value_rows(data, parent_children_map,
show_zero_values=filters.get("show_zero_values"))
return data
def get_opening_balances(filters):
balance_sheet_opening = get_rootwise_opening_balances(filters, "Balance Sheet")
pl_opening = get_rootwise_opening_balances(filters, "Profit and Loss")
balance_sheet_opening.update(pl_opening)
return balance_sheet_opening
def get_rootwise_opening_balances(filters, report_type):
additional_conditions = ""
if not filters.show_unclosed_fy_pl_balances:
additional_conditions = " and posting_date >= %(year_start_date)s" \
if report_type == "Profit and Loss" else ""
if not flt(filters.with_period_closing_entry):
additional_conditions += " and ifnull(voucher_type, '')!='Period Closing Voucher'"
gle = frappe.db.sql("""
select
account, sum(debit) as opening_debit, sum(credit) as opening_credit
from `tabGL Entry`
where
company=%(company)s
{additional_conditions}
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
and account in (select name from `tabAccount` where report_type=%(report_type)s)
group by account""".format(additional_conditions=additional_conditions),
{
"company": filters.company,
"from_date": filters.from_date,
"report_type": report_type,
"year_start_date": filters.year_start_date
},
as_dict=True)
opening = frappe._dict()
for d in gle:
opening.setdefault(d.account, d)
return opening
def calculate_values(accounts, gl_entries_by_account, opening_balances, filters, company_currency):
init = {
"opening_debit": 0.0,
"opening_credit": 0.0,
"debit": 0.0,
"credit": 0.0,
"closing_debit": 0.0,
"closing_credit": 0.0
}
total_row = {
"account": "'" + _("Total") + "'",
"account_name": "'" + _("Total") + "'",
"warn_if_negative": True,
"opening_debit": 0.0,
"opening_credit": 0.0,
"debit": 0.0,
"credit": 0.0,
"closing_debit": 0.0,
"closing_credit": 0.0,
"parent_account": None,
"indent": 0,
"has_value": True,
"currency": company_currency
}
for d in accounts:
d.update(init.copy())
# add opening
d["opening_debit"] = opening_balances.get(d.name, {}).get("opening_debit", 0)
d["opening_credit"] = opening_balances.get(d.name, {}).get("opening_credit", 0)
for entry in gl_entries_by_account.get(d.name, []):
if cstr(entry.is_opening) != "Yes":
d["debit"] += flt(entry.debit)
d["credit"] += flt(entry.credit)
d["closing_debit"] = d["opening_debit"] + d["debit"]
d["closing_credit"] = d["opening_credit"] + d["credit"]
total_row["debit"] += d["debit"]
total_row["credit"] += d["credit"]
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["opening_debit"] -= d["opening_credit"]
d["opening_credit"] = 0.0
total_row["opening_debit"] += d["opening_debit"]
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["opening_credit"] -= d["opening_debit"]
d["opening_debit"] = 0.0
total_row["opening_credit"] += d["opening_credit"]
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["closing_debit"] -= d["closing_credit"]
d["closing_credit"] = 0.0
total_row["closing_debit"] += d["closing_debit"]
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["closing_credit"] -= d["closing_debit"]
d["closing_debit"] = 0.0
total_row["closing_credit"] += d["closing_credit"]
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, company_currency):
data = []
for d in accounts:
has_value = False
row = {
"account": d.name,
"parent_account": d.parent_account,
"indent": d.indent,
"from_date": filters.from_date,
"to_date": filters.to_date,
"currency": company_currency,
"account_name": ('{} - {}'.format(d.account_number, d.account_name)
if d.account_number else d.account_name)
}
prepare_opening_and_closing(d)
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():
return [
{
"fieldname": "account",
"label": _("Account"),
"fieldtype": "Link",
"options": "Account",
"width": 300
},
{
"fieldname": "opening_debit",
"label": _("Opening (Dr)"),
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"fieldname": "opening_credit",
"label": _("Opening (Cr)"),
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"fieldname": "debit",
"label": _("Debit"),
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"fieldname": "credit",
"label": _("Credit"),
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"fieldname": "closing_debit",
"label": _("Closing (Dr)"),
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"fieldname": "closing_credit",
"label": _("Closing (Cr)"),
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"fieldname": "currency",
"label": _("Currency"),
"fieldtype": "Link",
"options": "Currency",
"hidden": 1
}
]
def prepare_opening_and_closing(d):
d["closing_debit"] = d["opening_debit"] + d["debit"]
d["closing_credit"] = d["opening_credit"] + d["credit"]
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["opening_debit"] -= d["opening_credit"]
d["opening_credit"] = 0.0
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["opening_credit"] -= d["opening_debit"]
d["opening_debit"] = 0.0
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
d["closing_debit"] -= d["closing_credit"]
d["closing_credit"] = 0.0
if d["root_type"] == "Liability" or d["root_type"] == "Income":
d["closing_credit"] -= d["closing_debit"]
d["closing_debit"] = 0.0