"""Webapp app models.""" from django.conf import settings from django.db import models from django.utils import timezone # from datetime import timedelta from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver from webapp.utils import month_from_now, send_signup_email from django.utils.translation import ugettext_lazy as _ from auditlog.registry import auditlog from phonenumber_field.modelfields import PhoneNumberField from django.contrib.postgres.fields import JSONField from uuid import uuid4 import logging VERBOSE_NAME = _('Webapp') EMAIL_REGEX = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" class Tag(models.Model): """Model for tag.""" class Meta: verbose_name = _('Tag') verbose_name_plural = _('Tags') slug = models.SlugField(unique=True) name = models.CharField(max_length=127) icon = models.ImageField() def __str__(self): return _('Tag: {}').format(self.slug) class BaseFeed(models.Model): """Model containing something showing on some info feed.""" tags = models.ManyToManyField(Tag, related_name="feeds", blank=True) visible = models.BooleanField(default=True) title = models.CharField(max_length=255) description = models.CharField(max_length=255) content = models.TextField() image = models.ImageField(blank=True, null=True) class Feed(BaseFeed): """Model representing feed.""" class Meta: verbose_name = _('Feed') verbose_name_plural = _('Feeds') publish_time = models.DateTimeField(default=timezone.now) autohide = models.DateTimeField(default=month_from_now) autohide_enabled = models.BooleanField(default=False) def __str__(self): return _('Feed: {}').format(self.title) class Event(BaseFeed): """Model for event in guild calendar""" class Meta: verbose_name = _('Event') verbose_name_plural = _('Events') start_time = models.DateTimeField(default=timezone.now) end_time = models.DateTimeField(default=timezone.now) signupForm = models.ManyToManyField( 'SignupForm', blank=True, related_name="event") location = models.CharField(max_length=255, blank=True) def __str__(self): return _('Event: {}').format(self.title) class TemplateQuestion(models.Model): """ NOT IMPLEMENTED!!! Stores template questions for signup forms as JSON format. Used in signup form creation """ class Meta: verbose_name = _('Template question') verbose_name_plural = _('Template questions') name = models.CharField(max_length=255) question = JSONField() def __str__(self): return _('Template questions: {}').format(self.name) class SignupForm(models.Model): """Model for event signup form. Stores questions in JSON format.""" class Meta: verbose_name = _('Signup form') verbose_name_plural = _('Signup forms') title = models.CharField(max_length=255) start_time = models.DateTimeField(default=timezone.now) end_time = models.DateTimeField(default=timezone.now) questions = JSONField() schema = JSONField() visible = models.BooleanField(default=True) quota = models.PositiveIntegerField(blank=True, null=True) email_content = models.TextField(blank=True) def __str__(self): return _('#{} {}').format(self.id, self.title) @property def signups(self): return Signup.objects.filter(signupForm=self).order_by('pk') @property def isOpen(self): now = timezone.now() return self.start_time <= now and now < self.end_time class Signup(models.Model): """ Actual signup into any SignupForm. Deletes are soft. """ class Meta: verbose_name = _('Sign-up') verbose_name_plural = _('Sign-ups') signupForm = models.ForeignKey('SignupForm', on_delete=models.CASCADE) time = models.DateTimeField(default=timezone.now) answer = JSONField() # Answer we use in signupForm signups field. Frontend uses first questions answer as this value. list_name = models.CharField(_('Name'), max_length=255) # If there is email in questions, we save it as own field email = models.EmailField(blank=True, null=True) # Random unique identifier. Used for signup editing by the user. uuid = models.UUIDField(default=uuid4, editable=False) deleted = models.BooleanField(default=False) def __str__(self): return f"{self.signupForm}: {self.list_name} ({self.pk})" @receiver(post_save, sender=Signup) def email_on_signup(sender, instance, created, **kwargs): if created and instance.email: # TODO: Possible bug due to many-to-many relationship with events and forms. # TODO: Subject field crashes with lazy loaded translations. try: # subject = _(f"Olet ilmoittautunut tapahtumaan {instance.signupForm.event.first().title}") subject = f"Olet ilmoittautunut tapahtumaan {instance.signupForm.event.first().title}" except AttributeError: # subject = _(f"Olet ilmoittautunut ilmoon {instance.signupForm.title}") subject = f"Olet ilmoittautunut ilmoon {instance.signupForm.title}" send_signup_email(instance.email, subject, instance.id, instance.uuid, instance.signupForm.email_content) class BaseRole(models.Model): """Base model for occupations/roles.""" name = models.CharField(_('Name'), max_length=255) is_board = models.BooleanField(_('Board member')) def __str__(self): n = self.name.capitalize() return '{} ({})'.format(n, _('board member')) if self.is_board else n class JobAd(models.Model): """Job advertisements shown on Corporate relations page""" class Meta: verbose_name = _('JobAd') verbose_name_plural = _('JobAds') title = models.CharField(max_length=255) description = models.CharField(max_length=255) content = models.TextField() visible = models.BooleanField(default=True) created_at = models.DateTimeField(default=timezone.now) autohide_at = models.DateTimeField(default=month_from_now) autohide_enabled = models.BooleanField(default=False) auditlog.register(Tag) auditlog.register(Feed) auditlog.register(Event) auditlog.register(SignupForm) auditlog.register(Signup) auditlog.register(JobAd)