Skip to content

Commit

Permalink
issue #104 - WIP actually getting some results in to the UI
Browse files Browse the repository at this point in the history
  • Loading branch information
jantman committed Aug 14, 2017
1 parent 97d8e4b commit 73e6609
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 79 deletions.
7 changes: 7 additions & 0 deletions biweeklybudget/flaskapp/filters.py
Expand Up @@ -193,3 +193,10 @@ def dict_to_class_args(j):
kwargs = j.get('kwargs', {})
s += ', '.join(['%s=%s' % (k, kwargs[k]) for k in kwargs.keys()])
return s


@app.template_filter('monthsyears')
def monthsyears(num):
if num < 12:
return '%d months' % num
return '%d years' % round(num / 12)
89 changes: 45 additions & 44 deletions biweeklybudget/flaskapp/templates/credit-payoffs.html
Expand Up @@ -5,6 +5,48 @@
<link href="/static/bootstrap-datepicker/css/bootstrap-datepicker.standalone.min.css" rel="stylesheet">
{% endblock %}
{% block body %}
{% macro payoffresult(res) -%}
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default" id="result_panel_{{ res['name'] }}">
<div class="panel-heading">
<strong>{{ res['name'] }}</strong> <em>- {{ res['description'] }}</em><br /><em>{{ res['doc'] }}</em>
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover" id="table_{{ res['name'] }}">
<thead>
<tr>
<th>Account</th>
<th>Time To Pay Off</th>
<th>Total Payments</th>
<th>Total Interest</th>
</tr>
</thead>
<tbody>
{% for row in res['results'] %}
<tr>
<td>{{ row['name'] }}</td>
<td>{{ row['payoff_months']|monthsyears }}</td>
<td>{{ row['total_payments']|dollars }}</td>
<td>{{ row['total_interest']|dollars }}</td>
</tr>
{% endfor %}
<tr>
<th>Totals</th>
<th>{{ res['total']['payoff_months']|monthsyears }}</th>
<th>{{ res['total']['total_payments']|dollars }}</th>
<th>{{ res['total']['total_interest']|dollars }}</th>
</tr>
</tbody>
</table>
</div> <!-- /.table-responsive -->
</div> <!-- /.panel-body -->
</div> <!-- /.panel -->
</div> <!-- /.col-lg-12 -->
</div> <!-- /.row -->
{%- endmacro %}
{% include 'notifications.html' %}
<div class="row">
<div class="col-lg-12">
Expand Down Expand Up @@ -65,50 +107,9 @@
</div> <!-- /panel -->
</div> <!-- /.col-lg-12 -->
</div> <!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<strong>Some Calculation Method</strong> <em>- Some description</em>
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Account</th>
<th>Time To Pay Off</th>
<th>Total Payments</th>
<th>Total Interest</th>
</tr>
</thead>
<tbody>
<tr>
<td>CreditOne</td>
<td>X years</td>
<td>$X,XXX.XX</td>
<td>$X,XXX.XX</td>
</tr>
<tr>
<td>CreditTwo</td>
<td>X years</td>
<td>$X,XXX.XX</td>
<td>$X,XXX.XX</td>
</tr>
<tr>
<th>Totals</th>
<th>X years</th>
<th>$X,XXX.XX</th>
<th>$X,XXX.XX</th>
</tr>
</tbody>
</table>
</div> <!-- /.table-responsive -->
</div> <!-- /.panel-body -->
</div> <!-- /.panel -->
</div> <!-- /.col-lg-12 -->
</div> <!-- /.row -->
{% for calc in payoffs %}
{{ payoffresult(calc) }}
{% endfor %}
{% endblock %}
{% block extra_foot_script %}
<!-- BootStrap DatePicker JS -->
Expand Down
Empty file.
33 changes: 32 additions & 1 deletion biweeklybudget/flaskapp/views/credit_payoffs.py
Expand Up @@ -57,9 +57,40 @@ class CreditPayoffsView(MethodView):
def get(self):
ih = InterestHelper(db_session)
mps = sum(ih.min_payments.values())
res = ih.calculate_payoffs()
payoffs = []
for methname in sorted(res.keys()):
tmp = {
'name': methname,
'description': res[methname]['description'],
'doc': res[methname]['doc'],
'results': []
}
total_pymt = Decimal('0')
total_int = Decimal('0')
max_mos = 0
for k in sorted(res[methname]['results'].keys()):
r = res[methname]['results'][k]
tmp['results'].append({
'name': '%s (%d)' % (ih.accounts[k].name, k),
'total_payments': r['total_payments'],
'total_interest': r['total_interest'],
'payoff_months': r['payoff_months']
})
total_pymt += r['total_payments']
total_int += r['total_interest']
if r['payoff_months'] > max_mos:
max_mos = r['payoff_months']
tmp['total'] = {
'total_payments': total_pymt,
'total_interest': total_int,
'payoff_months': max_mos
}
payoffs.append(tmp)
return render_template(
'credit-payoffs.html',
monthly_pymt_sum=mps.quantize(Decimal('.01'), rounding=ROUND_UP)
monthly_pymt_sum=mps.quantize(Decimal('.01'), rounding=ROUND_UP),
payoffs=payoffs
)


Expand Down
22 changes: 12 additions & 10 deletions biweeklybudget/interest.py
Expand Up @@ -137,22 +137,25 @@ def calculate_payoffs(self):
Calculate payoffs for each account/statement.
:return: dict of payoff information. Keys are payoff method names.
Values are dicts, with keys "description" (str description of the
payoff method), "doc" (the docstring of the class), and "results".
The "results" dict has integer `account_id` as the key, and values are
dicts with keys "payoff_months" (int), "total_payments" (Decimal) and
"total_interest" (Decimal).
Values are dicts, with keys "description" (str description of the
payoff method), "doc" (the docstring of the class), and "results".
The "results" dict has integer `account_id` as the key, and values are
dicts with keys "payoff_months" (int), "total_payments" (Decimal) and
"total_interest" (Decimal).
:rtype: dict
"""
res = {}
max_total = sum(list(self.min_payments.values()))
for name, d in PAYOFF_METHOD_NAMES.items():
cls = d['cls']
if not cls.show_in_ui:
continue
res[name] = {
'description': d['description'],
'doc': d['doc'],
'results': self._calc_payoff_method(cls)
# @TODO - this really needs to come from the user,
# and also allow passing increases over time into the class.
'results': self._calc_payoff_method(cls(max_total))
}
return res

Expand All @@ -163,16 +166,15 @@ def _calc_payoff_method(self, cls):
:param cls: payoff method class
:type cls: biweeklybudget.interest._PayoffMethod
:return: Dict with integer `account_id` as the key, and values are
dicts with keys "payoff_months" (int), "total_payments" (Decimal) and
"total_interest" (Decimal).
dicts with keys "payoff_months" (int), "total_payments" (Decimal) and
"total_interest" (Decimal).
:rtype: dict
"""
accts = self.accounts
balances = {
x: self._statements[x].principal for x in self._statements.keys()
}
res = {}
calc = calculate_payoffs(cls, self._statements.values())
calc = calculate_payoffs(cls, list(self._statements.values()))
for idx, result in enumerate(calc):
a_id = list(self._statements.keys())[idx]
res[a_id] = {
Expand Down
Expand Up @@ -115,3 +115,13 @@ def test_01_no_config(self, base_url, selenium):
'amount': ''
}
}

def test_02_min_payment(self, base_url, selenium):
self.get(selenium, base_url + '/accounts/credit-payoff')
table = selenium.find_element_by_id('table_MinPaymentMethod')
texts = self.tbody2textlist(table)
assert texts == [
['CreditOne (3)', '2 years', '$963.21', '$11.15'],
['CreditTwo (4)', '14 years', '$8,764.66', '$3,266.01'],
['Totals', '14 years', '$9,727.87', '$3,277,16']
]

0 comments on commit 73e6609

Please sign in to comment.