Skip to content

Commit

Permalink
issue #104 - generate and fill logic for payoffs settings form
Browse files Browse the repository at this point in the history
  • Loading branch information
jantman committed Aug 14, 2017
1 parent 2af58e0 commit 9a2f63e
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 22 deletions.
146 changes: 146 additions & 0 deletions biweeklybudget/flaskapp/static/js/credit_payoffs.js
@@ -0,0 +1,146 @@
/*
The latest version of this package is available at:
<http://github.com/jantman/biweeklybudget>
################################################################################
Copyright 2016 Jason Antman <jason@jasonantman.com> <http://www.jasonantman.com>
This file is part of biweeklybudget, also known as biweeklybudget.
biweeklybudget is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
biweeklybudget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with biweeklybudget. If not, see <http://www.gnu.org/licenses/>.
The Copyright and Authors attributions contained herein may not be removed or
otherwise altered, except to add the Author attribution of a contributor to
this work. (Additional Terms pursuant to Section 7b of the AGPL v3)
################################################################################
While not legally required, I sincerely request that anyone who finds
bugs please submit them at <https://github.com/jantman/biweeklybudget> or
to me via email, and that you send any contributions or improvements
either as a pull request on GitHub, or to me via email.
################################################################################
AUTHORS:
Jason Antman <jason@jasonantman.com> <http://www.jasonantman.com>
################################################################################
*/

/**
* Link handler to add another "starting on, increase payments by" form to
* the credit payoff page.
*/
function addIncrease(settings) {
idx = nextIndex("payoff_increase_frm_");
var s = '<form id="payoff_increase_frm_' + idx + '" class="form-inline">';
s = s + '<div class="form-group">';
s = s + '<label for="payoff_increase_frm_' + idx + '_enable" class="control-label sr-only">Enable Payment Increase ' + idx + '</label>';
s = s + '<input type="checkbox" id="payoff_increase_frm_' + idx + '_enable" name="payoff_increase_frm_' + idx + '_enable" onchange="setChanged()">';
s = s + ' Starting on ';
s = s + '<label for="payoff_increase_frm_' + idx + '_date" class="control-label sr-only">Payment Increase ' + idx + ' Date</label>';
s = s + '<div class="input-group date" id="payoff_increase_frm_' + idx + '_date_input_group">';
s = s + '<span class="input-group-addon"><i class="fa fa-calendar fa-fw"></i></span><input class="form-control" id="payoff_increase_frm_' + idx + '_date" name="payoff_increase_frm_' + idx + '_date" type="text" size="12" maxlength="10" style="width: auto;" onchange="setChanged()">';
s = s + '</div>';
s = s + ' , increase sum of monthly payments by ';
s = s + '<label for="payoff_increase_frm_' + idx + '_amt" class="control-label sr-only">Payment Increase ' + idx + ' Amount</label>';
s = s + '<div class="input-group">';
s = s + '<span class="input-group-addon">$</span><input class="form-control" id="payoff_increase_frm_' + idx + '_amt" name="payoff_increase_frm_' + idx + '_amt" type="text" size="8" style="width: auto;" onchange="setChanged()">';
s = s + '</div> .</div></form>';
s = s + '<!-- /#payoff_increase_frm_' + idx + ' -->';
$('#payoff_increase_forms').append(s);
if ( settings !== undefined ) {
$('#payoff_increase_frm_' + idx + '_enable').prop('checked', settings['enabled']);
$('#payoff_increase_frm_' + idx + '_date').val(settings['date']['str']);
$('#payoff_increase_frm_' + idx + '_date').datepicker({
todayBtn: "linked",
autoclose: true,
todayHighlight: true,
format: 'yyyy-mm-dd'
});
$('#payoff_increase_frm_' + idx + '_amt').val(settings['amount']);
}
}

/**
* Return the next index for the form with an ID beginning with a given string.
*
* @param {string} prefix - The prefix of the form IDs.
* @return {int} next form index
*/
function nextIndex(prefix) {
return $('form[id^="' + prefix + '"]').length + 1;
}

/**
* Link handler to add another one time payment form to the credit payoff page.
*/
function addOnetime(settings) {
idx = nextIndex("payoff_onetime_frm_");
var s = '<form id="payoff_onetime_frm_' + idx + '" class="form-inline">';
s = s + '<div class="form-group">';
s = s + '<label for="payoff_onetime_frm_' + idx + '_enable" class="control-label sr-only">Enable Onetime Payment ' + idx + '</label>';
s = s + '<input type="checkbox" id="payoff_onetime_frm_' + idx + '_enable" name="payoff_onetime_frm_' + idx + '_enable" onchange="setChanged()">';
s = s + ' On the first payment date on or after ';
s = s + '<label for="payoff_onetime_frm_' + idx + '_date" class="control-label sr-only">Onetime Payment ' + idx + ' Date</label>';
s = s + '<div class="input-group date" id="payoff_onetime_frm_' + idx + '_date_input_group">';
s = s + '<span class="input-group-addon"><i class="fa fa-calendar fa-fw"></i></span><input class="form-control" id="payoff_onetime_frm_' + idx + '_date" name="payoff_onetime_frm_' + idx + '_date" type="text" size="12" maxlength="10" style="width: auto;" onchange="setChanged()">';
s = s + '</div>';
s = s + ' , add ';
s = s + '<label for="payoff_onetime_frm_' + idx + '_amt" class="control-label sr-only">Onetime Payment ' + idx + ' Amount</label>';
s = s + '<div class="input-group">';
s = s + '<span class="input-group-addon">$</span><input class="form-control" id="payoff_onetime_frm_' + idx + '_amt" name="payoff_onetime_frm_' + idx + '_amt" type="text" size="8" style="width: auto;" onchange="setChanged()">';
s = s + '</div> to the payment amount.</div></form>';
s = s + '<!-- /#payoff_onetime_frm_' + idx + ' -->';
$('#payoff_onetime_forms').append(s);
if ( settings !== undefined ) {
$('#payoff_onetime_frm_' + idx + '_enable').prop('checked', settings['enabled']);
$('#payoff_onetime_frm_' + idx + '_date').val(settings['date']['str']);
$('#payoff_onetime_frm_' + idx + '_date').datepicker({
todayBtn: "linked",
autoclose: true,
todayHighlight: true,
format: 'yyyy-mm-dd'
});
$('#payoff_onetime_frm_' + idx + '_amt').val(settings['amount']);
}
}

/**
* Buttom handler to serialize and submit the forms, to save user input and
* recalculate the payoff amounts.
*/
function recalcPayoffs() {
console.log("recalcPayoffs() called");
}

/**
* Event handler to activate the "Save & Recalculate" button when user input
* fields have changed.
*/
function setChanged() {
$('#btn_recalc_payoffs').removeClass('disabled btn-default').addClass('btn-primary');
}

/**
* Load settings from embedded JSON. Called on page load.
*/
function loadSettings() {
var settings = JSON.parse($('#pymt_settings_json').html());
for (var s in settings["increases"]) { addIncrease(settings["increases"][s]); }
if ( settings["increases"].length == 0 ) { addIncrease(); }
for (var s in settings["onetimes"]) { addOnetime(settings["onetimes"][s]); }
if ( settings["onetimes"].length == 0 ) { addOnetime(); }
}

$(document).ready(function() {
loadSettings();
});
27 changes: 9 additions & 18 deletions biweeklybudget/flaskapp/templates/credit-payoffs.html
Expand Up @@ -3,6 +3,10 @@
{% block extra_head_css %}
<!-- Bootstrap Datepicker CSS -->
<link href="/static/bootstrap-datepicker/css/bootstrap-datepicker.standalone.min.css" rel="stylesheet">

<script type="application/json" id="pymt_settings_json">
{{ pymt_settings_json|safe }}
</script>
{% endblock %}
{% block body %}
{% macro payoffresult(res) -%}
Expand Down Expand Up @@ -82,24 +86,10 @@
</div> <!-- /.form-group -->
</fieldset>
</form> <!-- /#min_payment_frm -->
<form id="payoff_increase_frm_1" class="form-inline">
<div class="form-group">
<label for="payoff_increase_frm_1_enable" class="control-label sr-only">Enable Payment Increase 1</label>
<input type="checkbox" id="payoff_increase_frm_1_enable" name="payoff_increase_frm_1_enable" onchange="setChanged()">
Starting on
<label for="payoff_increase_frm_1_date" class="control-label sr-only">Payment Increase 1 Date</label>
<div class="input-group date" id="payoff_increase_frm_1_date_input_group">
<span class="input-group-addon"><i class="fa fa-calendar fa-fw"></i></span><input class="form-control" id="payoff_increase_frm_1_date" name="payoff_increase_frm_1_date" type="text" size="12" maxlength="10" style="width: auto;" onchange="setChanged()">
</div> <!-- /.input-group -->
, increase sum of monthly payments by
<label for="payoff_increase_frm_1_amt" class="control-label sr-only">Payment Increase 1 Amount</label>
<div class="input-group">
<span class="input-group-addon">$</span><input class="form-control" id="payoff_increase_frm_1_amt" name="payoff_increase_frm_1_amt" type="text" size="8" style="width: auto;" onchange="setChanged()">
</div> <!-- /.input-group -->
.
</div> <!-- /.form-group -->
</form> <!-- /#payoff_increase_frm_1 -->
<div style="padding-top: 1em;"><em><a onclick="addIncrease()">(add another increase)</a></em></div>
<div id="payoff_increase_forms"></div>
<div style="padding-top: 1em; padding-bottom: 1em;"><em><a href="#" onclick="addIncrease()">(add another increase)</a></em></div>
<div id="payoff_onetime_forms"></div>
<div style="padding-top: 1em; padding-bottom: 1em;"><em><a href="#" onclick="addOnetime()">(add another one-time additional payment)</a></em></div>
</div> <!-- /.panel-body -->
<div class="panel-footer">
<button type="button" class="btn btn-sm btn-default disabled" id="btn_recalc_payoffs" onclick="recalcPayoffs()">Save & Recalculate</button>
Expand All @@ -116,4 +106,5 @@
<script src="/utils/datetest.js"></script>
<script src="/static/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
<script src="/static/js/custom.js"></script>
<script src="/static/js/credit_payoffs.js"></script>
{% endblock %}
30 changes: 26 additions & 4 deletions biweeklybudget/flaskapp/views/credit_payoffs.py
Expand Up @@ -36,14 +36,18 @@
"""

import logging
import json
from decimal import Decimal, ROUND_UP
from datetime import date

from flask.views import MethodView
from flask import render_template

from biweeklybudget.flaskapp.jsonencoder import MagicJSONEncoder
from biweeklybudget.flaskapp.app import app
from biweeklybudget.db import db_session
from biweeklybudget.interest import InterestHelper
from biweeklybudget.models.dbsetting import DBSetting

logger = logging.getLogger(__name__)

Expand All @@ -54,9 +58,15 @@ class CreditPayoffsView(MethodView):
``credit-payoffs.html`` template.
"""

def get(self):
ih = InterestHelper(db_session)
mps = sum(ih.min_payments.values())
def _payoffs_list(self, ih):
"""
Return a payoffs list suitable for rendering.
:param ih: interest helper instance
:type ih: biweeklybudget.interest.InterestHelper
:return: list of payoffs suitable for rendering
:rtype: list
"""
res = ih.calculate_payoffs()
payoffs = []
for methname in sorted(res.keys()):
Expand Down Expand Up @@ -87,10 +97,22 @@ def get(self):
'payoff_months': max_mos
}
payoffs.append(tmp)
return payoffs

def get(self):
pymt_settings_json = db_session.query(DBSetting).get('credit-payoff')
if pymt_settings_json is None:
pymt_settings_json = json.dumps({'increases': [], 'onetimes': []})
# @NOTE we'll need to convert these JSON values to the right
# (Decimal and date) types.
ih = InterestHelper(db_session)
mps = sum(ih.min_payments.values())
payoffs = self._payoffs_list(ih)
return render_template(
'credit-payoffs.html',
monthly_pymt_sum=mps.quantize(Decimal('.01'), rounding=ROUND_UP),
payoffs=payoffs
payoffs=payoffs,
pymt_settings_json=pymt_settings_json
)


Expand Down

0 comments on commit 9a2f63e

Please sign in to comment.