fix(dashboard): simpler way to get account timeline from first principles
This commit is contained in:
parent
fbc56c6d97
commit
3882a41c51
@ -9,6 +9,8 @@ from frappe.core.page.dashboard.dashboard import cache_source
|
||||
from frappe.utils import add_to_date, date_diff, getdate, nowdate
|
||||
from erpnext.accounts.report.general_ledger.general_ledger import execute
|
||||
|
||||
from frappe.utils.nestedset import get_descendants_of
|
||||
|
||||
@frappe.whitelist()
|
||||
@cache_source
|
||||
def get(filters=None):
|
||||
@ -19,35 +21,56 @@ def get(filters=None):
|
||||
|
||||
from_date = get_from_date_from_timespan(timespan)
|
||||
to_date = nowdate()
|
||||
filters = frappe._dict({
|
||||
"company": company,
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"account": account,
|
||||
"group_by": "Group by Voucher (Consolidated)"
|
||||
})
|
||||
report_results = execute(filters=filters)[1]
|
||||
|
||||
interesting_fields = ["posting_date", "balance"]
|
||||
# fetch dates to plot
|
||||
dates = get_dates_from_timegrain(from_date, to_date, timegrain)
|
||||
|
||||
_results = []
|
||||
for row in report_results[1:-2]:
|
||||
_results.append([row[key] for key in interesting_fields])
|
||||
# get all the entries for this account and its descendants
|
||||
gl_entries = get_gl_entries(account, to_date)
|
||||
|
||||
_results = add_opening_balance(from_date, _results, report_results[0])
|
||||
grouped_results = groupby(_results, key=itemgetter(0))
|
||||
results = [list(values)[-1] for key, values in grouped_results]
|
||||
results = add_missing_dates(results, from_date, to_date)
|
||||
results = granulate_results(results, from_date, to_date, timegrain)
|
||||
# compile balance values
|
||||
result = build_result(account, dates, gl_entries)
|
||||
|
||||
return {
|
||||
"labels": [result[0] for result in results],
|
||||
"labels": [r[0].strftime('%Y-%m-%d') for r in result],
|
||||
"datasets": [{
|
||||
"name": account,
|
||||
"values": [result[1] for result in results]
|
||||
"values": [r[1] for r in result]
|
||||
}]
|
||||
}
|
||||
|
||||
def build_result(account, dates, gl_entries):
|
||||
result = [[getdate(date), 0.0] for date in dates]
|
||||
|
||||
# start with the first date
|
||||
date_index = 0
|
||||
|
||||
# get balances in debit
|
||||
for entry in gl_entries:
|
||||
|
||||
# find the date index after the posting date
|
||||
while getdate(entry.posting_date) > result[date_index][0]:
|
||||
date_index += 1
|
||||
|
||||
result[date_index][1] += entry.debit - entry.credit
|
||||
|
||||
# if account type is credit, switch balances
|
||||
if frappe.db.get_value('Account', account, 'root_type') not in ('Asset', 'Expense'):
|
||||
for r in result:
|
||||
r[1] = -1 * r[1]
|
||||
|
||||
return result
|
||||
|
||||
def get_gl_entries(account, to_date):
|
||||
child_accounts = get_descendants_of('Account', account, ignore_permissions=True)
|
||||
|
||||
return frappe.db.get_all('GL Entry',
|
||||
fields = ['posting_date', 'debit', 'credit'],
|
||||
filters = [
|
||||
dict(posting_date = ('<', to_date)),
|
||||
dict(account = ('in', child_accounts))
|
||||
])
|
||||
|
||||
def get_from_date_from_timespan(timespan):
|
||||
days = months = years = 0
|
||||
if "Last Week" == timespan:
|
||||
@ -61,24 +84,6 @@ def get_from_date_from_timespan(timespan):
|
||||
return add_to_date(None, years=years, months=months, days=days,
|
||||
as_string=True, as_datetime=True)
|
||||
|
||||
|
||||
def add_opening_balance(from_date, _results, opening):
|
||||
if not _results or (_results[0][0] != getdate(from_date)):
|
||||
_results.insert(0, [from_date, opening.balance])
|
||||
return _results
|
||||
|
||||
def add_missing_dates(incomplete_results, from_date, to_date):
|
||||
day_count = date_diff(to_date, from_date)
|
||||
|
||||
results_dict = dict(incomplete_results)
|
||||
last_balance = incomplete_results[0][1]
|
||||
results = []
|
||||
for date in (add_to_date(getdate(from_date), days=n) for n in range(day_count + 1)):
|
||||
if date in results_dict:
|
||||
last_balance = results_dict[date]
|
||||
results.append([date, last_balance])
|
||||
return results
|
||||
|
||||
def get_dates_from_timegrain(from_date, to_date, timegrain):
|
||||
days = months = years = 0
|
||||
if "Daily" == timegrain:
|
||||
@ -94,7 +99,3 @@ def get_dates_from_timegrain(from_date, to_date, timegrain):
|
||||
while dates[-1] <= to_date:
|
||||
dates.append(add_to_date(dates[-1], years=years, months=months, days=days))
|
||||
return dates
|
||||
|
||||
def granulate_results(incomplete_results, from_date, to_date, timegrain):
|
||||
dates = set(get_dates_from_timegrain(getdate(from_date), getdate(to_date), timegrain))
|
||||
return list(filter(lambda x: x[0] in dates,incomplete_results))
|
||||
|
Loading…
x
Reference in New Issue
Block a user