models.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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='Adherent') \
  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 == 'adherent':
  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. # Note: 'adherent' is already used as the related_query_name
  56. # of the GenericRelation on Adherent
  57. def get_adherent(self):
  58. if self.reason_type.app_label == 'adhesions' \
  59. and self.reason_type.model == 'adherent':
  60. return self.reason
  61. if self.reason_type.app_label == 'services' \
  62. and self.reason_type.model == 'service':
  63. return self.reason.adherent
  64. get_adherent.short_description = 'Adhérent'
  65. def clean(self):
  66. super().clean()
  67. # S’il s’agit d’un paiement non récurrent, le champ end doit rester blanc
  68. if self.period == 0 and self.end:
  69. raise ValidationError({'end': "Un paiement non récurrent ne doit pas avoir de date de fin."})
  70. # Vérification de la cohérence des champs start et end
  71. if self.end and self.start > self.end:
  72. raise ValidationError("La date de début de paiement doit être antérieur à la date de fin de paiement.")
  73. # Vérification de l’absence de chevauchement avec une période existante
  74. if self.reason:
  75. payments = Payment.objects.filter(reason_type=self.reason_type, reason_id=self.reason_id)
  76. if is_overlapping(self, payments):
  77. raise ValidationError("Les périodes de paiement ne doivent pas se chevaucher.")
  78. def __str__(self):
  79. s = str(self.amount) + '€'
  80. if self.period:
  81. if self.period == 1:
  82. s += '/mois'
  83. elif self.period == 12:
  84. s += '/an'
  85. else:
  86. s += '/%d mois' % self.period
  87. if self.payment_method == self.TRANSFERT:
  88. s += ' (virement)'
  89. elif self.payment_method == self.WITHDRAWAL:
  90. s += ' (prélèvement)'
  91. return s