[report][performance] Speed increased by approx 10 times in Trial Balance, General Ledger, AR/AP, Balance Sheet and P&L Statement
This commit is contained in:
parent
87edd86854
commit
6b01abe9ad
@ -544,7 +544,7 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
|
and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
|
||||||
and ifnull(jv_detail.against_jv, '') = '' )
|
and ifnull(jv_detail.against_jv, '') = '' )
|
||||||
and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
|
and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
|
||||||
(filters["account"], cstr(filters["party"]), "%{0}%".format(txt), start, page_len))
|
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_outstanding(args):
|
def get_outstanding(args):
|
||||||
|
@ -51,7 +51,7 @@ class ReceivablePayableReport(object):
|
|||||||
currency_precision = get_currency_precision() or 2
|
currency_precision = get_currency_precision() or 2
|
||||||
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
||||||
|
|
||||||
voucher_details = self.get_voucher_details()
|
voucher_details = self.get_voucher_details(args.get("party_type"))
|
||||||
|
|
||||||
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
||||||
|
|
||||||
@ -153,23 +153,26 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
return self.party_map
|
return self.party_map
|
||||||
|
|
||||||
def get_voucher_details(self):
|
def get_voucher_details(self, party_type):
|
||||||
voucher_details = frappe._dict()
|
voucher_details = frappe._dict()
|
||||||
|
|
||||||
|
if party_type == "Customer":
|
||||||
|
for si in frappe.db.sql("""select name, due_date
|
||||||
|
from `tabSales Invoice` where docstatus=1""", as_dict=1):
|
||||||
|
voucher_details.setdefault(si.name, si)
|
||||||
|
|
||||||
for si in frappe.db.sql("""select name, due_date
|
if party_type == "Supplier":
|
||||||
from `tabSales Invoice` where docstatus=1""", as_dict=1):
|
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
||||||
voucher_details.setdefault(si.name, si)
|
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
|
||||||
|
voucher_details.setdefault(pi.name, pi)
|
||||||
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
|
||||||
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
|
|
||||||
voucher_details.setdefault(pi.name, pi)
|
|
||||||
|
|
||||||
return voucher_details
|
return voucher_details
|
||||||
|
|
||||||
def get_gl_entries(self, party_type):
|
def get_gl_entries(self, party_type):
|
||||||
if not hasattr(self, "gl_entries"):
|
if not hasattr(self, "gl_entries"):
|
||||||
conditions, values = self.prepare_conditions(party_type)
|
conditions, values = self.prepare_conditions(party_type)
|
||||||
self.gl_entries = frappe.db.sql("""select * from `tabGL Entry`
|
self.gl_entries = frappe.db.sql("""select posting_date, account, party_type, party, debit, credit,
|
||||||
|
voucher_type, voucher_no, against_voucher_type, against_voucher from `tabGL Entry`
|
||||||
where docstatus < 2 and party_type=%s {0} order by posting_date, party"""
|
where docstatus < 2 and party_type=%s {0} order by posting_date, party"""
|
||||||
.format(conditions), values, as_dict=True)
|
.format(conditions), values, as_dict=True)
|
||||||
|
|
||||||
@ -187,7 +190,7 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
if self.filters.get(party_type_field):
|
if self.filters.get(party_type_field):
|
||||||
conditions.append("party=%s")
|
conditions.append("party=%s")
|
||||||
values.append(self.filters.get(party_type_field))
|
values.append(self.filters.get(party_type_field))
|
||||||
|
|
||||||
return " and ".join(conditions), values
|
return " and ".join(conditions), values
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
|
|||||||
gl_entries_by_account = get_gl_entries(company, period_list[0]["from_date"], period_list[-1]["to_date"],
|
gl_entries_by_account = get_gl_entries(company, period_list[0]["from_date"], period_list[-1]["to_date"],
|
||||||
accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
|
accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
|
||||||
|
|
||||||
calculate_values(accounts, gl_entries_by_account, period_list)
|
calculate_values(accounts_by_name, gl_entries_by_account, period_list)
|
||||||
accumulate_values_into_parents(accounts, accounts_by_name, period_list)
|
accumulate_values_into_parents(accounts, accounts_by_name, period_list)
|
||||||
out = prepare_data(accounts, balance_must_be, period_list)
|
out = prepare_data(accounts, balance_must_be, period_list)
|
||||||
|
|
||||||
@ -92,16 +92,14 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
|
|||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def calculate_values(accounts, gl_entries_by_account, period_list):
|
def calculate_values(accounts_by_name, gl_entries_by_account, period_list):
|
||||||
for d in accounts:
|
for entries in gl_entries_by_account.values():
|
||||||
for name in ([d.name] + (d.collapsed_children or [])):
|
for entry in entries:
|
||||||
for entry in gl_entries_by_account.get(name, []):
|
d = accounts_by_name.get(entry.account)
|
||||||
for period in period_list:
|
for period in period_list:
|
||||||
entry.posting_date = getdate(entry.posting_date)
|
# check if posting date is within the period
|
||||||
|
if entry.posting_date <= period.to_date:
|
||||||
# check if posting date is within the period
|
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
|
||||||
if entry.posting_date <= period.to_date:
|
|
||||||
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
|
|
||||||
|
|
||||||
|
|
||||||
def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
|
def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
|
||||||
@ -159,22 +157,8 @@ def add_total_row(out, balance_must_be, period_list):
|
|||||||
out.append({})
|
out.append({})
|
||||||
|
|
||||||
def get_accounts(company, root_type):
|
def get_accounts(company, root_type):
|
||||||
# root lft, rgt
|
return frappe.db.sql("""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
|
||||||
root_account = frappe.db.sql("""select lft, rgt from `tabAccount`
|
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)
|
||||||
where company=%s and root_type=%s and ifnull(parent_account, '') = ''
|
|
||||||
order by lft limit 1""",
|
|
||||||
(company, root_type), as_dict=True)
|
|
||||||
|
|
||||||
if not root_account:
|
|
||||||
return None
|
|
||||||
|
|
||||||
lft, rgt = root_account[0].lft, root_account[0].rgt
|
|
||||||
|
|
||||||
accounts = frappe.db.sql("""select * from `tabAccount`
|
|
||||||
where company=%(company)s and lft >= %(lft)s and rgt <= %(rgt)s order by lft""",
|
|
||||||
{ "company": company, "lft": lft, "rgt": rgt }, as_dict=True)
|
|
||||||
|
|
||||||
return accounts
|
|
||||||
|
|
||||||
def filter_accounts(accounts, depth=10):
|
def filter_accounts(accounts, depth=10):
|
||||||
parent_children_map = {}
|
parent_children_map = {}
|
||||||
@ -196,14 +180,6 @@ def filter_accounts(accounts, depth=10):
|
|||||||
filtered_accounts.append(child)
|
filtered_accounts.append(child)
|
||||||
add_to_list(child.name, level + 1)
|
add_to_list(child.name, level + 1)
|
||||||
|
|
||||||
else:
|
|
||||||
# include all children at level lower than the depth
|
|
||||||
parent_account = accounts_by_name[parent]
|
|
||||||
parent_account["collapsed_children"] = []
|
|
||||||
for d in accounts:
|
|
||||||
if d.lft > parent_account.lft and d.rgt < parent_account.rgt:
|
|
||||||
parent_account["collapsed_children"].append(d.name)
|
|
||||||
|
|
||||||
add_to_list(None, 0)
|
add_to_list(None, 0)
|
||||||
|
|
||||||
return filtered_accounts, accounts_by_name
|
return filtered_accounts, accounts_by_name
|
||||||
@ -234,7 +210,7 @@ def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closi
|
|||||||
if from_date:
|
if from_date:
|
||||||
additional_conditions.append("and posting_date >= %(from_date)s")
|
additional_conditions.append("and posting_date >= %(from_date)s")
|
||||||
|
|
||||||
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
|
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit from `tabGL Entry`
|
||||||
where company=%(company)s
|
where company=%(company)s
|
||||||
{additional_conditions}
|
{additional_conditions}
|
||||||
and posting_date <= %(to_date)s
|
and posting_date <= %(to_date)s
|
||||||
|
@ -66,7 +66,7 @@ def get_gl_entries(filters):
|
|||||||
|
|
||||||
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
|
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
|
||||||
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
|
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
|
||||||
voucher_type, voucher_no, cost_center, remarks, is_opening, against
|
voucher_type, voucher_no, cost_center, remarks, against
|
||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where company=%(company)s {conditions}
|
where company=%(company)s {conditions}
|
||||||
{group_by_condition}
|
{group_by_condition}
|
||||||
@ -91,6 +91,9 @@ def get_conditions(filters):
|
|||||||
|
|
||||||
if filters.get("party"):
|
if filters.get("party"):
|
||||||
conditions.append("party=%(party)s")
|
conditions.append("party=%(party)s")
|
||||||
|
|
||||||
|
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
|
||||||
|
conditions.append("posting_date >=%(from_date)s")
|
||||||
|
|
||||||
from frappe.desk.reportview import build_match_conditions
|
from frappe.desk.reportview import build_match_conditions
|
||||||
match_conditions = build_match_conditions("GL Entry")
|
match_conditions = build_match_conditions("GL Entry")
|
||||||
@ -148,14 +151,15 @@ def initialize_gle_map(gl_entries):
|
|||||||
|
|
||||||
def get_accountwise_gle(filters, gl_entries, gle_map):
|
def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||||
opening, total_debit, total_credit = 0, 0, 0
|
opening, total_debit, total_credit = 0, 0, 0
|
||||||
|
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
|
||||||
for gle in gl_entries:
|
for gle in gl_entries:
|
||||||
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
|
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
|
||||||
if gle.posting_date < getdate(filters.from_date):
|
if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
|
||||||
|
and gle.posting_date < from_date:
|
||||||
gle_map[gle.account].opening += amount
|
gle_map[gle.account].opening += amount
|
||||||
if filters.get("account") or filters.get("party"):
|
if filters.get("account") or filters.get("party"):
|
||||||
opening += amount
|
opening += amount
|
||||||
elif gle.posting_date <= getdate(filters.to_date):
|
elif gle.posting_date <= to_date:
|
||||||
gle_map[gle.account].entries.append(gle)
|
gle_map[gle.account].entries.append(gle)
|
||||||
gle_map[gle.account].total_debit += flt(gle.debit, 3)
|
gle_map[gle.account].total_debit += flt(gle.debit, 3)
|
||||||
gle_map[gle.account].total_credit += flt(gle.credit, 3)
|
gle_map[gle.account].total_credit += flt(gle.credit, 3)
|
||||||
|
@ -9,7 +9,7 @@ from erpnext.accounts.report.financial_statements import filter_accounts, get_gl
|
|||||||
|
|
||||||
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
|
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
|
||||||
|
|
||||||
def execute(filters):
|
def execute(filters=None):
|
||||||
validate_filters(filters)
|
validate_filters(filters)
|
||||||
data = get_data(filters)
|
data = get_data(filters)
|
||||||
columns = get_columns()
|
columns = get_columns()
|
||||||
@ -45,8 +45,8 @@ def validate_filters(filters):
|
|||||||
filters.to_date = filters.year_end_date
|
filters.to_date = filters.year_end_date
|
||||||
|
|
||||||
def get_data(filters):
|
def get_data(filters):
|
||||||
accounts = frappe.db.sql("""select * from `tabAccount` where company=%s order by lft""",
|
accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt
|
||||||
filters.company, as_dict=True)
|
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
|
||||||
|
|
||||||
if not accounts:
|
if not accounts:
|
||||||
return None
|
return None
|
||||||
@ -56,17 +56,58 @@ def get_data(filters):
|
|||||||
min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount`
|
min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount`
|
||||||
where company=%s""", (filters.company,))[0]
|
where company=%s""", (filters.company,))[0]
|
||||||
|
|
||||||
gl_entries_by_account = get_gl_entries(filters.company, None, filters.to_date, min_lft, max_rgt,
|
gl_entries_by_account = get_gl_entries(filters.company, filters.from_date, filters.to_date, min_lft, max_rgt,
|
||||||
ignore_closing_entries=not flt(filters.with_period_closing_entry))
|
ignore_closing_entries=not flt(filters.with_period_closing_entry))
|
||||||
|
|
||||||
total_row = calculate_values(accounts, gl_entries_by_account, filters)
|
opening_balances = get_opening_balances(filters)
|
||||||
|
|
||||||
|
total_row = calculate_values(accounts, gl_entries_by_account, opening_balances, filters)
|
||||||
accumulate_values_into_parents(accounts, accounts_by_name)
|
accumulate_values_into_parents(accounts, accounts_by_name)
|
||||||
|
|
||||||
data = prepare_data(accounts, filters, total_row)
|
data = prepare_data(accounts, filters, total_row)
|
||||||
|
|
||||||
return data
|
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 = " 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(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
|
||||||
|
from `tabGL Entry`
|
||||||
|
where
|
||||||
|
company=%(company)s
|
||||||
|
{additional_conditions}
|
||||||
|
and posting_date < %(from_date)s
|
||||||
|
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, filters):
|
def calculate_values(accounts, gl_entries_by_account, opening_balances, filters):
|
||||||
init = {
|
init = {
|
||||||
"opening_debit": 0.0,
|
"opening_debit": 0.0,
|
||||||
"opening_credit": 0.0,
|
"opening_credit": 0.0,
|
||||||
@ -88,29 +129,15 @@ def calculate_values(accounts, gl_entries_by_account, filters):
|
|||||||
d.update(init.copy())
|
d.update(init.copy())
|
||||||
|
|
||||||
for entry in gl_entries_by_account.get(d.name, []):
|
for entry in gl_entries_by_account.get(d.name, []):
|
||||||
posting_date = getdate(entry.posting_date)
|
d["debit"] += flt(entry.debit)
|
||||||
|
d["credit"] += flt(entry.credit)
|
||||||
# opening
|
|
||||||
if posting_date < filters.from_date:
|
|
||||||
is_valid_opening = (d.root_type in ("Asset", "Liability", "Equity") or
|
|
||||||
(filters.year_start_date <= posting_date < filters.from_date))
|
|
||||||
|
|
||||||
if is_valid_opening:
|
|
||||||
d["opening_debit"] += flt(entry.debit)
|
|
||||||
d["opening_credit"] += flt(entry.credit)
|
|
||||||
|
|
||||||
elif posting_date <= filters.to_date:
|
|
||||||
|
|
||||||
if entry.is_opening == "Yes" and d.root_type in ("Asset", "Liability", "Equity"):
|
|
||||||
d["opening_debit"] += flt(entry.debit)
|
|
||||||
d["opening_credit"] += flt(entry.credit)
|
|
||||||
|
|
||||||
else:
|
|
||||||
d["debit"] += flt(entry.debit)
|
|
||||||
d["credit"] += flt(entry.credit)
|
|
||||||
|
|
||||||
total_row["debit"] += d["debit"]
|
total_row["debit"] += d["debit"]
|
||||||
total_row["credit"] += d["credit"]
|
total_row["credit"] += d["credit"]
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
return total_row
|
return total_row
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
|
|||||||
# different filter for group and ledger - improved performance
|
# different filter for group and ledger - improved performance
|
||||||
if acc.is_group:
|
if acc.is_group:
|
||||||
cond.append("""exists (
|
cond.append("""exists (
|
||||||
select * from `tabAccount` ac where ac.name = gle.account
|
select name from `tabAccount` ac where ac.name = gle.account
|
||||||
and ac.lft >= %s and ac.rgt <= %s
|
and ac.lft >= %s and ac.rgt <= %s
|
||||||
)""" % (acc.lft, acc.rgt))
|
)""" % (acc.lft, acc.rgt))
|
||||||
else:
|
else:
|
||||||
@ -397,7 +397,7 @@ def get_outstanding_invoices(amount_query, account, party_type, party):
|
|||||||
|
|
||||||
for d in outstanding_voucher_list:
|
for d in outstanding_voucher_list:
|
||||||
payment_amount = frappe.db.sql("""
|
payment_amount = frappe.db.sql("""
|
||||||
select ifnull(sum(ifnull({amount_query}, 0)), 0)
|
select ifnull(sum({amount_query}), 0)
|
||||||
from
|
from
|
||||||
`tabGL Entry`
|
`tabGL Entry`
|
||||||
where
|
where
|
||||||
|
Loading…
x
Reference in New Issue
Block a user