from django.db import models from django.urls import reverse from django.contrib.auth.models import User from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.core.urlresolvers import reverse from django.utils.html import format_html from djadhere.utils import get_active_filter from banking.models import Payment # Terminologie : une « adhésion » désgine une instance de ce modèle # tandis qu’un « adhérent » désigne un user ou une corporation. class Adhesion(models.Model): limit = models.Q(app_label='auth', model='user') \ | models.Q(app_label='adhesions', model='corporation') 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, content_type_field='reason_type', object_id_field='reason_id', related_query_name='adhesion') created = models.DateTimeField(null=True, blank=True, auto_now_add=True) class Meta: verbose_name = 'adhésion' unique_together = ("adherent_type", "adherent_id") ordering = ('id',) @property def contribution(self): try: return self.contributions.exclude(period=0).filter(get_active_filter()).get() except Payment.DoesNotExist: return None # MultipleObjectsReturned non catché volontairement, le filtrage par la méthode clean est censé # empêcher cette possibilité, si cette exception est levé on veut recevoir un mail avec l’erreur ! def is_physical(self): return self.adherent_type.app_label == 'auth' and self.adherent_type.model == 'user' def is_moral(self): return self.adherent_type.app_label == 'adhesions' and self.adherent_type.model == 'corporation' @property def type(self): if self.is_physical(): return 'Personne physique' else: return 'Personne morale' def get_adherent_name(self): if self.is_physical(): return str(self.adherent.profile) else: return str(self.adherent) get_adherent_name.short_description = 'Nom ou raison sociale' def get_adherent_link(self): if self.is_physical(): name = str(self.adherent.profile) model_name = 'proxyuser' else: name = str(self.adherent) model_name = 'corporation' url = reverse('admin:adhesions_%s_change' % model_name, args=(self.adherent.id,)) return format_html(u'{}', url, name) get_adherent_link.short_description = 'Nom ou raison sociale' def __str__(self): return 'ADT%d' % self.id if self.id is None: return '?' else: return 'ADT%d (%s)' % (self.id, self.get_adherent_name()) class ProxyUser(User): class Meta: proxy = True verbose_name = 'personne physique' verbose_name_plural = 'personnes physiques' def get_model_perms(self, request): return {} def __str__(self): return str(self.profile) 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