from django.db import models from django.db.models import Q from django.core.validators import MaxValueValidator from django.utils import timezone from django.contrib.auth.models import Group from django.contrib.contenttypes.fields import GenericRelation from django.core.exceptions import ValidationError from adhesions.models import Adherent from banking.models import Payment class IPResource(models.Model): ip = models.GenericIPAddressField(verbose_name='IP') mask = models.PositiveIntegerField(validators=[MaxValueValidator(128)], default=0, verbose_name='Masque') @property def in_use(self): if Service.objects.filter(ip_resources=self) \ .filter(Service.get_ongoing_filter()).exists(): return True else: return False class Meta: verbose_name = 'Ressource IP' verbose_name_plural = 'Ressources IP' def __str__(self): r = str(self.ip) if self.mask: r += '/%d' % self.mask return r class ServiceType(models.Model): name = models.CharField(max_length=64, verbose_name='Nom', unique=True) group = models.ForeignKey(Group, null=True, blank=True, verbose_name='Groupe de gestion', related_name='service_types') class Meta: verbose_name = 'Type de service' verbose_name_plural = 'Types de service' def __str__(self): return self.name class Service(models.Model): adherent = models.ForeignKey(Adherent, verbose_name='Adhérent', null=True, blank=True) service_type = models.ForeignKey(ServiceType, related_name='services', verbose_name='Type de service') notes = models.TextField(blank=True, default='') contribution = GenericRelation(Payment, content_type_field='reason_type', object_id_field='reason_id', related_query_name='service') ip_resources = models.ManyToManyField(IPResource, blank=True, verbose_name='Ressources IP') start = models.DateTimeField(null=True, blank=True, verbose_name='Début du service') end = models.DateTimeField(null=True, blank=True, verbose_name='Fin du service') # Designed with a Karnaugh map, should be correct... @staticmethod def get_forthcoming_filter(): now = timezone.now() return Q(start__isnull=True, end__isnull=True) \ | Q(start__gt=now) @staticmethod def get_ongoing_filter(): now = timezone.now() return Q(start__lte=now, end__isnull=True) \ | Q(start__lte=now, end__gt=now) \ | Q(start__isnull=True, end__gt=now) @staticmethod def get_finished_filter(): now = timezone.now() return Q(end__lte=now) @property def is_ongoing(self): if (not self.start or self.start < timezone.now()) \ and (not self.end or self.end > timezone.now()) \ and (self.start or self.end): return True else: return False def clean(self): if self.start and self.end and self.start > self.end: raise ValidationError("La date de début du service doit être antérieur " "à la date de fin du service.") def __str__(self): return str(self.service_type) + ' ' + str(self.adherent)