Parcourir la source

amélioration gestion des adhésions

Élie Bouttier il y a 7 ans
Parent
commit
7807a56f19

+ 1 - 15
accounts/models.py

@@ -1,5 +1,4 @@
 from django.db import models
 from django.db import models
-from django.contrib.contenttypes.models import ContentType
 from django.urls import reverse
 from django.urls import reverse
 
 
 
 
@@ -18,21 +17,8 @@ class Profile(models.Model):
         verbose_name = 'profil'
         verbose_name = 'profil'
 
 
     @property
     @property
-    def adhesion(self): # user adhesion
-        ctype = ContentType.objects.get_for_model(User)
-        try:
-            return Adhesion.objects.get(adherent_type=ctype, adherent_id=self.user.pk)
-        except Adhesion.DoesNotExist:
-            return None
-
-    @property
     def adhesions(self): # user and corporations (for which the user is a member) adhesions
     def adhesions(self): # user and corporations (for which the user is a member) adhesions
-        user_type = ContentType.objects.get_for_model(User)
-        corp_type = ContentType.objects.get_for_model(Corporation)
-        return Adhesion.objects.filter(
-            models.Q(adherent_type=user_type, adherent_id=self.user.pk)
-            | models.Q(adherent_type=corp_type, adherent_id__in=Corporation.objects.filter(members=self.user).values_list('pk'))
-        )
+        return Adhesion.objects.filter(models.Q(user__pk=self.user.pk) | models.Q(corporation__members__profile__pk=self.pk))
 
 
     def __str__(self):
     def __str__(self):
         return self.user.get_full_name() or self.user.username
         return self.user.get_full_name() or self.user.username

+ 113 - 118
adhesions/admin.py

@@ -6,29 +6,28 @@ from django.contrib.auth.models import User as AuthUser, Group
 from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
 from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
 from django.http import HttpResponseRedirect
 from django.http import HttpResponseRedirect
 
 
-from .forms import AdhesionForm, UserCreationForm
+from .forms import UserCreationForm
 from .models import User, Corporation, Adhesion
 from .models import User, Corporation, Adhesion
 from accounts.models import Profile
 from accounts.models import Profile
 from services.models import Service
 from services.models import Service
 from banking.admin import PaymentInline
 from banking.admin import PaymentInline
 
 
 
 
-class AdhesionInline(GenericTabularInline):
-    model = Adhesion
-    ct_field = 'adherent_type'
-    ct_fk_field = 'adherent_id'
-    form = AdhesionForm
-    min_num = 1
-    max_num = 1
-    extra = 0
-    show_change_link = True
+### Inlines
+
+class ProfileInline(admin.StackedInline):
+    model = Profile
+
+    def has_add_permission(self, request):
+        return False
 
 
     def has_delete_permission(self, request, obj=None):
     def has_delete_permission(self, request, obj=None):
         return False
         return False
 
 
 
 
-class ProfileInline(admin.StackedInline):
-    model = Profile
+class AdhesionInline(admin.StackedInline):
+    model = Adhesion
+    fields = ('id', 'active', 'notes',)
 
 
     def has_add_permission(self, request):
     def has_add_permission(self, request):
         return False
         return False
@@ -51,50 +50,79 @@ class ServiceInline(admin.StackedInline):
         return False
         return False
 
 
 
 
-class UserIsAdherentFilter(admin.SimpleListFilter):
-    title = 'status adhérent'
-    parameter_name = 'adherent'
+### Filters
+
+class AdherentTypeFilter(admin.SimpleListFilter):
+    title = 'type d’adhérent'
+    parameter_name = 'type'
 
 
     def lookups(self, request, model_admin):
     def lookups(self, request, model_admin):
         return (
         return (
-            ('1', 'Oui'),
-            ('0', 'Non'),
+            ('physique', 'Personne physique'),
+            ('morale', 'Personne morale'),
         )
         )
 
 
     def queryset(self, request, queryset):
     def queryset(self, request, queryset):
-        adhesion_list = Adhesion.objects.values_list('adherent_id')
-        if self.value() == '0':
-            return queryset.exclude(pk__in=adhesion_list)
-        if self.value() == '1':
-            return queryset.filter(pk__in=adhesion_list)
+        if self.value() == 'physique':
+            return queryset.filter(user__isnull=False)
+        if self.value() == 'morale':
+            return queryset.filter(corporation__isnull=False)
+
+
+### Mixins
+
+class AdtSearchMixin:
+    adhesion_search_field = 'id'
+
+    def get_search_results(self, request, queryset, search_term):
+        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
+        if search_term[:3] == 'ADT':
+            try:
+                adh_id = int(search_term[3:])
+            except ValueError:
+                pass
+            else:
+                queryset |= self.model.objects.filter(**{self.adhesion_search_field: adh_id})
+        return queryset, use_distinct
+
 
 
+### ModelAdmin
 
 
-class UserAdmin(AuthUserAdmin):
+class UserAdmin(AdtSearchMixin, AuthUserAdmin):
     list_display = AuthUserAdmin.list_display + ('get_adhesion_link',)
     list_display = AuthUserAdmin.list_display + ('get_adhesion_link',)
-    list_filter = AuthUserAdmin.list_filter + (UserIsAdherentFilter,)
+    list_select_related = ('profile', 'adhesion',)
+    ordering = ('adhesion__id',)
+    search_fields = AuthUserAdmin.search_fields + ('=adhesion__id', 'adhesion__notes',)
     readonly_fields = ('get_adhesion_link',)
     readonly_fields = ('get_adhesion_link',)
+    adhesion_search_field = 'adhesion__id'
 
 
-    def get_adhesion_link(self, user):
-        adhesion = user.adhesion
-        if adhesion:
-            return adhesion.get_adhesion_link()
-    get_adhesion_link.short_description = 'Numéro d’adhérent'
+    def get_adhesion_id(self, user):
+        return user.adhesion
+    get_adhesion_id.short_description = 'Numéro d’adhérent'
+    get_adhesion_id.admin_order_field = 'adhesion__id'
+
+    get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
+    get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
+
+    def get_inline_instances(self, request, obj=None):
+        if obj:
+            inlines = (ProfileInline, AdhesionInline,)
+        else:
+            inlines = ()
+        return [inline(self.model, self.admin_site) for inline in inlines]
 
 
     def get_form(self, request, obj=None, **kwargs):
     def get_form(self, request, obj=None, **kwargs):
         if obj:
         if obj:
-            if obj.profile.adhesion:
-                UserAdmin.inlines = (ProfileInline,)
-            else:
-                UserAdmin.inlines = (ProfileInline, AdhesionInline,)
             return super().get_form(request, obj, **kwargs)
             return super().get_form(request, obj, **kwargs)
         else:
         else:
-            UserAdmin.inlines = (AdhesionInline,)
             return UserCreationForm
             return UserCreationForm
 
 
     def get_fieldsets(self, request, obj=None):
     def get_fieldsets(self, request, obj=None):
         if obj:
         if obj:
             fieldsets = (
             fieldsets = (
-                AuthUserAdmin.fieldsets[1],
+                (AuthUserAdmin.fieldsets[1][0], {
+                    'fields': ('get_adhesion_link',) + AuthUserAdmin.fieldsets[1][1]['fields'],
+                }),
                 ('Nom d’utilisateur et mot de passe', {
                 ('Nom d’utilisateur et mot de passe', {
                     'classes': ('collapse',),
                     'classes': ('collapse',),
                     'fields': AuthUserAdmin.fieldsets[0][1]['fields'],
                     'fields': AuthUserAdmin.fieldsets[0][1]['fields'],
@@ -108,16 +136,10 @@ class UserAdmin(AuthUserAdmin):
                     'fields': AuthUserAdmin.fieldsets[3][1]['fields'],
                     'fields': AuthUserAdmin.fieldsets[3][1]['fields'],
                 }),
                 }),
             )
             )
-            if obj.profile.adhesion:
-                fieldsets = (
-                    (None, {
-                        'fields': ('get_adhesion_link',),
-                    }),
-                ) + fieldsets
         else:
         else:
             fieldsets = (
             fieldsets = (
                 (None, {
                 (None, {
-                    'fields': ('first_name', 'last_name', 'username',),
+                    'fields': ('first_name', 'last_name', 'username', 'email',),
                 }),
                 }),
             )
             )
         return fieldsets
         return fieldsets
@@ -132,52 +154,29 @@ class UserAdmin(AuthUserAdmin):
         return obj and not obj.adhesion
         return obj and not obj.adhesion
 
 
 
 
-class AdherentTypeFilter(admin.SimpleListFilter):
-    title = 'type d’adhérent'
-    parameter_name = 'type'
-
-    def lookups(self, request, model_admin):
-        return (
-            ('physique', 'Personne physique'),
-            ('morale', 'Personne morale'),
-        )
-
-    def queryset(self, request, queryset):
-        if self.value() == 'physique':
-            return queryset.filter(adherent_type__app_label='auth',
-                                   adherent_type__model='user')
-        if self.value() == 'morale':
-            return queryset.filter(adherent_type__app_label='adhesions',
-                                   adherent_type__model='corporation')
-
+class CorporationAdmin(AdtSearchMixin, admin.ModelAdmin):
+    list_display = ('social_reason', 'get_adhesion_link',)
+    list_select_related = ('adhesion',)
+    ordering = ('adhesion__id',)
+    search_fields = ('social_reason', 'description', 'email', 'phone_number', 'address', 'notes', 'adhesion__id', 'adhesion__notes',)
+    readonly_fields = ('get_adhesion_link',)
+    filter_horizontal = ('members',)
+    adhesion_search_field = 'adhesion__id'
 
 
-class AdhesionAdmin(admin.ModelAdmin):
-    list_display = ('get_id', 'type', 'get_adherent_link', 'active')
-    list_filter = (AdherentTypeFilter, 'active',)
-    fields = ('id', 'type', 'get_adherent_link', 'active', 'notes')
-    readonly_fields = ('id', 'type', 'get_adherent_link',)
-    search_fields = ('=id', 'notes',)
-    inlines = (ServiceInline,)#PaymentInline,)
+    def get_adhesion_id(self, corp):
+        return corp.adhesion
+    get_adhesion_id.short_description = 'Numéro d’adhérent'
+    get_adhesion_id.admin_order_field = 'adhesion__id'
 
 
-    def get_id(self, obj):
-        return 'ADT%d' % obj.id
-    get_id.short_description = 'Numéro d’adhérent'
+    get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
+    get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
 
 
-    def get_search_results(self, request, queryset, search_term):
-        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
-        users = User.objects.filter(
-                    Q(username__icontains=search_term)
-                    | Q(first_name__icontains=search_term)
-                    | Q(last_name__icontains=search_term)
-        )
-        user_type = ContentType.objects.get_for_model(User)
-        queryset |= Adhesion.objects.filter(adherent_type=user_type,
-                                            adherent_id__in=users.values_list('pk'))
-        corporations = Corporation.objects.filter(social_reason__icontains=search_term)
-        corporation_type = ContentType.objects.get_for_model(Corporation)
-        queryset |= Adhesion.objects.filter(adherent_type=corporation_type,
-                                            adherent_id__in=corporations.values_list('pk'))
-        return queryset, use_distinct
+    def get_inline_instances(self, request, obj=None):
+        if obj:
+            inlines = (AdhesionInline,)
+        else:
+            inlines = ()
+        return [inline(self.model, self.admin_site) for inline in inlines]
 
 
     def get_actions(self, request):
     def get_actions(self, request):
         actions = super().get_actions(request)
         actions = super().get_actions(request)
@@ -185,23 +184,38 @@ class AdhesionAdmin(admin.ModelAdmin):
             del actions['delete_selected']
             del actions['delete_selected']
         return actions
         return actions
 
 
-    def has_add_permission(self, request):
-        return False
+    def get_fieldsets(self, request, obj=None):
+        fieldsets = super().get_fieldsets(request, obj)
+        # put adhesion id on top
+        if obj:
+            fields = fieldsets[0][1]['fields']
+            fields.remove('get_adhesion_link')
+            fieldsets = (
+                (None, {
+                    'fields': ['get_adhesion_link'] + fields,
+                }),
+            )
+        return fieldsets
 
 
     def has_delete_permission(self, request, obj=None):
     def has_delete_permission(self, request, obj=None):
         return False
         return False
 
 
 
 
-class CorporationAdmin(admin.ModelAdmin):
-    list_display = ('social_reason', 'get_adhesion_link')
-    search_fields = ('social_reason',)
-    filter_horizontal = ('members',)
+class AdhesionAdmin(AdtSearchMixin, admin.ModelAdmin):
+    list_display = ('get_id', 'type', 'get_adherent_link',)
+    list_filter = (AdherentTypeFilter, 'active',)
+    list_select_related = ('user', 'user__profile', 'corporation',)
+    fields = ('id', 'type', 'get_adherent_link',)
+    readonly_fields = ('id', 'type', 'get_adherent_link',)
+    search_fields = ('=id', 'notes',) \
+                    + tuple(['user__%s' % f for f in UserAdmin.search_fields if '__' not in f]) \
+                    + tuple(['corporation__%s' % f for f in CorporationAdmin.search_fields if '__' not in f])
+    inlines = (ServiceInline,)#PaymentInline,)
 
 
-    def get_adhesion_link(self, corp):
-        adhesion = corp.adhesion
-        if adhesion:
-            return adhesion.get_adhesion_link()
-    get_adhesion_link.short_description = 'Numéro d’adhérent'
+    def get_id(self, obj):
+        return 'ADT%d' % obj.id
+    get_id.short_description = 'Numéro d’adhérent'
+    get_id.admin_order_field = 'id'
 
 
     def get_actions(self, request):
     def get_actions(self, request):
         actions = super().get_actions(request)
         actions = super().get_actions(request)
@@ -209,30 +223,11 @@ class CorporationAdmin(admin.ModelAdmin):
             del actions['delete_selected']
             del actions['delete_selected']
         return actions
         return actions
 
 
-    def get_readonly_fields(self, request, obj=None):
-        readonly_fields = super().get_readonly_fields(request, obj)
-        if obj and obj.adhesion:
-            readonly_fields += ('get_adhesion_link',)
-        return readonly_fields
-
-    def get_fieldsets(self, request, obj=None):
-        fieldsets = super().get_fieldsets(request, obj)
-        # put adhesion_link on top
-        if obj and obj.adhesion:
-            CorporationAdmin.inlines = ()
-            fields = fieldsets[0][1]['fields']
-            fields.remove('get_adhesion_link')
-            fieldsets = (
-                (None, {
-                    'fields': ['get_adhesion_link'] + fields,
-                }),
-            )
-        else:
-            CorporationAdmin.inlines = (AdhesionInline,)
-        return fieldsets
+    def has_add_permission(self, request):
+        return False
 
 
     def has_delete_permission(self, request, obj=None):
     def has_delete_permission(self, request, obj=None):
-        return obj and not obj.adhesion
+        return False
 
 
 
 
 admin.site.unregister(AuthUser)
 admin.site.unregister(AuthUser)

+ 3 - 0
adhesions/apps.py

@@ -4,3 +4,6 @@ from django.apps import AppConfig
 class AdhesionsConfig(AppConfig):
 class AdhesionsConfig(AppConfig):
     name = 'adhesions'
     name = 'adhesions'
     verbose_name = 'Adhérents'
     verbose_name = 'Adhérents'
+
+    def ready(self):
+        import adhesions.signals  # noqa

+ 1 - 15
adhesions/forms.py

@@ -9,24 +9,10 @@ class UserCreationForm(forms.ModelForm):
 
 
     class Meta:
     class Meta:
         model = User
         model = User
-        fields = ('first_name', 'last_name', 'username',)
+        fields = ('first_name', 'last_name', 'username', 'email')
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
         self.fields['first_name'].required = True
         self.fields['first_name'].required = True
         self.fields['last_name'].required = True
         self.fields['last_name'].required = True
         self.fields['username'].required = False
         self.fields['username'].required = False
-
-
-class AdhesionForm(forms.ModelForm):
-    adhesion = forms.BooleanField(label='Adhérent ?', required=False)
-
-    class Meta:
-        model = Adhesion
-        exclude = ()
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        if self.instance.id:
-            self.fields['adhesion'].initial = True
-            self.fields['adhesion'].widget.attrs['readonly'] = True

+ 45 - 0
adhesions/migrations/0014_auto_20170614_2242.py

@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.2 on 2017-06-14 20:42
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+def migrate_adhesions(apps, schema_editor):
+    User = apps.get_model("adhesions", "User")
+    Corporation = apps.get_model("adhesions", "Corporation")
+    Adhesion = apps.get_model("adhesions", "Adhesion")
+    ContentType = apps.get_model("contenttypes", "ContentType")
+    user_type = ContentType.objects.get_for_model(User)
+    corp_type = ContentType.objects.get_for_model(Corporation)
+    db_alias = schema_editor.connection.alias
+    for adh in Adhesion.objects.using(db_alias).all():
+        if adh.adherent_type == user_type:
+            adh.user = User.objects.using(db_alias).get(pk=adh.adherent_id)
+        else:
+            assert(adh.adherent_type == corp_type)
+            adh.corporation = Corporation.objects.using(db_alias).get(pk=adh.adherent_id)
+        adh.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('adhesions', '0013_adhesion_active'),
+        ('accounts', '0006_auto_20170607_2306'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='adhesion',
+            name='user',
+            field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='adhesions.User'),
+        ),
+        migrations.AddField(
+            model_name='adhesion',
+            name='corporation',
+            field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='adhesions.Corporation'),
+        ),
+        migrations.RunPython(migrate_adhesions),
+    ]

+ 44 - 0
adhesions/migrations/0015_auto_20170614_2312.py

@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.2 on 2017-06-14 21:12
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+def create_missing_adhesions(apps, schema_editor):
+    User = apps.get_model("adhesions", "User")
+    Corporation = apps.get_model("adhesions", "Corporation")
+    Adhesion = apps.get_model("adhesions", "Adhesion")
+    ContentType = apps.get_model("contenttypes", "ContentType")
+    user_type = ContentType.objects.get_for_model(User)
+    corp_type = ContentType.objects.get_for_model(Corporation)
+    db_alias = schema_editor.connection.alias
+    for user in User.objects.using(db_alias).filter(adhesion__isnull=True).all():
+        if not Adhesion.objects.using(db_alias).filter(user__pk=user.pk).exists():
+            Adhesion.objects.using(db_alias).create(user=user)
+    for corp in Corporation.objects.using(db_alias).filter(adhesion__isnull=True).all():
+        if not Adhesion.objects.using(db_alias).filter(corporation__pk=corp.pk).exists():
+            Adhesion.objects.using(db_alias).create(corporation=corp)
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('adhesions', '0014_auto_20170614_2242'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='adhesion',
+            unique_together=set([]),
+        ),
+        migrations.RemoveField(
+            model_name='adhesion',
+            name='adherent_id',
+        ),
+        migrations.RemoveField(
+            model_name='adhesion',
+            name='adherent_type',
+        ),
+        migrations.RunPython(create_missing_adhesions),
+    ]

+ 57 - 64
adhesions/models.py

@@ -10,16 +10,54 @@ from djadhere.utils import get_active_filter
 from banking.models import Payment
 from banking.models import Payment
 
 
 
 
+class User(AuthUser):
+    def get_model_perms(self, request):
+        return {}
+
+    @property
+    def adhesions(self): # user and corporations (for which the user is a member) adhesions
+        return self.profile.adhesions
+
+    class Meta:
+        proxy = True
+        verbose_name = 'personne physique'
+        verbose_name_plural = 'personnes physiques'
+
+    def get_absolute_url(self):
+        return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=(self.pk,))
+
+    def __str__(self):
+        return self.get_full_name() or self.username
+
+
+class Corporation(models.Model):
+    social_reason = models.CharField(max_length=256, verbose_name='Raison sociale', unique=True)
+    description = models.TextField(blank=True, default='')
+    members = models.ManyToManyField(User, blank=True, verbose_name='Membres',
+                                     related_name='corporations', related_query_name='corporation')
+    email = models.EmailField(verbose_name='Adresse e-mail', blank=True)
+    phone_number = models.CharField(max_length=16, blank=True, default='',
+                                    verbose_name='Numéro de téléphone')
+    address = models.TextField(blank=True, default='', verbose_name='Adresse')
+    notes = models.TextField(blank=True, default='')
+
+    class Meta:
+        verbose_name = 'personne morale'
+        verbose_name_plural = 'personnes morales'
+
+    def get_absolute_url(self):
+        return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=(self.pk,))
+
+    def __str__(self):
+        return self.social_reason
+
+
 # Terminologie : une « adhésion » désgine une instance de ce modèle
 # Terminologie : une « adhésion » désgine une instance de ce modèle
 # tandis qu’un « adhérent » désigne un user ou une corporation.
 # tandis qu’un « adhérent » désigne un user ou une corporation.
 class Adhesion(models.Model):
 class Adhesion(models.Model):
     limit = models.Q(app_label='auth', model='user') \
     limit = models.Q(app_label='auth', model='user') \
           | models.Q(app_label='adhesions', model='corporation')
           | models.Q(app_label='adhesions', model='corporation')
     id = models.AutoField(verbose_name='Numéro d’adhérent', primary_key=True, editable=True)
     id = models.AutoField(verbose_name='Numéro d’adhérent', primary_key=True, editable=True)
-    adherent_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
-                                      limit_choices_to=limit, verbose_name='Type d’adhérent')
-    adherent_id = models.PositiveIntegerField(verbose_name='ID')
-    adherent = GenericForeignKey('adherent_type', 'adherent_id')
     contributions = GenericRelation(Payment,
     contributions = GenericRelation(Payment,
                                    content_type_field='reason_type',
                                    content_type_field='reason_type',
                                    object_id_field='reason_id',
                                    object_id_field='reason_id',
@@ -28,9 +66,11 @@ class Adhesion(models.Model):
     notes = models.TextField(blank=True, default='')
     notes = models.TextField(blank=True, default='')
     active = models.NullBooleanField(default=None, verbose_name='Adhésion en cours')
     active = models.NullBooleanField(default=None, verbose_name='Adhésion en cours')
 
 
+    user = models.OneToOneField(User, null=True)
+    corporation = models.OneToOneField(Corporation, null=True)
+
     class Meta:
     class Meta:
         verbose_name = 'adhésion'
         verbose_name = 'adhésion'
-        unique_together = ("adherent_type", "adherent_id")
         ordering = ('id',)
         ordering = ('id',)
 
 
     @property
     @property
@@ -43,10 +83,10 @@ class Adhesion(models.Model):
         # empêcher cette possibilité, si cette exception est levé on veut recevoir un mail avec l’erreur !
         # empêcher cette possibilité, si cette exception est levé on veut recevoir un mail avec l’erreur !
 
 
     def is_physical(self):
     def is_physical(self):
-        return self.adherent_type.app_label == 'auth' and self.adherent_type.model == 'user'
+        return self.user is not None
 
 
     def is_moral(self):
     def is_moral(self):
-        return self.adherent_type.app_label == 'adhesions' and self.adherent_type.model == 'corporation'
+        return self.corporation is not None
 
 
     @property
     @property
     def type(self):
     def type(self):
@@ -55,74 +95,27 @@ class Adhesion(models.Model):
         else:
         else:
             return 'Personne morale'
             return 'Personne morale'
 
 
-    def get_adherent_name(self):
+    @property
+    def adherent(self):
         if self.is_physical():
         if self.is_physical():
-            return str(self.adherent.profile)
+            return self.user
         else:
         else:
-            return str(self.adherent)
-    get_adherent_name.short_description = 'Nom ou raison sociale'
+            return self.corporation
 
 
     def get_adherent_link(self):
     def get_adherent_link(self):
-        url = reverse('admin:adhesions_%s_change' % self.adherent._meta.model_name, args=(self.adherent.id,))
-        return format_html(u'<a href="{}">{}</a>', url, self.get_adherent_name())
+        return format_html(u'<a href="{}">{}</a>', self.adherent.get_absolute_url(), self.adherent)
     get_adherent_link.short_description = 'Nom ou raison sociale'
     get_adherent_link.short_description = 'Nom ou raison sociale'
 
 
     def get_adhesion_link(self):
     def get_adhesion_link(self):
-        url = reverse('admin:adhesions_adhesion_change', args=(self.id,))
-        return format_html(u'<a href="{}">ADT{}</a>', url, str(self.id))
+        return format_html(u'<a href="{}">ADT{}</a>', self.get_absolute_url(), str(self.id))
     get_adhesion_link.short_description = 'Numéro d’adhérent'
     get_adhesion_link.short_description = 'Numéro d’adhérent'
 
 
+    def get_absolute_url(self):
+        return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=(self.pk,))
+
     def __str__(self):
     def __str__(self):
         return 'ADT%d' % self.id
         return 'ADT%d' % self.id
         if self.id is None:
         if self.id is None:
             return '?'
             return '?'
         else:
         else:
-            return 'ADT%d (%s)' % (self.id, self.get_adherent_name())
-
-
-class User(AuthUser):
-    class Meta:
-        proxy = True
-        verbose_name = 'personne physique'
-        verbose_name_plural = 'personnes physiques'
-
-    def get_model_perms(self, request):
-        return {}
-
-    @property
-    def adhesion(self): # user adhesion
-        return self.profile.adhesion
-
-    @property
-    def adhesions(self): # user and corporations (for which the user is a member) adhesions
-        return self.profile.adhesions
-    
-    def __str__(self):
-        return self.get_full_name() or self.username
-
-
-class Corporation(models.Model):
-    social_reason = models.CharField(max_length=256, verbose_name='Raison sociale', unique=True)
-    description = models.TextField(blank=True, default='')
-    members = models.ManyToManyField(User, blank=True, verbose_name='Membres',
-                                     related_name='corporations', related_query_name='corporation')
-    email = models.EmailField(verbose_name='Adresse e-mail', blank=True)
-    phone_number = models.CharField(max_length=16, blank=True, default='',
-                                    verbose_name='Numéro de téléphone')
-    address = models.TextField(blank=True, default='', verbose_name='Adresse')
-    notes = models.TextField(blank=True, default='')
-
-    @property
-    def adhesion(self):
-        ctype = ContentType.objects.get_for_model(self)
-        try:
-            return Adhesion.objects.get(adherent_type=ctype, adherent_id=self.pk)
-        except Adhesion.DoesNotExist:
-            return None
-
-    class Meta:
-        verbose_name = 'personne morale'
-        verbose_name_plural = 'personnes morales'
-
-    def __str__(self):
-        return self.social_reason
+            return 'ADT%d (%s)' % (self.id, self.adherent)

+ 16 - 0
adhesions/signals.py

@@ -0,0 +1,16 @@
+from django.dispatch import receiver
+from django.db.models.signals import post_save
+
+from .models import User, Corporation, Adhesion
+
+
+@receiver(post_save, sender=User, dispatch_uid='create_user_adhesion')
+def create_user_adhesion(sender, instance, created, **kwargs):
+    if created:
+        Adhesion.objects.create(user=instance)
+
+
+@receiver(post_save, sender=Corporation, dispatch_uid='create_corporation_adhesion')
+def create_corporation_adhesion(sender, instance, created, **kwargs):
+    if created:
+        Adhesion.objects.create(corporation=instance)

+ 1 - 1
services/admin.py

@@ -156,7 +156,7 @@ ends_resource.short_description = 'Terminer les allocations sélectionnées'
 
 
 class ServiceAdmin(admin.ModelAdmin):
 class ServiceAdmin(admin.ModelAdmin):
     list_display = ('id', 'get_adhesion_link', 'get_adherent_link', 'service_type', 'label', 'active')
     list_display = ('id', 'get_adhesion_link', 'get_adherent_link', 'service_type', 'label', 'active')
-    list_select_related = ('adhesion',) # to reduce database requests
+    list_select_related = ('adhesion', 'adhesion__user', 'adhesion__user__profile', 'adhesion__corporation', 'service_type')
     list_filter = (
     list_filter = (
         'active',
         'active',
         ('service_type', admin.RelatedOnlyFieldListFilter),
         ('service_type', admin.RelatedOnlyFieldListFilter),