models.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. from django.db import models
  2. from django.contrib.contenttypes.fields import GenericForeignKey
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.core.validators import MaxValueValidator
  5. from django.core.urlresolvers import reverse
  6. from django.core.exceptions import ValidationError
  7. from djadhere.utils import is_overlapping
  8. class Payment(models.Model):
  9. TRANSFERT = 0
  10. WITHDRAWAL = 1
  11. PAYMENT_CHOICES = (
  12. (TRANSFERT, 'Virement'),
  13. (WITHDRAWAL, 'Prélèvement'),
  14. )
  15. limit = models.Q(app_label='adhesions', model='Adhesion') \
  16. | models.Q(app_label='services', model='Service')
  17. reason_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
  18. limit_choices_to=limit)
  19. reason_id = models.PositiveIntegerField()
  20. reason = GenericForeignKey('reason_type', 'reason_id')
  21. amount = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Montant')
  22. period = models.PositiveIntegerField(validators=[MaxValueValidator(12)],
  23. verbose_name='Période (mois) (0 si non récurrent)')
  24. payment_method = models.IntegerField(choices=PAYMENT_CHOICES,
  25. verbose_name='Méthode de paiement')
  26. start = models.DateField(verbose_name='Date de paiement ou de début de paiement')
  27. end = models.DateField(null=True, blank=True, verbose_name='Date de fin de paiement (si récurrent)')
  28. validated = models.BooleanField(default=False, verbose_name='Paiement validé')
  29. class Meta:
  30. verbose_name = 'paiement'
  31. permissions = (
  32. ('validate_payment', 'Peut valider les paiements'),
  33. )
  34. def payment_type_verbose(self):
  35. if self.reason_type.app_label == 'adhesions' \
  36. and self.reason_type.model == 'adhesion':
  37. return 'Cotisation'
  38. if self.reason_type.app_label == 'services' \
  39. and self.reason_type.model == 'service':
  40. return 'Service (%s)' % self.reason.service_type
  41. payment_type_verbose.short_description = 'Type'
  42. def period_verbose(self):
  43. if self.period == 0:
  44. return 'non récurrent'
  45. elif self.period == 1:
  46. return 'mensuel'
  47. elif self.period == 3:
  48. return 'trimestriel'
  49. elif self.period == 6:
  50. return 'biannuel'
  51. elif self.period == 12:
  52. return 'annuel'
  53. else:
  54. return '%d mois' % self.period
  55. # FIXME
  56. @property
  57. def adherent(self):
  58. return self.get_adhesion().adherent
  59. def get_adhesion(self):
  60. if self.reason_type.app_label == 'adhesions' \
  61. and self.reason_type.model == 'adhesion':
  62. return self.reason
  63. if self.reason_type.app_label == 'services' \
  64. and self.reason_type.model == 'service':
  65. return self.reason.adhesion
  66. get_adhesion.short_description = 'Adhésion'
  67. def clean(self):
  68. super().clean()
  69. # S’il s’agit d’un paiement non récurrent, le champ end doit rester blanc
  70. if self.period == 0 and self.end:
  71. raise ValidationError({'end': "Un paiement non récurrent ne doit pas avoir de date de fin."})
  72. # Vérification de la cohérence des champs start et end
  73. if self.end and self.start > self.end:
  74. raise ValidationError("La date de début de paiement doit être antérieur à la date de fin de paiement.")
  75. # Vérification de l’absence de chevauchement avec une période existante
  76. # FIXME ne fonctionne pas vraiment via les inlines…
  77. if self.reason:
  78. payments = Payment.objects.filter(reason_type=self.reason_type, reason_id=self.reason_id)
  79. if is_overlapping(self, payments):
  80. raise ValidationError("Les périodes de paiement ne doivent pas se chevaucher.")
  81. def __str__(self):
  82. s = str(self.amount) + '€'
  83. if self.period:
  84. if self.period == 1:
  85. s += '/mois'
  86. elif self.period == 12:
  87. s += '/an'
  88. else:
  89. s += '/%d mois' % self.period
  90. if self.payment_method == self.TRANSFERT:
  91. s += ' (virement)'
  92. elif self.payment_method == self.WITHDRAWAL:
  93. s += ' (prélèvement)'
  94. return s