123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- from django.db import models
- from django.core.validators import MinValueValidator, MaxValueValidator
- from django.core.exceptions import ValidationError
- from django.urls import reverse
- class CurrentPaymentManager(models.Manager):
- def get_queryset(self):
- qs = super().get_queryset()
- qs = qs.annotate(
- payment_method=models.Subquery(
- PaymentUpdate.objects.filter(payment=models.OuterRef('pk'), validated=True)
- .values('payment_method')[:1]
- )
- )
- qs = qs.annotate(
- active=models.Case(
- models.When(payment_method__isnull=True, then=None),
- models.When(payment_method=PaymentUpdate.STOP, then=False),
- default=True,
- output_field=models.NullBooleanField()
- )
- )
- return qs
- class RecurringPayment(models.Model):
- objects = CurrentPaymentManager()
- @property
- def debtor(self):
- if hasattr(self, 'adhesion'):
- return self.adhesion
- if hasattr(self, 'service'):
- return self.service.adhesion
- def payment_type(self):
- if hasattr(self, 'adhesion'):
- return 'Adhésion'
- if hasattr(self, 'service'):
- return 'Service'
- payment_type.short_description = 'Type'
- def payment_object(self):
- return self.adhesion if hasattr(self, 'adhesion') else self.service
- def get_absolute_url(self):
- return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=(self.pk,))
- def get_current_payment(self):
- return self.updates.filter(validated=True).first()
- def get_current_payment_display(self):
- current = self.get_current_payment()
- if current:
- return str(current)
- else:
- return 'non renseignée'
- class Meta:
- verbose_name = 'paiement récurrent'
- verbose_name_plural = 'paiements récurrents'
- def __str__(self):
- if hasattr(self, 'adhesion'):
- return "Cotisation %s" % self.adhesion
- else:
- return "Contribution %s" % self.service
- class PaymentUpdate(models.Model):
- STOP = 0
- FREE = 1
- DEBIT = 2
- TRANSFER = 3
- CASH = 4
- INVOICE = 5
- PAYMENT_CHOICES = (
- (DEBIT, 'Prélèvement'),
- (TRANSFER, 'Virement'),
- (CASH, 'Liquide'),
- (INVOICE, 'Facture'),
- (FREE, 'Gratuit'),
- (STOP, 'Arrêt'),
- )
- created = models.DateTimeField(auto_now_add=True)
- payment = models.ForeignKey(RecurringPayment, related_name='updates', on_delete=models.CASCADE)
- amount = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Montant')
- period = models.PositiveIntegerField(validators=[MinValueValidator(1), MaxValueValidator(12)],
- verbose_name='Période (mois)')
- payment_method = models.IntegerField(choices=PAYMENT_CHOICES, default=DEBIT,
- verbose_name='Méthode de paiement')
- start = models.DateTimeField(verbose_name='Date')
- month_day = models.PositiveIntegerField(validators=[MinValueValidator(1), MaxValueValidator(25)],
- verbose_name='Jour souhaité de prélèvement',
- null=True, blank=True)
- validated = models.BooleanField(default=False, verbose_name='Saisie bancaire effectuée')
- class Meta:
- verbose_name = 'paiement'
- ordering = ('-start',)
- def clean(self):
- super().clean()
- errors = {}
- if self.payment_method == PaymentUpdate.STOP and self.amount:
- errors.update({'amount': "Pour l’arrêt d’un paiement, le montant doit être nul."})
- if errors:
- raise ValidationError(errors)
- 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
- def __str__(self):
- if self.payment_method == self.STOP:
- return 'paiement arrêté'
- if self.payment_method == self.FREE:
- return 'libre'
- 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.DEBIT:
- s += ' (prélèvement)'
- elif self.payment_method == self.TRANSFER:
- s += ' (virement)'
- elif self.payment_method == self.CASH:
- s += ' (liquide)'
- elif self.payment_method == self.INVOICE:
- s += ' (sur facture)'
- return s
|