diff --git a/nummi/main/migrations/0013_account_snapshot_account_transaction_account.py b/nummi/main/migrations/0013_account_snapshot_account_transaction_account.py new file mode 100644 index 0000000..d4a0e82 --- /dev/null +++ b/nummi/main/migrations/0013_account_snapshot_account_transaction_account.py @@ -0,0 +1,80 @@ +# Generated by Django 4.1.4 on 2022-12-29 18:32 + +import uuid + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("main", "0012_alter_snapshot_date"), + ] + + operations = [ + migrations.CreateModel( + name="Account", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField( + default="Account", max_length=64, verbose_name="Nom" + ), + ), + ( + "icon", + models.CharField( + default="folder", max_length=64, verbose_name="IcĂ´ne" + ), + ), + ( + "user", + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + ), + ], + options={ + "verbose_name": "Account", + "verbose_name_plural": "Accounts", + "ordering": ["name"], + }, + ), + migrations.AddField( + model_name="snapshot", + name="account", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="main.account", + verbose_name="Account", + ), + ), + migrations.AddField( + model_name="transaction", + name="account", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="main.account", + verbose_name="Account", + ), + ), + ] diff --git a/nummi/main/models.py b/nummi/main/models.py index f9d25f7..8e86065 100644 --- a/nummi/main/models.py +++ b/nummi/main/models.py @@ -2,12 +2,12 @@ import pathlib import uuid from datetime import date +from django.contrib.auth.models import User from django.core.validators import FileExtensionValidator from django.db import models from django.forms import ModelForm from django.urls import reverse from django.utils.translation import gettext as _ -from django.contrib.auth.models import User class UserModel(models.Model): @@ -19,7 +19,57 @@ class UserModel(models.Model): abstract = True -class Category(UserModel): +class CustomModel(UserModel): + @property + def adding(self): + return self._state.adding + + class Meta: + abstract = True + + +class Account(CustomModel): + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + name = models.CharField(max_length=64, default=_("Account"), verbose_name=_("Name")) + icon = models.CharField(max_length=64, default="folder", verbose_name=_("Icon")) + + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse("account", kwargs={"pk": self.pk}) + + def get_delete_url(self): + return reverse("del_account", kwargs={"pk": self.pk}) + + @property + def transactions(self): + return Transaction.objects.filter(account=self) + + @property + def snapshots(self): + return Snapshot.objects.filter(account=self) + + class Meta: + ordering = ["name"] + verbose_name = _("Account") + verbose_name_plural = _("Accounts") + + +class AccountModel(CustomModel): + account = models.ForeignKey( + Account, + on_delete=models.SET_NULL, + blank=True, + null=True, + verbose_name=_("Account"), + ) + + class Meta: + abstract = True + + +class Category(CustomModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField( max_length=64, default=_("Category"), verbose_name=_("Name") @@ -36,10 +86,6 @@ class Category(UserModel): def get_delete_url(self): return reverse("del_category", kwargs={"pk": self.pk}) - @property - def adding(self): - return self._state.adding - @property def transactions(self): return Transaction.objects.filter(category=self) @@ -50,15 +96,7 @@ class Category(UserModel): verbose_name_plural = _("Categories") -class CategoryForm(ModelForm): - template_name = "main/form/base.html" - - class Meta: - model = Category - fields = ["name", "icon", "budget"] - - -class Transaction(UserModel): +class Transaction(AccountModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField( max_length=256, default=_("Transaction"), verbose_name=_("Name") @@ -92,10 +130,6 @@ class Transaction(UserModel): def get_delete_url(self): return reverse("del_transaction", kwargs={"pk": self.pk}) - @property - def adding(self): - return self._state.adding - @property def invoices(self): return Invoice.objects.filter(transaction=self) @@ -110,28 +144,11 @@ class Transaction(UserModel): verbose_name_plural = _("Transactions") -class TransactionForm(ModelForm): - template_name = "main/form/base.html" - - class Meta: - model = Transaction - fields = [ - "date", - "name", - "value", - "trader", - "category", - "real_date", - "payment", - "description", - ] - - def invoice_path(instance, filename): return pathlib.Path("invoices", str(instance.id)).with_suffix(".pdf") -class Invoice(UserModel): +class Invoice(CustomModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField( max_length=256, default=_("Invoice"), verbose_name=_("Name") @@ -165,29 +182,16 @@ class Invoice(UserModel): "del_invoice", kwargs={"transaction_pk": self.transaction.pk, "pk": self.pk} ) - @property - def adding(self): - return self._state.adding - class Meta: verbose_name = _("Invoice") verbose_name_plural = _("Invoices") -class InvoiceForm(ModelForm): - template_name = "main/form/base.html" - prefix = "invoice" - - class Meta: - model = Invoice - fields = "__all__" - - def snapshot_path(instance, filename): return pathlib.Path("snapshots", str(instance.id)).with_suffix(".pdf") -class Snapshot(UserModel): +class Snapshot(AccountModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) date = models.DateField(default=date.today, verbose_name=_("Date")) value = models.DecimalField( @@ -284,10 +288,6 @@ class Snapshot(UserModel): def get_delete_url(self): return reverse("del_snapshot", kwargs={"pk": self.pk}) - @property - def adding(self): - return self._state.adding - @property def sum(self): if self.previous is None: @@ -327,9 +327,37 @@ class Snapshot(UserModel): verbose_name_plural = _("Snapshots") -class SnapshotForm(ModelForm): +class NummiForm(ModelForm): template_name = "main/form/base.html" + +class AccountForm(NummiForm): + class Meta: + model = Account + fields = "__all__" + + +class CategoryForm(NummiForm): + class Meta: + model = Category + fields = "__all__" + + +class TransactionForm(NummiForm): + class Meta: + model = Transaction + fields = "__all__" + + +class InvoiceForm(NummiForm): + prefix = "invoice" + + class Meta: + model = Invoice + fields = "__all__" + + +class SnapshotForm(NummiForm): class Meta: model = Snapshot - fields = ["date", "value", "file"] + fields = "__all__" diff --git a/nummi/main/templates/main/account_form.html b/nummi/main/templates/main/account_form.html new file mode 100644 index 0000000..ce55c42 --- /dev/null +++ b/nummi/main/templates/main/account_form.html @@ -0,0 +1,22 @@ +{% extends "main/base.html" %} +{% load static %} +{% load main_extras %} +{% load i18n %} +{% block link %} + {{ block.super }} + + +{% endblock %} +{% block body %} +