Compare commits

..

2 commits

Author SHA1 Message Date
7d0ed1dd5a
Fix unique date field on snapshots 2022-12-29 19:22:38 +01:00
2ac316aaca
Add User field to models
Support for multiple users !
2022-12-29 19:20:52 +01:00
6 changed files with 192 additions and 28 deletions

View file

@ -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,
),
]

View file

@ -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",
),
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2022-12-29 18:22
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("main", "0011_alter_category_user_alter_invoice_user_and_more"),
]
operations = [
migrations.AlterField(
model_name="snapshot",
name="date",
field=models.DateField(default=datetime.date.today, verbose_name="Date"),
),
]

View file

@ -7,9 +7,19 @@ from django.db import models
from django.forms import ModelForm from django.forms import ModelForm
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext as _ 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) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField( name = models.CharField(
max_length=64, default=_("Category"), verbose_name=_("Name") max_length=64, default=_("Category"), verbose_name=_("Name")
@ -48,7 +58,7 @@ class CategoryForm(ModelForm):
fields = ["name", "icon", "budget"] fields = ["name", "icon", "budget"]
class Transaction(models.Model): class Transaction(UserModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField( name = models.CharField(
max_length=256, default=_("Transaction"), verbose_name=_("Name") 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") 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) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField( name = models.CharField(
max_length=256, default=_("Invoice"), verbose_name=_("Name") max_length=256, default=_("Invoice"), verbose_name=_("Name")
@ -177,9 +187,9 @@ def snapshot_path(instance, filename):
return pathlib.Path("snapshots", str(instance.id)).with_suffix(".pdf") 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) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
date = models.DateField(default=date.today, unique=True, verbose_name=_("Date")) date = models.DateField(default=date.today, verbose_name=_("Date"))
value = models.DecimalField( value = models.DecimalField(
max_digits=12, decimal_places=2, default=0, verbose_name=_("Value") max_digits=12, decimal_places=2, default=0, verbose_name=_("Value")
) )

View file

@ -1,2 +1 @@
# Create your tests here. # Create your tests here.

View file

@ -35,12 +35,23 @@ class IndexView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | { return super().get_context_data(**kwargs) | {
"transactions": Transaction.objects.all()[:10], "transactions": Transaction.objects.filter(user=self.request.user)[:10],
"categories": Category.objects.all(), "categories": Category.objects.filter(user=self.request.user),
"snapshots": Snapshot.objects.all(), "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): class LoginView(auth_views.LoginView):
template_name = "main/login.html" template_name = "main/login.html"
next_page = "index" next_page = "index"
@ -50,25 +61,26 @@ class LogoutView(auth_views.LogoutView):
next_page = "login" next_page = "login"
class TransactionListView(LoginRequiredMixin, ListView): class TransactionListView(UserMixin, ListView):
paginate_by = 24 paginate_by = 24
model = Transaction model = Transaction
template_name = "main/transactions.html" template_name = "main/transactions.html"
context_object_name = "transactions" context_object_name = "transactions"
class TransactionCreateView(LoginRequiredMixin, CreateView): class TransactionCreateView(UserCreateView):
model = Transaction model = Transaction
form_class = TransactionForm form_class = TransactionForm
class InvoiceCreateView(LoginRequiredMixin, CreateView): class InvoiceCreateView(UserCreateView):
model = Invoice model = Invoice
form_class = InvoiceForm form_class = InvoiceForm
def form_valid(self, form): def form_valid(self, form):
form.instance.transaction = get_object_or_404( 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) return super().form_valid(form)
@ -76,22 +88,22 @@ class InvoiceCreateView(LoginRequiredMixin, CreateView):
return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk}) return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk})
class CategoryCreateView(LoginRequiredMixin, CreateView): class CategoryCreateView(UserCreateView):
model = Category model = Category
form_class = CategoryForm form_class = CategoryForm
class SnapshotCreateView(LoginRequiredMixin, CreateView): class SnapshotCreateView(UserCreateView):
model = Snapshot model = Snapshot
form_class = SnapshotForm form_class = SnapshotForm
class TransactionUpdateView(LoginRequiredMixin, UpdateView): class TransactionUpdateView(UserMixin, UpdateView):
model = Transaction model = Transaction
form_class = TransactionForm form_class = TransactionForm
class InvoiceUpdateView(LoginRequiredMixin, UpdateView): class InvoiceUpdateView(UserMixin, UpdateView):
model = Invoice model = Invoice
form_class = InvoiceForm form_class = InvoiceForm
@ -99,28 +111,34 @@ class InvoiceUpdateView(LoginRequiredMixin, UpdateView):
return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk}) return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk})
def get_queryset(self): def get_queryset(self):
return Invoice.objects.filter( return (
transaction=get_object_or_404(Transaction, pk=self.kwargs["transaction_pk"]) 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 model = Category
form_class = CategoryForm form_class = CategoryForm
class SnapshotUpdateView(LoginRequiredMixin, UpdateView): class SnapshotUpdateView(UserMixin, UpdateView):
model = Snapshot model = Snapshot
form_class = SnapshotForm form_class = SnapshotForm
class TransactionDeleteView(LoginRequiredMixin, DeleteView): class TransactionDeleteView(UserMixin, DeleteView):
model = Transaction model = Transaction
template_name = "main/confirm_delete.html" template_name = "main/confirm_delete.html"
success_url = reverse_lazy("index") success_url = reverse_lazy("index")
class InvoiceDeleteView(LoginRequiredMixin, DeleteView): class InvoiceDeleteView(UserMixin, DeleteView):
model = Invoice model = Invoice
template_name = "main/confirm_delete.html" template_name = "main/confirm_delete.html"
@ -128,24 +146,24 @@ class InvoiceDeleteView(LoginRequiredMixin, DeleteView):
return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk}) return reverse_lazy("transaction", kwargs={"pk": self.object.transaction.pk})
def get_queryset(self): def get_queryset(self):
return Invoice.objects.filter( return super.get_queryset().filter(
transaction=get_object_or_404(Transaction, pk=self.kwargs["transaction_pk"]) transaction=get_object_or_404(Transaction, pk=self.kwargs["transaction_pk"])
) )
class CategoryDeleteView(LoginRequiredMixin, DeleteView): class CategoryDeleteView(UserMixin, DeleteView):
model = Category model = Category
template_name = "main/confirm_delete.html" template_name = "main/confirm_delete.html"
success_url = reverse_lazy("index") success_url = reverse_lazy("index")
class SnapshotDeleteView(LoginRequiredMixin, DeleteView): class SnapshotDeleteView(UserMixin, DeleteView):
model = Snapshot model = Snapshot
template_name = "main/confirm_delete.html" template_name = "main/confirm_delete.html"
success_url = reverse_lazy("index") success_url = reverse_lazy("index")
class SearchView(LoginRequiredMixin, ListView, ProcessFormView): class SearchView(UserMixin, ListView, ProcessFormView):
paginate_by = 24 paginate_by = 24
model = Transaction model = Transaction
template_name = "main/transactions.html" template_name = "main/transactions.html"
@ -157,7 +175,9 @@ class SearchView(LoginRequiredMixin, ListView, ProcessFormView):
def get_queryset(self): def get_queryset(self):
self.search = self.kwargs["search"] self.search = self.kwargs["search"]
return ( return (
Transaction.objects.annotate( super()
.get_queryset()
.annotate(
rank=SearchRank( rank=SearchRank(
SearchVector("name", weight="A") SearchVector("name", weight="A")
+ SearchVector("description", weight="B") + SearchVector("description", weight="B")