web/penny/templates/reports/account-monthly-breakdown.html
{% extends "navbar.html" %}
{% block content %}
<div class="container-fluid">
<h1 class="h3 mb-2 text-gray-800">Account Monthly Breakdown</h1>
<div class="row">
<div class="card shadow w-100">
<div class="card-header py-3">
{% if account %}<h6 class="m-0 font-weight-bold text-primary">{{ account.name }}</h6>{% endif %}
</div>
<div class="card-body">
<form action={{ url_for('reports.account_monthly_breakdown') }} method="POST">
{{ form.hidden_tag() }}
{{ form.csrf_token }}
<table class="table">
<tbody>
<tr>
<td>
{% if form.account.errors -%}
<div class="form-group has-error">
<label class="control-label" for="inputError">{{ form.account.errors[0] }}</label>
{% endif -%}
<select id="account" name="account" class="form-control">
{% for choice in form.account.choices %}
<option value="{{ choice.0 }}"{% if account and account.id|int == choice.0|int %} selected="selected"{% endif %}>{{choice.1}}</option>
{% endfor %}
</select>
{% if form.account.errors -%}
</div>
{% endif -%}
</td>
<td>
<input type="submit" class="btn btn-primary" name="submit" value="submit">
{{ form.submit }}
</td>
</tr>
</tbody>
</table>
</form>
{% if report.transactions|length >= 1 %}
<div class="chart-bar">
<canvas id="barChart"></canvas>
</div>
<table class="table table-bordered" data-toggle="table" data-pagination="true" data-page-size="50" width="100%" cellspacing="0">
<thead>
<tr>
<th data-field="month">Month</th>
<th data-field="amount">Amount</th>
<th data-field="change">Change</th>
<th data-field="average">Average</th>
</tr>
</thead>
<tbody>
{% for date, month in report.transactions.items()|sort(reverse=true) %}
{% set start_month = month.date|replace("-", "") + "01" %}
{% set end_month = month.date|replace("-", "") + month.daycount|string %}
<tr>
<td>{{ date }}</td>
<td><a href="{{ url_for('transactions.account', id=account.id, start_date=start_month, end_date=end_month) }}">{{ month.amount|convert_to_float }}</a></td>
<td>{{ month.change|convert_to_float }}</td>
<td>{{ month.avg|convert_to_float }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
</div>
</div>
</div>
{% if account %}
<script src="/static/vendor/chart.js/Chart.min.js"></script>
<script>
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = 'Nunito', '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#858796';
function number_format(number, decimals, dec_point, thousands_sep) {
// * example: number_format(1234.56, 2, ',', ' ');
// * return: '1 234,56'
number = (number + '').replace(',', '').replace(' ', '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function(n, prec) {
var k = Math.pow(10, prec);
return '' + Math.round(n * k) / k;
};
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
labels = JSON.parse({{ labels | tojson }})
data = JSON.parse({{ data | tojson }})
var ctx = document.getElementById("barChart");
var barChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: "{{ account.accounttype.name }}",
backgroundColor: "#4e73df",
hoverBackgroundColor: "#2e59d9",
borderColor: "#4e73df",
data: data,
}],
},
options: {
maintainAspectRatio: false,
layout: {
padding: {
left: 10,
right: 25,
top: 25,
bottom: 0
}
},
scales: {
xAxes: [{
time: {
unit: 'month'
},
gridLines: {
display: false,
drawBorder: false
},
ticks: {
maxTicksLimit: 6
},
maxBarThickness: 25,
}],
yAxes: [{
ticks: {
min: 0,
maxTicksLimit: 5,
padding: 10,
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return '$' + number_format(value);
}
},
gridLines: {
color: "rgb(234, 236, 244)",
zeroLineColor: "rgb(234, 236, 244)",
drawBorder: false,
borderDash: [2],
zeroLineBorderDash: [2]
}
}],
},
legend: {
display: false
},
tooltips: {
titleMarginBottom: 10,
titleFontColor: '#6e707e',
titleFontSize: 14,
backgroundColor: "rgb(255,255,255)",
bodyFontColor: "#858796",
borderColor: '#dddfeb',
borderWidth: 1,
xPadding: 15,
yPadding: 15,
displayColors: false,
caretPadding: 10,
callbacks: {
label: function(tooltipItem, chart) {
var datasetLabel = chart.datasets[tooltipItem.datasetIndex].label || '';
return datasetLabel + ': $' + number_format(tooltipItem.yLabel);
}
}
},
}
});
</script>
{% endif %}
{% endblock %}