From bbcaf1c1d333a3e5e932b4ab7b551af7b806a5e9 Mon Sep 17 00:00:00 2001 From: "Edgar P. Burkhart" Date: Tue, 20 Dec 2022 16:14:06 +0100 Subject: [PATCH] Add timeline per category --- nummi/plot/urls.py | 1 + nummi/plot/views.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/nummi/plot/urls.py b/nummi/plot/urls.py index fbff014..9a07e4e 100644 --- a/nummi/plot/urls.py +++ b/nummi/plot/urls.py @@ -5,4 +5,5 @@ from . import views urlpatterns = [ path("timeline", views.timeline, name="timeline"), path("categories", views.categories, name="categories"), + path("category/", views.category, name="category"), ] diff --git a/nummi/plot/views.py b/nummi/plot/views.py index e01aecb..5abc4d5 100644 --- a/nummi/plot/views.py +++ b/nummi/plot/views.py @@ -5,6 +5,7 @@ import matplotlib.pyplot as plt from matplotlib import dates as mdates from django.db import models from django.contrib.auth.decorators import login_required +from django.shortcuts import get_object_or_404 from django.http import HttpResponse from django.utils.translation import gettext as _ @@ -63,3 +64,35 @@ def categories(request): fig.savefig(_io, format="svg") return HttpResponse(_io.getvalue(), headers={"Content-Type": "image/svg+xml"}) + + +@login_required +def category(request, uuid): + _category = get_object_or_404(Category, id=uuid) + _values = ( + Transaction.objects.filter(category=_category) + .annotate(m=models.functions.TruncMonth("date")) + .values("m") + .annotate(sum=models.Sum("value")) + .order_by("m") + ) + + fig, ax = plt.subplots() + ax.step( + [v["m"] for v in _values], + [v["sum"] for v in _values], + where="post", + ) + ax.xaxis.set_major_formatter( + mdates.ConciseDateFormatter(ax.xaxis.get_major_locator()) + ) + ax.autoscale(True, "x", True) + _ym, _yp = ax.get_ylim() + ax.set(ylim=(min(_ym, 0), max(_yp, 0))) + ax.set(ylabel=f"{_category.name} (€)") + + _io = io.StringIO() + + fig.savefig(_io, format="svg") + + return HttpResponse(_io.getvalue(), headers={"Content-Type": "image/svg+xml"})