diff --git a/aleksis/apps/paweljong/migrations/0001_initial.py b/aleksis/apps/paweljong/migrations/0001_initial.py index 2ca1cd2a0be1aac31e5114b1835cd7a84250bab3..3921c4c214e171d7eab6f83d6e117bd3f903bc28 100644 --- a/aleksis/apps/paweljong/migrations/0001_initial.py +++ b/aleksis/apps/paweljong/migrations/0001_initial.py @@ -11,7 +11,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('core', '0028_alter_globalpermissions_options'), + ('core', '0035_preference_model_unique'), ('sites', '0002_alter_domain_unique'), ] diff --git a/aleksis/apps/paweljong/migrations/0003_alter_event_feedback_aspects.py b/aleksis/apps/paweljong/migrations/0003_alter_event_feedback_aspects.py new file mode 100644 index 0000000000000000000000000000000000000000..6d1d673bacf4fb403f29270d9c739cfadcf2165a --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0003_alter_event_feedback_aspects.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2022-02-13 14:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('paweljong', '0002_event_website'), + ] + + operations = [ + migrations.AlterField( + model_name='event', + name='feedback_aspects', + field=models.ManyToManyField(blank=True, null=True, related_name='event', to='paweljong.FeedbackAspect', verbose_name='Feedback aspects'), + ), + ] diff --git a/aleksis/apps/paweljong/migrations/0004_richtext_field_information.py b/aleksis/apps/paweljong/migrations/0004_richtext_field_information.py new file mode 100644 index 0000000000000000000000000000000000000000..428b54724e90ae09ebb521f2cfd49511bfcf7a2c --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0004_richtext_field_information.py @@ -0,0 +1,30 @@ +# Generated by Django 3.2.12 on 2022-02-16 18:52 + +import ckeditor.fields +from django.db import migrations +import django_iban.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('paweljong', '0003_alter_event_feedback_aspects'), + ] + + operations = [ + migrations.RemoveField( + model_name='event', + name='website', + ), + migrations.AddField( + model_name='event', + name='information', + field=ckeditor.fields.RichTextField(default='', verbose_name='Information about the event'), + preserve_default=False, + ), + migrations.AlterField( + model_name='eventregistration', + name='iban', + field=django_iban.fields.IBANField(blank=True, enforce_database_constraint=True, max_length=34, null=True, verbose_name='IBAN (for SEPA direct debit)'), + ), + ] diff --git a/aleksis/apps/paweljong/migrations/0005_eventregistration_medical_information.py b/aleksis/apps/paweljong/migrations/0005_eventregistration_medical_information.py new file mode 100644 index 0000000000000000000000000000000000000000..23bd625af560e29e4d303600f180b3b70fb168b7 --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0005_eventregistration_medical_information.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2022-02-16 21:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('paweljong', '0004_richtext_field_information'), + ] + + operations = [ + migrations.AddField( + model_name='eventregistration', + name='medical_information', + field=models.TextField(blank=True, default='', verbose_name='Medical information / intolerances'), + ), + ] diff --git a/aleksis/apps/paweljong/migrations/0006_unique_constraints.py b/aleksis/apps/paweljong/migrations/0006_unique_constraints.py new file mode 100644 index 0000000000000000000000000000000000000000..945d2e5457bc33d54a0c8d0ea7bd3b45f8a68780 --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0006_unique_constraints.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.12 on 2022-02-18 14:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('paweljong', '0005_eventregistration_medical_information'), + ] + + operations = [ + migrations.AlterModelOptions( + name='eventregistration', + options={'verbose_name': 'Event registration', 'verbose_name_plural': 'Event registrations'}, + ), + migrations.AddConstraint( + model_name='eventfeedback', + constraint=models.UniqueConstraint(fields=('person', 'event'), name='unique_person_feedback_per_event'), + ), + migrations.AddConstraint( + model_name='eventregistration', + constraint=models.UniqueConstraint(fields=('person', 'event'), name='unique_person_registration_per_event'), + ), + ] diff --git a/aleksis/apps/paweljong/models.py b/aleksis/apps/paweljong/models.py index c8e21ca94d291b08e45de53b2ee30a11da8163a9..2b325aa644e2659d701e21651453096f54f0ecb4 100644 --- a/aleksis/apps/paweljong/models.py +++ b/aleksis/apps/paweljong/models.py @@ -1,12 +1,16 @@ +from datetime import datetime + from django.db import models -from django.utils import timezone 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) @@ -33,50 +37,54 @@ class Event(ExtensibleModel): # Other details cost = models.IntegerField(verbose_name=_("Cost in €")) max_participants = models.PositiveSmallIntegerField(verbose_name=_("Maximum participants")) - website = models.CharField(verbose_name=_("Website of event"), max_length=255) + information = RichTextField(verbose_name=_("Information about the event")) # Feedback feedback_aspects = models.ManyToManyField( - FeedbackAspect, verbose_name=_("Feedback aspects"), related_name="event" + 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 = timezone.now() + 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.group.members.count() >= self.max_participants: + if self.linked_group.members.count() >= self.max_participants: return False if self.date_registration: - return self.date_registration >= timezone.now() - return self.date_event > timezone.now() + return self.date_registration >= now + return self.date_event > now @property def booked_percentage(self): - return self.group.members.count() / self.max_participants * 100 + return self.linked_group.members.count() / self.max_participants * 100 @property def members_persons(self): - return self.group.members.all() + return self.linked_group.members.all() @property def owners_persons(self): - return self.group.owners.all() + return self.linked_group.owners.all() class EventFeedback(ExtensibleModel): - class Meta: - verbose_name = _("Event feedback") - verbose_name_plural = _("Event feedbacks") COMMENT_CHOICES = [ ("first", _("Only first name")), @@ -113,6 +121,15 @@ class EventFeedback(ExtensibleModel): 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: @@ -148,17 +165,22 @@ class Voucher(ExtensibleModel): 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): - class Meta: - verbose_name = _("Registration") - verbose_name_plural = _("Registrations") 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, @@ -174,6 +196,7 @@ class EventRegistration(ExtensibleModel): 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")) @@ -184,3 +207,12 @@ class EventRegistration(ExtensibleModel): 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" + ) + ]