from django.contrib.auth import get_user_model from django.utils.translation import ugettext_lazy as _ from django.core.validators import RegexValidator from django.core.exceptions import FieldError from django.db import models from communication.models import SubscriptionMixin User = get_user_model() class Event(SubscriptionMixin, models.Model): title = models.CharField( _("nom de l'évènement"), max_length=200, ) slug = models.SlugField( _('identificateur'), unique=True, help_text=_("Seulement des lettres, des chiffres ou" "les caractères '_' ou '-'."), ) created_by = models.ForeignKey( User, related_name="created_events", editable=False, ) creation_date = models.DateTimeField( _('date de création'), auto_now_add=True, ) description = models.TextField(_('description')) beginning_date = models.DateTimeField(_('date de début')) ending_date = models.DateTimeField(_('date de fin')) class Meta: verbose_name = _("évènement") verbose_name_plural = _("évènements") def __str__(self): return self.title class EventSpecificMixin(models.Model): """Mixin allowing for event-specific models instances or not (depending on whether the event field is null)""" event = models.ForeignKey( 'event.Event', verbose_name=_("évènement"), help_text=_("Si spécifié, l'instance du modèle " "est spécifique à l'évènement en question"), blank=True, null=True ) class Meta: abstract = True class Place(EventSpecificMixin, models.Model): name = models.CharField( _("nom du lieu"), max_length=200, ) description = models.TextField(blank=True) class Meta: verbose_name = _("lieu") verbose_name_plural = _("lieux") def __str__(self): return self.name class ActivityTag(EventSpecificMixin, models.Model): name = models.CharField( _("nom du tag"), max_length=200, ) is_public = models.BooleanField( help_text=_("Sert à faire une distinction dans" " l'affichage selon que cela soit" " destiné au public ou à l'équipe" " organisatrice"), ) color_regex = RegexValidator( regex=r'^#(?:[0-9a-fA-F]{3}){1,2}$', message=_("La chaîne de caractère rentrée n'est pas" " une couleur en hexadécimal."), ) color = models.CharField( _('couleur'), max_length=7, validators=[color_regex], help_text=_("Rentrer une couleur en hexadécimal"), ) class Meta: verbose_name = _("tag") verbose_name_plural = _("tags") def __str__(self): return self.name class AbstractActivityTemplate(SubscriptionMixin, models.Model): title = models.CharField( _("nom de l'activité"), max_length=200, blank=True, null=True, ) # FIXME: voir comment on traite l'héritage de `event` event = models.ForeignKey(Event) is_public = models.NullBooleanField( blank=True, ) has_perm = models.NullBooleanField( blank=True, ) min_perm = models.PositiveSmallIntegerField( _('nombre minimum de permanents'), blank=True, null=True, ) max_perm = models.PositiveSmallIntegerField( _('nombre maximum de permanents'), blank=True, null=True, ) description = models.TextField( _('description'), help_text=_("Public, Visible par tout le monde."), blank=True, null=True, ) remarks = models.TextField( _('remarques'), help_text=_("Visible uniquement par les organisateurs"), blank=True, null=True, ) tags = models.ManyToManyField( ActivityTag, blank=True, ) place = models.ManyToManyField( Place, blank=True, ) class Meta: abstract = True class ActivityTemplate(AbstractActivityTemplate): class Meta: verbose_name = _("template activité") verbose_name_plural = _("templates activité") def __str__(self): return self.title class Activity(AbstractActivityTemplate): parent = models.ForeignKey( ActivityTemplate, related_name="children", ) staff = models.ManyToManyField( User, related_name="in_perm_activities", blank=True, ) beginning = models.DateTimeField(_("heure de début")) end = models.DateTimeField(_("heure de fin")) def get_herited(self, attrname): inherited_fields = [f.name for f in ActivityTemplate._meta.get_fields()] m2m_fields = [f.name for f in ActivityTemplate._meta.get_fields() if f.many_to_many] attr = getattr(self, attrname) if attrname not in inherited_fields: raise FieldError( _("%(attrname)s n'est pas un champ héritable"), params={'attrname': attrname}, ) elif attrname in m2m_fields: if attr.exists(): return attr else: return getattr(self.parent, attrname) elif attr is None: return getattr(self.parent, attrname) else: return attr class Meta: verbose_name = _("activité") verbose_name_plural = _("activités") def __str__(self): return self.get_herited('title')