123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- from django.db import models
- from django.contrib.contenttypes.fields import GenericForeignKey
- from django.contrib.contenttypes.models import ContentType
- from django.core.validators import MaxValueValidator
- from django.core.urlresolvers import reverse
- from django.core.exceptions import ValidationError
- from djadhere.utils import is_overlapping
- class Payment(models.Model):
- TRANSFERT = 0
- WITHDRAWAL = 1
- PAYMENT_CHOICES = (
- (TRANSFERT, 'Virement'),
- (WITHDRAWAL, 'Prélèvement'),
- )
- limit = models.Q(app_label='adhesions', model='Adherent') \
- | models.Q(app_label='services', model='Service')
- reason_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
- limit_choices_to=limit)
- reason_id = models.PositiveIntegerField()
- reason = GenericForeignKey('reason_type', 'reason_id')
- amount = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Montant')
- period = models.PositiveIntegerField(validators=[MaxValueValidator(12)],
- verbose_name='Période (mois) (0 si non récurrent)')
- payment_method = models.IntegerField(choices=PAYMENT_CHOICES,
- verbose_name='Méthode de paiement')
- start = models.DateField(verbose_name='Date de paiement ou de début de paiement')
- end = models.DateField(null=True, blank=True, verbose_name='Date de fin de paiement (si récurrent)')
- validated = models.BooleanField(default=False, verbose_name='Paiement validé')
- class Meta:
- verbose_name = 'paiement'
- permissions = (
- ('validate_payment', 'Peut valider les paiements'),
- )
- def payment_type_verbose(self):
- if self.reason_type.app_label == 'adhesions' \
- and self.reason_type.model == 'adherent':
- return 'Cotisation'
- if self.reason_type.app_label == 'services' \
- and self.reason_type.model == 'service':
- return 'Service (%s)' % self.reason.service_type
- payment_type_verbose.short_description = 'Type'
- def period_verbose(self):
- if self.period == 0:
- return 'non récurrent'
- elif self.period == 1:
- return 'mensuel'
- elif self.period == 3:
- return 'trimestriel'
- elif self.period == 6:
- return 'biannuel'
- elif self.period == 12:
- return 'annuel'
- else:
- return '%d mois' % self.period
- # Note: 'adherent' is already used as the related_query_name
- # of the GenericRelation on Adherent
- def get_adherent(self):
- if self.reason_type.app_label == 'adhesions' \
- and self.reason_type.model == 'adherent':
- return self.reason
- if self.reason_type.app_label == 'services' \
- and self.reason_type.model == 'service':
- return self.reason.adherent
- get_adherent.short_description = 'Adhérent'
- def clean(self):
- super().clean()
- # S’il s’agit d’un paiement non récurrent, le champ end doit rester blanc
- if self.period == 0 and self.end:
- raise ValidationError({'end': "Un paiement non récurrent ne doit pas avoir de date de fin."})
- # Vérification de la cohérence des champs start et end
- if self.end and self.start > self.end:
- raise ValidationError("La date de début de paiement doit être antérieur à la date de fin de paiement.")
- # Vérification de l’absence de chevauchement avec une période existante
- if self.reason:
- payments = Payment.objects.filter(reason_type=self.reason_type, reason_id=self.reason_id)
- if is_overlapping(self, payments):
- raise ValidationError("Les périodes de paiement ne doivent pas se chevaucher.")
- def __str__(self):
- s = str(self.amount) + '€'
- if self.period:
- if self.period == 1:
- s += '/mois'
- elif self.period == 12:
- s += '/an'
- else:
- s += '/%d mois' % self.period
- if self.payment_method == self.TRANSFERT:
- s += ' (virement)'
- elif self.payment_method == self.WITHDRAWAL:
- s += ' (prélèvement)'
- return s
|