Add snapshot form

This commit is contained in:
Edgar P. Burkhart 2022-05-22 10:06:44 +02:00
parent 4b784a553b
commit cb458cf472
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
17 changed files with 159 additions and 372 deletions

View file

@ -1,7 +1,10 @@
# Generated by Django 4.0.4 on 2022-05-20 12:24 # Generated by Django 4.0.4 on 2022-05-22 07:45
import datetime
import django.core.validators
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import re
import uuid import uuid
@ -24,9 +27,26 @@ class Migration(migrations.Migration):
serialize=False, serialize=False,
), ),
), ),
("name", models.CharField(max_length=256)), (
"name",
models.CharField(
default="New Category",
max_length=64,
validators=[
django.core.validators.RegexValidator(
re.compile("^[-\\w]+\\Z"),
"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens.",
"invalid",
)
], ],
), ),
),
("icon", models.CharField(default="folder", max_length=64)),
],
options={
"ordering": ["name"],
},
),
migrations.CreateModel( migrations.CreateModel(
name="Transaction", name="Transaction",
fields=[ fields=[
@ -39,10 +59,14 @@ class Migration(migrations.Migration):
serialize=False, serialize=False,
), ),
), ),
("name", models.CharField(max_length=256)), ("name", models.CharField(default="New Transaction", max_length=256)),
("description", models.TextField()), ("description", models.TextField(blank=True, null=True)),
("value", models.DecimalField(decimal_places=2, max_digits=12)), (
("date", models.DateField()), "value",
models.DecimalField(decimal_places=2, default=0, max_digits=12),
),
("date", models.DateField(default=datetime.date.today)),
("trader", models.CharField(blank=True, max_length=128, null=True)),
( (
"category", "category",
models.ForeignKey( models.ForeignKey(
@ -53,6 +77,47 @@ class Migration(migrations.Migration):
), ),
), ),
], ],
options={
"ordering": ["-date"],
},
),
migrations.CreateModel(
name="Snapshot",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("date", models.DateField(default=datetime.date.today, unique=True)),
(
"value",
models.DecimalField(decimal_places=2, default=0, max_digits=12),
),
(
"diff",
models.DecimalField(
decimal_places=2, default=0, editable=False, max_digits=12
),
),
(
"previous",
models.OneToOneField(
blank=True,
editable=False,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="main.snapshot",
),
),
],
options={
"ordering": ["-date"],
},
), ),
migrations.CreateModel( migrations.CreateModel(
name="Invoice", name="Invoice",
@ -66,8 +131,16 @@ class Migration(migrations.Migration):
serialize=False, serialize=False,
), ),
), ),
("name", models.CharField(max_length=256)), ("name", models.CharField(default="New Invoice", max_length=256)),
("file", models.FileField(upload_to="invoices/")), (
"file",
models.FileField(
upload_to="invoices/",
validators=[
django.core.validators.FileExtensionValidator(["pdf"])
],
),
),
( (
"transaction", "transaction",
models.ForeignKey( models.ForeignKey(
@ -77,29 +150,4 @@ class Migration(migrations.Migration):
), ),
], ],
), ),
migrations.CreateModel(
name="SubCategory",
fields=[
(
"category_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="main.category",
),
),
(
"parent",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="category_parent",
to="main.category",
),
),
],
bases=("main.category",),
),
] ]

View file

@ -1,16 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-20 12:30
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("main", "0001_initial"),
]
operations = [
migrations.DeleteModel(
name="SubCategory",
),
]

View file

@ -1,29 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-20 13:33
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("main", "0002_delete_subcategory"),
]
operations = [
migrations.AddField(
model_name="category",
name="parent",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="main.category",
),
),
migrations.AlterField(
model_name="category",
name="name",
field=models.CharField(max_length=64),
),
]

View file

@ -1,23 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-20 14:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("main", "0003_category_parent_alter_category_name"),
]
operations = [
migrations.AlterModelOptions(
name="category",
options={"ordering": ["-parent_id", "name"]},
),
migrations.AddField(
model_name="category",
name="full_name",
field=models.CharField(default="", max_length=512),
preserve_default=False,
),
]

View file

@ -1,18 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-20 14:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("main", "0004_alter_category_options_category_full_name"),
]
operations = [
migrations.AlterField(
model_name="category",
name="full_name",
field=models.CharField(default="", editable=False, max_length=512),
),
]

View file

@ -1,67 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-20 16:06
import datetime
import django.core.validators
from django.db import migrations, models
import re
class Migration(migrations.Migration):
dependencies = [
("main", "0005_alter_category_full_name"),
]
operations = [
migrations.AlterModelOptions(
name="category",
options={"ordering": ["full_name"]},
),
migrations.AddField(
model_name="transaction",
name="trader",
field=models.CharField(blank=True, max_length=128, null=True),
),
migrations.AlterField(
model_name="category",
name="name",
field=models.CharField(
max_length=64,
validators=[
django.core.validators.RegexValidator(
re.compile("^[-\\w]+\\Z"),
"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens.",
"invalid",
)
],
),
),
migrations.AlterField(
model_name="invoice",
name="file",
field=models.FileField(
upload_to="invoices/",
validators=[django.core.validators.FileExtensionValidator(["pdf"])],
),
),
migrations.AlterField(
model_name="transaction",
name="date",
field=models.DateField(default=datetime.date.today),
),
migrations.AlterField(
model_name="transaction",
name="description",
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name="transaction",
name="name",
field=models.CharField(default="Transaction", max_length=256),
),
migrations.AlterField(
model_name="transaction",
name="value",
field=models.DecimalField(decimal_places=2, default=0, max_digits=12),
),
]

View file

@ -1,56 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-20 19:25
import django.core.validators
from django.db import migrations, models
import re
class Migration(migrations.Migration):
dependencies = [
("main", "0006_alter_category_options_transaction_trader_and_more"),
]
operations = [
migrations.AlterModelOptions(
name="category",
options={},
),
migrations.AlterModelOptions(
name="transaction",
options={"ordering": ["-date"]},
),
migrations.RemoveField(
model_name="category",
name="full_name",
),
migrations.RemoveField(
model_name="category",
name="parent",
),
migrations.AlterField(
model_name="category",
name="name",
field=models.CharField(
default="New Category",
max_length=64,
validators=[
django.core.validators.RegexValidator(
re.compile("^[-\\w]+\\Z"),
"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens.",
"invalid",
)
],
),
),
migrations.AlterField(
model_name="invoice",
name="name",
field=models.CharField(default="New Invoice", max_length=256),
),
migrations.AlterField(
model_name="transaction",
name="name",
field=models.CharField(default="New Transaction", max_length=256),
),
]

View file

@ -1,22 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-20 20:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("main", "0007_alter_category_options_alter_transaction_options_and_more"),
]
operations = [
migrations.AlterModelOptions(
name="category",
options={"ordering": ["name"]},
),
migrations.AddField(
model_name="category",
name="icon",
field=models.CharField(default="folder", max_length=64),
),
]

View file

@ -1,44 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-21 18:40
import datetime
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
("main", "0008_alter_category_options_category_icon"),
]
operations = [
migrations.CreateModel(
name="Snapshot",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("date", models.DateField(default=datetime.date.today)),
(
"value",
models.DecimalField(decimal_places=2, default=0, max_digits=12),
),
(
"previous",
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="main.snapshot",
),
),
],
),
]

View file

@ -1,25 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-21 18:44
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("main", "0009_snapshot"),
]
operations = [
migrations.AlterField(
model_name="snapshot",
name="previous",
field=models.OneToOneField(
blank=True,
editable=False,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="main.snapshot",
),
),
]

View file

@ -1,30 +0,0 @@
# Generated by Django 4.0.4 on 2022-05-22 06:43
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("main", "0010_alter_snapshot_previous"),
]
operations = [
migrations.AlterModelOptions(
name="snapshot",
options={"ordering": ["-date"]},
),
migrations.AddField(
model_name="snapshot",
name="diff",
field=models.DecimalField(
decimal_places=2, default=0, editable=False, max_digits=12
),
),
migrations.AlterField(
model_name="snapshot",
name="date",
field=models.DateField(default=datetime.date.today, unique=True),
),
]

View file

@ -94,6 +94,7 @@ class Snapshot(models.Model):
if not only_super: if not only_super:
_prev = ( _prev = (
self.__class__.objects.order_by("-date") self.__class__.objects.order_by("-date")
.exclude(id=self.id)
.filter(date__lt=self.date) .filter(date__lt=self.date)
.first() .first()
) )
@ -139,3 +140,9 @@ class Snapshot(models.Model):
class Meta: class Meta:
ordering = ["-date"] ordering = ["-date"]
class SnapshotForm(ModelForm):
class Meta:
model = Snapshot
fields = ["date", "value"]

View file

@ -29,6 +29,10 @@
class="{% if request.resolver_match.url_name == "category" %} cur{% endif %}"> class="{% if request.resolver_match.url_name == "category" %} cur{% endif %}">
Add category Add category
</a> </a>
<a href="{% url 'snapshot' %}"
class="{% if request.resolver_match.url_name == "snapshot" %} cur{% endif %}">
Add snapshot
</a>
<a href="{% url 'logout' %}" <a href="{% url 'logout' %}"
class="logout"> class="logout">
Log Out Log Out

View file

@ -55,7 +55,9 @@
</div> </div>
{% for snap in snapshots %} {% for snap in snapshots %}
<div class="snapshot {% cycle 'w' 'g' %}"> <div class="snapshot {% cycle 'w' 'g' %}">
<span class="date num center">{{ snap.date|date:"Y-m-d" }}</span> <span class="date num center">
<a href="{% url 'snapshot' snap.date %}">{{ snap.date|date:"Y-m-d" }}</a>
</span>
<span class="value num right">{{ snap.value|floatformat:"2g" }} €</span> <span class="value num right">{{ snap.value|floatformat:"2g" }} €</span>
<span class="diff num right">{{ snap.diff|floatformat:"2g"|pm }} €</span> <span class="diff num right">{{ snap.diff|floatformat:"2g"|pm }} €</span>
{% with sum=snap.sum %} {% with sum=snap.sum %}

View file

@ -0,0 +1,26 @@
{% extends "main/base.html" %}
{% load static %}
{% block link %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'main/css/form.css' %}" type="text/css" />
{% endblock %}
{% block body %}
<h1>{{ snapshot }}</h1>
<form action="{% url 'update_snapshot' snapshot.id %}" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.errors }}
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
{% endfor %}
<div class="buttons">
<a href="{% url 'del_snapshot' snapshot.date %}"><input type="button" value="Delete" /></a>
<input type="reset" />
<input type="submit" value="Save Snapshot" />
</div>
</form>
{% endblock %}

View file

@ -21,4 +21,8 @@ urlpatterns = [
path("category", views.category, name="category"), path("category", views.category, name="category"),
path("category/<uuid>", views.category, name="category"), path("category/<uuid>", views.category, name="category"),
path("category/<uuid>/update", views.update_category, name="update_category"), path("category/<uuid>/update", views.update_category, name="update_category"),
path("snapshot", views.snapshot, name="snapshot"),
path("snapshot/<date>", views.snapshot, name="snapshot"),
path("snapshot/update/<uuid>", views.update_snapshot, name="update_snapshot"),
path("snapshot/<date>/del", views.del_snapshot, name="del_snapshot"),
] ]

View file

@ -11,6 +11,7 @@ from .models import (
Category, Category,
CategoryForm, CategoryForm,
Snapshot, Snapshot,
SnapshotForm,
) )
@ -59,10 +60,7 @@ def transaction(request, uuid=None):
@login_required @login_required
def update_transaction(request, uuid): def update_transaction(request, uuid):
try: _transaction, _ = Transaction.objects.get_or_create(id=uuid)
_transaction = Transaction.objects.get(id=uuid)
except Transaction.DoesNotExist:
_transaction = Transaction(id=uuid)
_form = TransactionForm(request.POST, instance=_transaction) _form = TransactionForm(request.POST, instance=_transaction)
_form.save() _form.save()
return redirect(transaction, uuid=uuid) return redirect(transaction, uuid=uuid)
@ -112,10 +110,38 @@ def category(request, uuid=None):
@login_required @login_required
def update_category(request, uuid): def update_category(request, uuid):
try: _category, _ = Category.objects.get_or_create(id=uuid)
_category = Category.objects.get(id=uuid)
except Category.DoesNotExist:
_category = Category(id=uuid)
_form = CategoryForm(request.POST, instance=_category) _form = CategoryForm(request.POST, instance=_category)
_form.save() _form.save()
return redirect(category, uuid=uuid) return redirect(category, uuid=uuid)
@login_required
def snapshot(request, date=None):
if date is None:
_snapshot = Snapshot()
else:
_snapshot = get_object_or_404(Snapshot, date=date)
return render(
request,
"main/snapshot.html",
{
"snapshot": _snapshot,
"form": SnapshotForm(instance=_snapshot),
},
)
@login_required
def update_snapshot(request, uuid):
_snapshot, _ = Snapshot.objects.get_or_create(id=uuid)
_form = SnapshotForm(request.POST, instance=_snapshot)
_form.save()
return redirect(snapshot, date=_snapshot.date)
@login_required
def del_snapshot(request, date):
_snapshot = get_object_or_404(Snapshot, date=date)
_snapshot.delete()
return redirect(index)