From 085cd90a7f9098cb3aca7858d648925476c7f61f Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Fri, 19 Jul 2019 15:00:44 +0200 Subject: [PATCH] Implement signals --- note/admin.py | 10 ++++++ note/apps.py | 17 +++++++++++ note/models/notes.py | 61 ++++++++++++++++++++++++------------- note/models/transactions.py | 22 +++++++++++++ note/signals.py | 23 ++++++++++++++ 5 files changed, 111 insertions(+), 22 deletions(-) create mode 100644 note/signals.py diff --git a/note/admin.py b/note/admin.py index ac17be4e..c576e121 100644 --- a/note/admin.py +++ b/note/admin.py @@ -119,6 +119,16 @@ class TransactionAdmin(admin.ModelAdmin): poly_destination.short_description = _('destination') + def get_readonly_fields(self, request, obj=None): + """ + Only valid can be edited after creation + Else the amount of money would not be transferred + """ + if obj: # user is editing an existing object + return 'created_at', 'source', 'destination', 'quantity',\ + 'amount', 'transaction_type' + return [] + @admin.register(TransactionTemplate) class TransactionTemplateAdmin(admin.ModelAdmin): diff --git a/note/apps.py b/note/apps.py index 439140b3..c53f915a 100644 --- a/note/apps.py +++ b/note/apps.py @@ -3,9 +3,26 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django.apps import AppConfig +from django.conf import settings +from django.db.models.signals import post_save from django.utils.translation import gettext_lazy as _ +from . import signals + class NoteConfig(AppConfig): name = 'note' verbose_name = _('note') + + def ready(self): + """ + Define app internal signals to interact with other apps + """ + post_save.connect( + signals.save_user_note, + sender=settings.AUTH_USER_MODEL + ) + post_save.connect( + signals.save_club_note, + sender='member.Club' + ) diff --git a/note/models/notes.py b/note/models/notes.py index 1cb34f56..4417447e 100644 --- a/note/models/notes.py +++ b/note/models/notes.py @@ -4,8 +4,6 @@ from django.conf import settings from django.db import models -from django.db.models.signals import post_save -from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ from polymorphic.models import PolymorphicModel @@ -64,6 +62,19 @@ class NoteUser(Note): def __str__(self): return _("%(user)s's note") % {'user': str(self.user)} + def save(self, *args, **kwargs): + """ + When saving, also create an alias + TODO: check availability of alias + TODO: remove old alias + """ + created = self.pk is None + if created: + alias = Alias.objects.create(name=str(self.user), note=self) + alias.save() + + super().save(*args, **kwargs) + class NoteClub(Note): """ @@ -83,6 +94,19 @@ class NoteClub(Note): def __str__(self): return _("Note for %(club)s club") % {'club': str(self.club)} + def save(self, *args, **kwargs): + """ + When saving, also create an alias + TODO: check availability of alias + TODO: remove old alias + """ + created = self.pk is None + if created: + alias = Alias.objects.create(name=str(self.club), note=self) + alias.save() + + super().save(*args, **kwargs) + class NoteSpecial(Note): """ @@ -106,6 +130,19 @@ class NoteSpecial(Note): def __str__(self): return self.special_type + def save(self, *args, **kwargs): + """ + When saving, also create an alias + TODO: check availability of alias + TODO: remove old alias + """ + created = self.pk is None + if created: + alias = Alias.objects.create(name=str(self.club), note=self) + alias.save() + + super().save(*args, **kwargs) + class Alias(models.Model): """ @@ -127,23 +164,3 @@ class Alias(models.Model): def __str__(self): return self.name - - -@receiver(post_save, sender=settings.AUTH_USER_MODEL) -def save_user_note(instance, created, **_kwargs): - """ - Hook to create and save a note when an user is updated - """ - if created: - NoteUser.objects.create(user=instance) - instance.note.save() - - -@receiver(post_save, sender='member.Club') -def save_club_note(instance, created, **_kwargs): - """ - Hook to create and save a note when a club is updated - """ - if created: - NoteClub.objects.create(club=instance) - instance.note.save() diff --git a/note/models/transactions.py b/note/models/transactions.py index c2d0135d..506908bf 100644 --- a/note/models/transactions.py +++ b/note/models/transactions.py @@ -79,6 +79,28 @@ class Transaction(models.Model): verbose_name = _("transaction") verbose_name_plural = _("transactions") + def save(self, *args, **kwargs): + """ + When saving, also transfer money between two notes + """ + created = self.pk is None + to_transfer = self.amount * self.quantity + if not created: + # Revert old transaction + old_transaction = Transaction.objects.get(pk=self.pk) + if old_transaction.valid: + self.source.balance += to_transfer + self.destination.balance -= to_transfer + + if self.valid: + self.source.balance -= to_transfer + self.destination.balance += to_transfer + + # Save notes + self.source.save() + self.destination.save() + super().save(*args, **kwargs) + class MembershipTransaction(Transaction): membership = models.OneToOneField( diff --git a/note/signals.py b/note/signals.py new file mode 100644 index 00000000..6e5d5c9e --- /dev/null +++ b/note/signals.py @@ -0,0 +1,23 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2018-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + + +def save_user_note(instance, created, **_kwargs): + """ + Hook to create and save a note when an user is updated + """ + if created: + from .models import NoteUser + NoteUser.objects.create(user=instance) + instance.note.save() + + +def save_club_note(instance, created, **_kwargs): + """ + Hook to create and save a note when a club is updated + """ + if created: + from .models import NoteClub + NoteClub.objects.create(club=instance) + instance.note.save()