114 lines
2.8 KiB
Python
114 lines
2.8 KiB
Python
import io
|
|
|
|
import matplotlib
|
|
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 _
|
|
|
|
from main.models import (
|
|
Transaction,
|
|
Invoice,
|
|
Category,
|
|
Snapshot,
|
|
)
|
|
|
|
|
|
matplotlib.use("Agg")
|
|
plt.style.use("./plot/nummi.mplstyle")
|
|
|
|
|
|
@login_required
|
|
def timeline(request):
|
|
_snapshots = Snapshot.objects.all()
|
|
|
|
fig, ax = plt.subplots()
|
|
ax.step(
|
|
[s.date for s in _snapshots],
|
|
[s.value for s in _snapshots],
|
|
where="post",
|
|
)
|
|
ax.set(ylabel=_("Snapshots"), ylim=0)
|
|
ax.xaxis.set_major_formatter(
|
|
mdates.ConciseDateFormatter(ax.xaxis.get_major_locator())
|
|
)
|
|
ax.autoscale(True, "x", True)
|
|
|
|
_io = io.StringIO()
|
|
|
|
fig.savefig(_io, format="svg")
|
|
|
|
return HttpResponse(_io.getvalue(), headers={"Content-Type": "image/svg+xml"})
|
|
|
|
|
|
@login_required
|
|
def categories(request):
|
|
_categories = Category.objects.filter(budget=True)
|
|
|
|
fig, ax = plt.subplots(figsize=(8, _categories.count() / 4))
|
|
ax.barh(
|
|
[str(c) for c in _categories][::-1],
|
|
[
|
|
Transaction.objects.filter(category=c).aggregate(sum=models.Sum("value"))[
|
|
"sum"
|
|
]
|
|
for c in _categories
|
|
][::-1],
|
|
)
|
|
|
|
_io = io.StringIO()
|
|
|
|
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_p = (
|
|
Transaction.objects.filter(category=_category)
|
|
.filter(value__gt=0)
|
|
.annotate(m=models.functions.TruncMonth("date"))
|
|
.values("m")
|
|
.annotate(sum=models.Sum("value"))
|
|
.order_by("m")
|
|
)
|
|
_values_m = (
|
|
Transaction.objects.filter(category=_category)
|
|
.filter(value__lt=0)
|
|
.annotate(m=models.functions.TruncMonth("date"))
|
|
.values("m")
|
|
.annotate(sum=models.Sum("value"))
|
|
.order_by("m")
|
|
)
|
|
|
|
fig, ax = plt.subplots()
|
|
ax.bar(
|
|
[v["m"] for v in _values_p],
|
|
[v["sum"] for v in _values_p],
|
|
width=12,
|
|
color="#66cc66",
|
|
)
|
|
ax.bar(
|
|
[v["m"] for v in _values_m],
|
|
[v["sum"] for v in _values_m],
|
|
width=12,
|
|
color="#cc6699",
|
|
)
|
|
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"})
|