Graph previous year totals and year-to-date totals next to budget listing/filtering results

This commit is contained in:
Yingtong Li 2023-05-01 21:24:24 +10:00
parent 8d3a7b7ed0
commit 603e276bac
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
2 changed files with 60 additions and 0 deletions

View File

@ -111,6 +111,11 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% if yearly_totals %}
<h2>Yearly totals</h2>
<canvas id="chartYearlyTotals"></canvas>
{% endif %}
{% endblock %} {% endblock %}
{% block head %} {% block head %}
@ -123,4 +128,41 @@
<script> <script>
$('.ui.dropdown').dropdown(); $('.ui.dropdown').dropdown();
</script> </script>
{% if yearly_totals %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.3.0/dist/chart.umd.js" integrity="sha256-5dsP1lVzcWPn5aOwu+zs+G+TqAu9oT8NUNM0C4n3H+4=" crossorigin="anonymous"></script>
<script>
const yearlyTotalsData = JSON.parse({{ import('json').dumps(import('json').dumps(yearly_totals))|safe }});
new Chart(document.getElementById('chartYearlyTotals'), {
type: 'bar',
data: {
labels: yearlyTotalsData.map(x => x[0]),
datasets: [{
label: {{ import('json').dumps(import('json').dumps(request.GET.get('cost_centre', 'all')))|safe }},
data: yearlyTotalsData.map(x => x[1]),
backgroundColor: yearlyTotalsData.map(x => x[1] >= 0 ? '#36a2eb' : '#ff6384')
}]
},
options: {
indexAxis: 'y',
scales: {
x: {
beginAtZero: true
}
},
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: i => '$' + i.parsed.x.toFixed(2)
}
}
}
},
});
</script>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -36,6 +36,7 @@ from ssmain.email import Emailer
import csv import csv
from datetime import datetime from datetime import datetime
from decimal import Decimal
import functools import functools
import io import io
import itertools import itertools
@ -266,13 +267,30 @@ def budget_list(request):
if group is not None: if group is not None:
group.append(revision) group.append(revision)
# Get yearly totals
if request.GET.get('cost_centre', 'all') != 'all':
yearly_totals = [[y, float(t)] for y, t in get_yearly_totals(budgets_filtered)]
else:
yearly_totals = None
return render(request, 'sstreasury/budget_list.html', { return render(request, 'sstreasury/budget_list.html', {
'budgets_action': budgets_action, 'budgets_action': budgets_action,
'budgets_open': budgets_open, 'budgets_open': budgets_open,
'budgets_closed': budgets_closed, 'budgets_closed': budgets_closed,
'yearly_totals': yearly_totals,
'page': page 'page': page
}) })
def get_yearly_totals(budgets_filtered):
"""Get total net profit per calendar year"""
results = []
for year, g in itertools.groupby(sorted(budgets_filtered, key=lambda r: r.time.year), key=lambda r: r.time.year):
results.append((year, sum((r.get_revenue_total() - r.get_expense_total() for r in g), Decimal('0'))))
return results
@login_required @login_required
@uses_budget @uses_budget
def budget_view(request, budget, revision): def budget_view(request, budget, revision):