diff --git a/nummi/main/migrations/0010_category_user_invoice_user_snapshot_user_and_more.py b/nummi/main/migrations/0010_category_user_invoice_user_snapshot_user_and_more.py new file mode 100644 index 0000000..26c3d88 --- /dev/null +++ b/nummi/main/migrations/0010_category_user_invoice_user_snapshot_user_and_more.py @@ -0,0 +1,60 @@ +# Generated by Django 4.1.4 on 2022-12-29 18:03 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("main", "0009_alter_invoice_file_alter_invoice_transaction_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="category", + name="user", + field=models.ForeignKey( + default=1, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + preserve_default=False, + ), + migrations.AddField( + model_name="invoice", + name="user", + field=models.ForeignKey( + default=1, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + preserve_default=False, + ), + migrations.AddField( + model_name="snapshot", + name="user", + field=models.ForeignKey( + default=1, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + preserve_default=False, + ), + migrations.AddField( + model_name="transaction", + name="user", + field=models.ForeignKey( + default=1, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + preserve_default=False, + ), + ] diff --git a/nummi/main/migrations/0011_alter_category_user_alter_invoice_user_and_more.py b/nummi/main/migrations/0011_alter_category_user_alter_invoice_user_and_more.py new file mode 100644 index 0000000..823cfa0 --- /dev/null +++ b/nummi/main/migrations/0011_alter_category_user_alter_invoice_user_and_more.py @@ -0,0 +1,56 @@ +# Generated by Django 4.1.4 on 2022-12-29 18:14 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("main", "0010_category_user_invoice_user_snapshot_user_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="category", + name="user", + field=models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + ), + migrations.AlterField( + model_name="invoice", + name="user", + field=models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + ), + migrations.AlterField( + model_name="snapshot", + name="user", + field=models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + ), + migrations.AlterField( + model_name="transaction", + name="user", + field=models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + verbose_name="Utilisateur", + ), + ), + ] diff --git a/nummi/main/models.py b/nummi/main/models.py index 06a4e4c..cf392f2 100644 --- a/nummi/main/models.py +++ b/nummi/main/models.py @@ -7,9 +7,19 @@ 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 Category(models.Model): +class UserModel(models.Model): + user = models.ForeignKey( + User, on_delete=models.CASCADE, verbose_name=_("User"), editable=False + ) + + class Meta: + abstract = True + + +class Category(UserModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField( max_length=64, default=_("Category"), verbose_name=_("Name") @@ -48,7 +58,7 @@ class CategoryForm(ModelForm): fields = ["name", "icon", "budget"] -class Transaction(models.Model): +class Transaction(UserModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField( max_length=256, default=_("Transaction"), verbose_name=_("Name") @@ -121,7 +131,7 @@ def invoice_path(instance, filename): return pathlib.Path("invoices", str(instance.id)).with_suffix(".pdf") -class Invoice(models.Model): +class Invoice(UserModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField( max_length=256, default=_("Invoice"), verbose_name=_("Name") @@ -177,7 +187,7 @@ def snapshot_path(instance, filename): return pathlib.Path("snapshots", str(instance.id)).with_suffix(".pdf") -class Snapshot(models.Model): +class Snapshot(UserModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) date = models.DateField(default=date.today, unique=True, verbose_name=_("Date")) value = models.DecimalField( diff --git a/nummi/main/tests.py b/nummi/main/tests.py index 4929020..a39b155 100644 --- a/nummi/main/tests.py +++ b/nummi/main/tests.py @@ -1,2 +1 @@ - # Create your tests here. diff --git a/nummi/main/views.py b/nummi/main/views.py index 4430392..8e5cd72 100644 --- a/nummi/main/views.py +++ b/nummi/main/views.py @@ -35,12 +35,23 @@ class IndexView(LoginRequiredMixin, TemplateView): def get_context_data(self, **kwargs): return super().get_context_data(**kwargs) | { - "transactions": Transaction.objects.all()[:10], - "categories": Category.objects.all(), - "snapshots": Snapshot.objects.all(), + "transactions": Transaction.objects.filter(user=self.request.user)[:10], + "categories": Category.objects.filter(user=self.request.user), + "snapshots": Snapshot.objects.filter(user=self.request.user), } +class UserMixin(LoginRequiredMixin): + def get_queryset(self, **kwargs): + return super().get_queryset().filter(user=self.request.user) + + +class UserCreateView(LoginRequiredMixin, CreateView): + def form_valid(self, form): + form.instance.user = self.request.user + return super().form_valid(form) + + class LoginView(auth_views.LoginView): template_name = "main/login.html" next_page = "index" @@ -50,25 +61,26 @@ class LogoutView(auth_views.LogoutView): next_page = "login" -class TransactionListView(LoginRequiredMixin, ListView): +class TransactionListView(UserMixin, ListView): paginate_by = 24 model = Transaction template_name = "main/transactions.html" context_object_name = "transactions" -class TransactionCreateView(LoginRequiredMixin, CreateView): +class TransactionCreateView(UserCreateView): model = Transaction form_class = TransactionForm -class InvoiceCreateView(LoginRequiredMixin, CreateView): +class InvoiceCreateView(UserCreateView): model = Invoice form_class = InvoiceForm def form_valid(self, form): form.instance.transaction = get_object_or_404( - Transaction, pk=self.kwargs["transaction_pk"] + Transaction.objects.filter(user=self.request.user), + pk=self.kwargs["transaction_pk"], ) return super().form_valid(form) @@ -76,22 +88,22 @@ class InvoiceCreateView(LoginRequiredMixin, CreateView): return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk}) -class CategoryCreateView(LoginRequiredMixin, CreateView): +class CategoryCreateView(UserCreateView): model = Category form_class = CategoryForm -class SnapshotCreateView(LoginRequiredMixin, CreateView): +class SnapshotCreateView(UserCreateView): model = Snapshot form_class = SnapshotForm -class TransactionUpdateView(LoginRequiredMixin, UpdateView): +class TransactionUpdateView(UserMixin, UpdateView): model = Transaction form_class = TransactionForm -class InvoiceUpdateView(LoginRequiredMixin, UpdateView): +class InvoiceUpdateView(UserMixin, UpdateView): model = Invoice form_class = InvoiceForm @@ -99,28 +111,34 @@ class InvoiceUpdateView(LoginRequiredMixin, UpdateView): return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk}) def get_queryset(self): - return Invoice.objects.filter( - transaction=get_object_or_404(Transaction, pk=self.kwargs["transaction_pk"]) + return ( + super() + .get_queryset() + .filter( + transaction=get_object_or_404( + Transaction, pk=self.kwargs["transaction_pk"] + ) + ) ) -class CategoryUpdateView(LoginRequiredMixin, UpdateView): +class CategoryUpdateView(UserMixin, UpdateView): model = Category form_class = CategoryForm -class SnapshotUpdateView(LoginRequiredMixin, UpdateView): +class SnapshotUpdateView(UserMixin, UpdateView): model = Snapshot form_class = SnapshotForm -class TransactionDeleteView(LoginRequiredMixin, DeleteView): +class TransactionDeleteView(UserMixin, DeleteView): model = Transaction template_name = "main/confirm_delete.html" success_url = reverse_lazy("index") -class InvoiceDeleteView(LoginRequiredMixin, DeleteView): +class InvoiceDeleteView(UserMixin, DeleteView): model = Invoice template_name = "main/confirm_delete.html" @@ -128,24 +146,24 @@ class InvoiceDeleteView(LoginRequiredMixin, DeleteView): return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk}) def get_queryset(self): - return Invoice.objects.filter( + return super.get_queryset().filter( transaction=get_object_or_404(Transaction, pk=self.kwargs["transaction_pk"]) ) -class CategoryDeleteView(LoginRequiredMixin, DeleteView): +class CategoryDeleteView(UserMixin, DeleteView): model = Category template_name = "main/confirm_delete.html" success_url = reverse_lazy("index") -class SnapshotDeleteView(LoginRequiredMixin, DeleteView): +class SnapshotDeleteView(UserMixin, DeleteView): model = Snapshot template_name = "main/confirm_delete.html" success_url = reverse_lazy("index") -class SearchView(LoginRequiredMixin, ListView, ProcessFormView): +class SearchView(UserMixin, ListView, ProcessFormView): paginate_by = 24 model = Transaction template_name = "main/transactions.html" @@ -157,7 +175,9 @@ class SearchView(LoginRequiredMixin, ListView, ProcessFormView): def get_queryset(self): self.search = self.kwargs["search"] return ( - Transaction.objects.annotate( + super() + .get_queryset() + .annotate( rank=SearchRank( SearchVector("name", weight="A") + SearchVector("description", weight="B")