220 lines
6.2 KiB
Python
220 lines
6.2 KiB
Python
from django.shortcuts import render, get_object_or_404, redirect
|
|
from django.http import HttpResponse
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.contrib.auth import views as auth_views
|
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
from django.views.generic import ListView
|
|
from django.core.paginator import Paginator
|
|
from django.db import models
|
|
import matplotlib.pyplot as plt
|
|
import tempfile
|
|
|
|
from .models import (
|
|
Transaction,
|
|
TransactionForm,
|
|
Invoice,
|
|
InvoiceForm,
|
|
Category,
|
|
CategoryForm,
|
|
Snapshot,
|
|
SnapshotForm,
|
|
)
|
|
|
|
|
|
@login_required
|
|
def index(request):
|
|
_transactions = Transaction.objects.all()[:10]
|
|
_categories = Category.objects.all()
|
|
_snapshots = Snapshot.objects.all()[:5]
|
|
|
|
context = {
|
|
"transactions": _transactions,
|
|
"categories": _categories,
|
|
"snapshots": _snapshots,
|
|
}
|
|
return render(request, "main/index.html", context)
|
|
|
|
|
|
class LoginView(auth_views.LoginView):
|
|
template_name = "main/login.html"
|
|
next_page = "index"
|
|
|
|
|
|
class LogoutView(auth_views.LogoutView):
|
|
next_page = "login"
|
|
|
|
|
|
class TransactionListView(LoginRequiredMixin, ListView):
|
|
paginate_by = 20
|
|
model = Transaction
|
|
template_name = "main/transactions.html"
|
|
context_object_name = "transactions"
|
|
|
|
|
|
@login_required
|
|
def transaction(request, uuid=None):
|
|
_form = None
|
|
_inv_form = None
|
|
_invoices = []
|
|
if request.method == "GET":
|
|
if uuid is None:
|
|
_transaction = Transaction()
|
|
else:
|
|
_transaction = get_object_or_404(Transaction, id=uuid)
|
|
elif request.method == "POST":
|
|
if request.POST["form"] == "transaction":
|
|
_transaction, _ = Transaction.objects.get_or_create(id=uuid)
|
|
_form = TransactionForm(request.POST, instance=_transaction)
|
|
if _form.is_valid():
|
|
_form.save()
|
|
_inv_form = InvoiceForm(instance=Invoice(transaction=_transaction))
|
|
elif request.POST["form"] == "invoice":
|
|
_transaction = get_object_or_404(Transaction, id=uuid)
|
|
_invoice = Invoice(transaction=_transaction)
|
|
_inv_form = InvoiceForm(request.POST, request.FILES, instance=_invoice)
|
|
if _inv_form.is_valid():
|
|
_inv_form.save()
|
|
|
|
return render(
|
|
request,
|
|
"main/transaction.html",
|
|
{
|
|
"transaction": _transaction,
|
|
"form": _form or TransactionForm(instance=_transaction),
|
|
"invoices": _invoices or Invoice.objects.filter(transaction=_transaction),
|
|
"invoice_form": _inv_form
|
|
or InvoiceForm(instance=Invoice(transaction=_transaction)),
|
|
},
|
|
)
|
|
|
|
|
|
@login_required
|
|
def del_transaction(request, uuid):
|
|
_transaction = get_object_or_404(Transaction, id=uuid)
|
|
_transaction.delete()
|
|
return redirect(index)
|
|
|
|
|
|
@login_required
|
|
def invoice(request, uuid):
|
|
_invoice = get_object_or_404(Invoice, id=uuid)
|
|
with _invoice.file.open() as _file:
|
|
return HttpResponse(_file.read(), content_type="application/pdf")
|
|
|
|
|
|
@login_required
|
|
def del_invoice(request, uuid, invoice_id):
|
|
_invoice = get_object_or_404(Invoice, id=invoice_id)
|
|
_invoice.delete()
|
|
return redirect(transaction, uuid=uuid)
|
|
|
|
|
|
@login_required
|
|
def category(request, uuid=None):
|
|
if request.method == "GET":
|
|
if uuid is None:
|
|
_category = Category()
|
|
else:
|
|
_category = get_object_or_404(Category, id=uuid)
|
|
_form = CategoryForm(instance=_category)
|
|
elif request.method == "POST":
|
|
_category, _ = Category.objects.get_or_create(id=uuid)
|
|
_form = CategoryForm(request.POST, instance=_category)
|
|
if _form.is_valid():
|
|
_form.save()
|
|
|
|
return render(
|
|
request,
|
|
"main/category.html",
|
|
{
|
|
"category": _category,
|
|
"form": _form,
|
|
"transactions": Transaction.objects.filter(category=_category),
|
|
},
|
|
)
|
|
|
|
|
|
@login_required
|
|
def del_category(request, uuid):
|
|
_category = get_object_or_404(Category, id=uuid)
|
|
_category.delete()
|
|
return redirect(index)
|
|
|
|
|
|
@login_required
|
|
def snapshot(request, uuid=None):
|
|
if request.method == "GET":
|
|
if uuid is None:
|
|
_snapshot = Snapshot()
|
|
else:
|
|
_snapshot = get_object_or_404(Snapshot, id=uuid)
|
|
context = {
|
|
"snapshot": _snapshot,
|
|
"form": SnapshotForm(instance=_snapshot),
|
|
}
|
|
elif request.method == "POST":
|
|
try:
|
|
_snapshot = Snapshot.objects.get(id=uuid)
|
|
except Snapshot.DoesNotExist:
|
|
_snapshot = Snapshot(id=uuid)
|
|
_form = SnapshotForm(request.POST, instance=_snapshot)
|
|
if _form.is_valid():
|
|
_form.save()
|
|
context = {
|
|
"snapshot": _snapshot,
|
|
"form": _form,
|
|
}
|
|
|
|
return render(
|
|
request,
|
|
"main/snapshot.html",
|
|
context,
|
|
)
|
|
|
|
|
|
@login_required
|
|
def snapshot_graph(request, uuid):
|
|
_snapshot = get_object_or_404(Snapshot, id=uuid)
|
|
_categories_p = (
|
|
_snapshot.transactions.filter(value__gt=0)
|
|
.values("category")
|
|
.annotate(sum=models.Sum("value"))
|
|
)
|
|
_categories_m = (
|
|
_snapshot.transactions.filter(value__lt=0)
|
|
.values("category")
|
|
.annotate(sum=models.Sum("value"))
|
|
)
|
|
|
|
print(_categories_p)
|
|
print(_categories_m)
|
|
fig, ax = plt.subplots()
|
|
ax.bar(
|
|
[
|
|
"*" if (c := _cat["category"]) is None else Category.objects.get(id=c).name
|
|
for _cat in _categories_p
|
|
],
|
|
[_cat["sum"] for _cat in _categories_p],
|
|
color="#007339",
|
|
)
|
|
ax.bar(
|
|
[
|
|
"*" if (c := _cat["category"]) is None else Category.objects.get(id=c).name
|
|
for _cat in _categories_m
|
|
],
|
|
[_cat["sum"] for _cat in _categories_m],
|
|
color="#bf1500",
|
|
)
|
|
ax.grid(color="k", alpha=0.2)
|
|
ax.set(ylabel="Value (€)")
|
|
with tempfile.NamedTemporaryFile(suffix=".svg") as f:
|
|
fig.savefig(f.name)
|
|
f.seek(0)
|
|
return HttpResponse(f.read(), content_type="image/svg+xml")
|
|
|
|
|
|
@login_required
|
|
def del_snapshot(request, uuid):
|
|
_snapshot = get_object_or_404(Snapshot, id=uuid)
|
|
_snapshot.delete()
|
|
return redirect(index)
|