From 1bfcedd4fec09f6c48f23af9231416ad5ce89a37 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss <erdnaxe@crans.org>
Date: Wed, 17 Jul 2019 12:14:23 +0200
Subject: [PATCH] Polymorphic search

---
 note/admin.py                        | 57 +++++++++++--------
 note/locale/fr/LC_MESSAGES/django.po | 84 ++++++++++++++++++----------
 note/models/notes.py                 | 12 ++++
 3 files changed, 100 insertions(+), 53 deletions(-)

diff --git a/note/admin.py b/note/admin.py
index 66623f58..8574142d 100644
--- a/note/admin.py
+++ b/note/admin.py
@@ -3,6 +3,8 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 from django.contrib import admin
+from polymorphic.admin import PolymorphicParentModelAdmin, \
+    PolymorphicChildModelAdmin, PolymorphicChildModelFilter
 
 from .models.notes import Alias, Note, NoteClub, NoteSpecial, NoteUser
 from .models.transactions import MembershipTransaction, Transaction, \
@@ -17,14 +19,32 @@ class AliasInlines(admin.TabularInline):
     model = Alias
 
 
-class NoteClubAdmin(admin.ModelAdmin):
+@admin.register(Note)
+class NoteAdmin(PolymorphicParentModelAdmin):
     """
-    Admin customisation for NoteClub
+    Parent regrouping all note types as children
+    """
+    child_models = (NoteClub, NoteSpecial, NoteUser)
+    list_filter = (PolymorphicChildModelFilter, 'is_active',)
+
+    # Use a polymorphic list
+    list_display = ('__str__', 'balance', 'is_active')
+    polymorphic_list = True
+
+    # Organize notes by registration date
+    date_hierarchy = 'created_at'
+    ordering = ['-created_at']
+
+    # Search by aliases
+    search_fields = ['alias__name']
+
+
+@admin.register(NoteClub)
+class NoteClubAdmin(PolymorphicChildModelAdmin):
+    """
+    Child for a club note, see NoteAdmin
     """
     inlines = (AliasInlines,)
-    list_display = ('club', 'balance', 'is_active')
-    list_filter = ('is_active',)
-    search_fields = ['club__name']
 
     # We can't change club after creation or the balance
     readonly_fields = ('club', 'balance')
@@ -42,25 +62,20 @@ class NoteClubAdmin(admin.ModelAdmin):
         return False
 
 
-class NoteSpecialAdmin(admin.ModelAdmin):
+@admin.register(NoteSpecial)
+class NoteSpecialAdmin(PolymorphicChildModelAdmin):
     """
-    Admin customisation for NoteSpecial
+    Child for a special note, see NoteAdmin
     """
-    list_display = ('special_type', 'balance', 'is_active')
+    readonly_fields = ('balance',)
 
 
-class NoteUserAdmin(admin.ModelAdmin):
+@admin.register(NoteUser)
+class NoteUserAdmin(PolymorphicChildModelAdmin):
     """
-    Admin customisation for NoteUser
+    Child for an user note, see NoteAdmin
     """
     inlines = (AliasInlines,)
-    list_display = ('user', 'balance', 'is_active')
-    list_filter = ('is_active',)
-    search_fields = ['user__username']
-
-    # Organize note by registration date
-    date_hierarchy = 'user__date_joined'
-    ordering = ['-user__date_joined']
 
     # We can't change user after creation or the balance
     readonly_fields = ('user', 'balance')
@@ -78,18 +93,16 @@ class NoteUserAdmin(admin.ModelAdmin):
         return False
 
 
+@admin.register(TransactionTemplate)
 class TransactionTemplateAdmin(admin.ModelAdmin):
     """
     Admin customisation for TransactionTemplate
     """
     list_display = ('name', 'destination', 'amount', 'template_type')
     list_filter = ('destination', 'template_type',)
+    # autocomplete_fields = ('destination',)
 
 
-# Register your models here.
-admin.site.register(NoteClub, NoteClubAdmin)
-admin.site.register(NoteSpecial, NoteSpecialAdmin)
-admin.site.register(NoteUser, NoteUserAdmin)
+# Register other models here.
 admin.site.register(MembershipTransaction)
 admin.site.register(Transaction)
-admin.site.register(TransactionTemplate, TransactionTemplateAdmin)
diff --git a/note/locale/fr/LC_MESSAGES/django.po b/note/locale/fr/LC_MESSAGES/django.po
index 97d5f9c7..4d9e7471 100644
--- a/note/locale/fr/LC_MESSAGES/django.po
+++ b/note/locale/fr/LC_MESSAGES/django.po
@@ -3,7 +3,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-16 15:21+0200\n"
+"POT-Creation-Date: 2019-07-17 11:51+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -13,122 +13,144 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: apps.py:11 models/notes.py:39
+#: apps.py:11 models/notes.py:41
 msgid "note"
 msgstr "note"
 
-#: models/notes.py:21
+#: models/notes.py:22
 msgid "account balance"
 msgstr "solde du compte"
 
-#: models/notes.py:22
+#: models/notes.py:23
 msgid "in centimes, money credited for this instance"
 msgstr "en centimes, argent crédité pour cette instance"
 
-#: models/notes.py:25
+#: models/notes.py:27
 msgid "active"
 msgstr "actif"
 
-#: models/notes.py:28
+#: models/notes.py:30
 msgid ""
 "Designates whether this note should be treated as active. Unselect this "
 "instead of deleting notes."
 msgstr ""
 "Indique si la note est active. Désactiver cela plutôt que supprimer la note."
 
-#: models/notes.py:33
+#: models/notes.py:35
 msgid "display image"
 msgstr "image affichée"
 
-#: models/notes.py:40
+#: models/notes.py:42
 msgid "notes"
 msgstr "notes"
 
-#: models/notes.py:54
+#: models/notes.py:53
+msgid "user"
+msgstr ""
+
+#: models/notes.py:57
 msgid "one's note"
 msgstr "note d'un utilisateur"
 
-#: models/notes.py:55
+#: models/notes.py:58
 msgid "users note"
 msgstr "notes des utilisateurs"
 
-#: models/notes.py:69
+#: models/notes.py:61
+#, python-format
+msgid "%(user)s's note"
+msgstr "Note de %(user)s"
+
+#: models/notes.py:72
+msgid "club"
+msgstr "club"
+
+#: models/notes.py:76
 msgid "club note"
 msgstr "note d'un club"
 
-#: models/notes.py:70
+#: models/notes.py:77
 msgid "clubs notes"
 msgstr "notes des clubs"
 
-#: models/notes.py:83 models/transactions.py:31 models/transactions.py:64
+#: models/notes.py:80
+#, python-format
+msgid "Note for %(club)s club"
+msgstr "Note du club %(club)s"
+
+#: models/notes.py:93 models/transactions.py:32 models/transactions.py:65
 msgid "type"
 msgstr "type"
 
-#: models/notes.py:89
+#: models/notes.py:99
 msgid "special note"
 msgstr "note spéciale"
 
-#: models/notes.py:90
+#: models/notes.py:100
 msgid "special notes"
 msgstr "notes spéciales"
 
-#: models/notes.py:98 models/transactions.py:18
+#: models/notes.py:111 models/transactions.py:18
 msgid "name"
 msgstr "nom"
 
-#: models/notes.py:108
+#: models/notes.py:121
 msgid "alias"
 msgstr "alias"
 
-#: models/notes.py:109
+#: models/notes.py:122
 msgid "aliases"
 msgstr "alias"
 
-#: models/transactions.py:25 models/transactions.py:51
-#: models/transactions.py:54
+#: models/transactions.py:25 models/transactions.py:52
+#: models/transactions.py:55
 msgid "destination"
 msgstr "destination"
 
-#: models/transactions.py:28 models/transactions.py:61
+#: models/transactions.py:28 models/transactions.py:62
 msgid "amount"
 msgstr "montant"
 
-#: models/transactions.py:36
+#: models/transactions.py:29
+msgid "in centimes"
+msgstr "en centimes"
+
+#: models/transactions.py:37
 msgid "transaction template"
 msgstr "modèle de transaction"
 
-#: models/transactions.py:37
+#: models/transactions.py:38
 msgid "transaction templates"
 msgstr "modèles de transaction"
 
-#: models/transactions.py:45
+#: models/transactions.py:46
 msgid "source"
 msgstr "source"
 
-#: models/transactions.py:58
+#: models/transactions.py:59
 msgid "quantity"
 msgstr "quantité"
 
-#: models/transactions.py:68
+#: models/transactions.py:69
 msgid "description"
 msgstr "description"
 
-#: models/transactions.py:71
+#: models/transactions.py:72
 msgid "valid"
 msgstr "valide"
 
-#: models/transactions.py:75
+#: models/transactions.py:76
 msgid "transaction"
 msgstr "transaction"
 
-#: models/transactions.py:76
+#: models/transactions.py:77
 msgid "transactions"
 msgstr "transactions"
 
-#: models/transactions.py:87
+#: models/transactions.py:88
 msgid "membership transaction"
 msgstr "transaction d'adhésion"
 
-#: models/transactions.py:88
+#: models/transactions.py:89
 msgid "membership transactions"
 msgstr "transactions d'adhésion"
diff --git a/note/models/notes.py b/note/models/notes.py
index 67965a7b..21ea8e2e 100644
--- a/note/models/notes.py
+++ b/note/models/notes.py
@@ -36,6 +36,10 @@ class Note(PolymorphicModel):
         max_length=255,
         blank=True,
     )
+    created_at = models.DateTimeField(
+        verbose_name=_('created at'),
+        auto_now_add=True,
+    )
 
     class Meta:
         verbose_name = _("note")
@@ -50,6 +54,7 @@ class NoteUser(Note):
         settings.AUTH_USER_MODEL,
         on_delete=models.PROTECT,
         related_name='note',
+        verbose_name=_('user'),
     )
 
     class Meta:
@@ -68,12 +73,16 @@ class NoteClub(Note):
         'member.Club',
         on_delete=models.PROTECT,
         related_name='note',
+        verbose_name=_('club'),
     )
 
     class Meta:
         verbose_name = _("club note")
         verbose_name_plural = _("clubs notes")
 
+    def __str__(self):
+        return _("Note for %(club)s club") % {'club': str(self.club)}
+
 
 class NoteSpecial(Note):
     """
@@ -94,6 +103,9 @@ class NoteSpecial(Note):
         verbose_name = _("special note")
         verbose_name_plural = _("special notes")
 
+    def __str__(self):
+        return self.special_type
+
 
 class Alias(models.Model):
     """
-- 
GitLab