models.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. from django.db import models
  2. from django.db.models import Q
  3. from django.core.validators import MaxValueValidator
  4. from django.utils import timezone
  5. from django.contrib.auth.models import Group
  6. from django.contrib.contenttypes.fields import GenericRelation
  7. from django.core.exceptions import ValidationError
  8. from djadhere.utils import get_active_filter, is_overlapping
  9. from adhesions.models import Adherent
  10. from banking.models import Payment
  11. class IPResource(models.Model):
  12. ip = models.GenericIPAddressField(verbose_name='IP')
  13. mask = models.PositiveIntegerField(validators=[MaxValueValidator(128)],
  14. default=0, verbose_name='Masque')
  15. @property
  16. def in_use(self):
  17. if self.allocations.filter(get_active_filter()).exists():
  18. return True
  19. else:
  20. return False
  21. class Meta:
  22. verbose_name = 'Ressource IP'
  23. verbose_name_plural = 'Ressources IP'
  24. def __str__(self):
  25. r = str(self.ip)
  26. if self.mask:
  27. r += '/%d' % self.mask
  28. return r
  29. class ServiceType(models.Model):
  30. name = models.CharField(max_length=64, verbose_name='Nom', unique=True)
  31. group = models.ForeignKey(Group, null=True, blank=True,
  32. verbose_name='Groupe de gestion',
  33. related_name='service_types')
  34. class Meta:
  35. verbose_name = 'Type de service'
  36. verbose_name_plural = 'Types de service'
  37. def __str__(self):
  38. return self.name
  39. class Service(models.Model):
  40. adherent = models.ForeignKey(Adherent, verbose_name='Adhérent', null=True, blank=True)
  41. service_type = models.ForeignKey(ServiceType, related_name='services',
  42. verbose_name='Type de service')
  43. label = models.CharField(blank=True, default='', max_length=128)
  44. notes = models.TextField(blank=True, default='')
  45. active = models.BooleanField(default=True, verbose_name='actif')
  46. created = models.DateTimeField(auto_now_add=True)
  47. contributions = GenericRelation(Payment,
  48. content_type_field='reason_type',
  49. object_id_field='reason_id',
  50. related_query_name='service')
  51. @property
  52. def contribution(self):
  53. try:
  54. return self.contributions.get(get_active_filter())
  55. except Payment.DoesNotExist:
  56. return None
  57. # MultipleObjectsReturned non catché volontairement, cf remarque adhesions.Adherent.contribution
  58. @property
  59. def active_allocations(self):
  60. return self.allocations.filter(get_active_filter())
  61. @property
  62. def inactive_allocations(self):
  63. return self.allocations.exclude(get_active_filter())
  64. def clean(self):
  65. super().clean()
  66. # Vérification de l’unicité par type de service du label
  67. if self.label != '' and Service.objects.exclude(pk=self.pk).filter(service_type=self.service_type, label=self.label):
  68. raise ValidationError("Un service du même type existe déjà avec ce label.")
  69. def __str__(self):
  70. s = str(self.service_type)
  71. if self.label:
  72. s += ' ' + self.label
  73. s += ' (' + str(self.adherent) + ')'
  74. return s
  75. class ResourceAllocation(models.Model):
  76. resource = models.ForeignKey(IPResource, verbose_name='Ressource', related_name='allocations', related_query_name='allocation')
  77. service = models.ForeignKey(Service, related_name='allocations', related_query_name='allocation')
  78. start = models.DateTimeField(verbose_name='Début de la période d’allocation')
  79. end = models.DateTimeField(null=True, blank=True, verbose_name='Fin de la période d’allocation')
  80. def clean(self):
  81. super().clean()
  82. # Vérification de la cohérence des champs start et end
  83. if self.end and self.start > self.end:
  84. raise ValidationError("La date de début de l’allocation doit être antérieur "
  85. "à la date de fin de l’allocation.")
  86. # Vérification de l’abscence de chevauchement de la période d’allocation
  87. allocations = ResourceAllocation.objects.filter(resource__pk=self.resource.pk)
  88. if is_overlapping(self, allocations):
  89. raise ValidationError("La période d’allocation de cette ressource chevauche "
  90. "avec une période d’allocation précédente.")
  91. class Meta:
  92. verbose_name = 'Allocation de ressource'
  93. verbose_name_plural = 'Allocations de ressources'
  94. def __str__(self):
  95. return str(self.resource) + ' pour ' + str(self.service)