from datetime import datetime from django.db import models from django.utils.translation import gettext_lazy as _ from ckeditor.fields import RichTextField from django_iban.fields import IBANField from aleksis.core.mixins import ExtensibleModel from aleksis.core.models import Group, Person from .util import generate_code class FeedbackAspect(ExtensibleModel): aspect = models.CharField(max_length=100) def __str__(self) -> str: return self.aspect class Event(ExtensibleModel): # Event details display_name = models.CharField(verbose_name=_("Display name"), max_length=255) linked_group = models.OneToOneField( Group, on_delete=models.CASCADE, verbose_name=_("Group"), related_name="linked_event" ) description = models.CharField(max_length=500, verbose_name=_("Description")) published = models.BooleanField(default=False, verbose_name=_("Publish")) place = models.CharField(max_length=50, verbose_name="Place") # Date details date_event = models.DateField(verbose_name=_("Date of event")) date_registration = models.DateField(verbose_name=_("Registration deadline")) date_retraction = models.DateField(verbose_name=_("Retraction deadline")) # Other details cost = models.IntegerField(verbose_name=_("Cost in €")) max_participants = models.PositiveSmallIntegerField(verbose_name=_("Maximum participants")) information = RichTextField(verbose_name=_("Information about the event")) # Feedback feedback_aspects = models.ManyToManyField( FeedbackAspect, verbose_name=_("Feedback aspects"), related_name="event", null=True, blank=True, ) def __str__(self) -> str: return self.display_name def can_register(self, request=None): now = datetime.today().date() if request and request.user.is_authenticated: if request.user.person in self.linked_group.members.all(): return False if ( Voucher.objects.filter(event=self, person=request.user.person, used=False).count() > 0 ): return True if self.linked_group.members.count() >= self.max_participants: return False if self.date_registration: return self.date_registration >= now return self.date_event > now @property def booked_percentage(self): return self.linked_group.members.count() / self.max_participants * 100 @property def members_persons(self): return self.linked_group.members.all() @property def owners_persons(self): return self.linked_group.owners.all() class EventFeedback(ExtensibleModel): COMMENT_CHOICES = [ ("first", _("Only first name")), ("first_age", _("First name and age")), ("first_last_age", _("First name, last name and age")), ] LICENCE_CHOICES = [ ("CC-BY-4.0+", _("Creative Commons with attribution, 4.0 or later")), ( "CC-BY-SA-4.0+", _( "Creative Commons with attribution and distribution only" "under the same conditions, 4.0 or later" ), ), ] event = models.ForeignKey( Event, on_delete=models.CASCADE, verbose_name=_("Event"), related_name="feedback" ) person = models.ForeignKey( Person, on_delete=models.CASCADE, verbose_name=_("Person"), related_name="feedback" ) comment_private = models.TextField(verbose_name=_("Private comment"), blank=True) comment_public = models.TextField(verbose_name=_("Public comment"), blank=True) comment_public_info = models.CharField( choices=COMMENT_CHOICES, verbose_name=_("Information in the comment"), max_length=255 ) photos = models.ImageField(verbose_name=_("Photos"), upload_to="feedback/", blank=True) photos_licence = models.CharField( choices=LICENCE_CHOICES, verbose_name=_("Photo licence"), max_length=255 ) class Meta: verbose_name = _("Event feedback") verbose_name_plural = _("Event feedbacks") constraints = [ models.UniqueConstraint( fields=["person", "event"], name="unique_person_feedback_per_event" ) ] class Voucher(ExtensibleModel): class Meta: verbose_name = _("Vouchers") verbose_name_plural = _("Vouchers") code = models.CharField(max_length=8, blank=True, default="") event = models.ForeignKey( Event, related_name="vouchers", verbose_name=_("Event"), on_delete=models.CASCADE, null=True, ) person = models.ForeignKey( Person, related_name="vouchers", verbose_name=_("Person"), on_delete=models.CASCADE, ) discount = models.IntegerField(default=100) used = models.BooleanField(default=False) used_person_uid = models.ForeignKey( Person, on_delete=models.CASCADE, verbose_name=_("Used by"), related_name="used_vouchers", null=True, ) deleted = models.BooleanField(default=False) def __str__(self) -> str: return self.code def save(self, *args, **kwargs): if not self.code: self.code = generate_code() super().save(*args, **kwargs) class EventRegistration(ExtensibleModel): event = models.ForeignKey(Event, on_delete=models.CASCADE, verbose_name=_("Event")) person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person")) date_registred = models.DateTimeField(auto_now_add=True, verbose_name=_("Registration date")) comment = models.TextField(verbose_name=_("Comment / remarks"), blank=True, default="") medical_information = models.TextField( verbose_name=_("Medical information / intolerances"), blank=True, default="" ) channel = models.CharField(verbose_name=_("Channel"), max_length=255, blank=True, default="") voucher = models.ForeignKey( Voucher, on_delete=models.CASCADE, verbose_name=_("Voucher"), blank=True, null=True, ) donation = models.PositiveIntegerField(verbose_name=_("Donation"), blank=True, null=True) accept_sepa = models.BooleanField(verbose_name=_("SEPA direct debit")) iban = IBANField( verbose_name=_("IBAN (for SEPA direct debit)"), enforce_database_constraint=True, null=True, blank=True, ) accept_terms = models.BooleanField(verbose_name=_("Delcaration of consent by parents")) accept_data = models.BooleanField(verbose_name=_("Declaration of consent data protection")) accept_general_terms = models.BooleanField( verbose_name=_("Declatation of consent terms and condition") ) def __str__(self) -> str: return f"{self.event}, {self.person.first_name} {self.person.last_name}" class Meta: verbose_name = _("Event registration") verbose_name_plural = _("Event registrations") constraints = [ models.UniqueConstraint( fields=["person", "event"], name="unique_person_registration_per_event" ) ]