From 5d564e1d62360dac2e18c66b4c4cae60fea918e2 Mon Sep 17 00:00:00 2001
From: Tom Teichler <t.teichler@babiel.com>
Date: Tue, 30 Nov 2021 16:23:44 +0100
Subject: [PATCH] Add models from TIC-Desk

---
 aleksis/apps/paweljong/models.py | 154 ++++++++++++++++++++++++++++++-
 poetry.lock                      |  18 +++-
 pyproject.toml                   |   1 +
 3 files changed, 171 insertions(+), 2 deletions(-)

diff --git a/aleksis/apps/paweljong/models.py b/aleksis/apps/paweljong/models.py
index 1b928df..0d73696 100644
--- a/aleksis/apps/paweljong/models.py
+++ b/aleksis/apps/paweljong/models.py
@@ -1,7 +1,18 @@
 from django.db import models
+from django.utils import timezone
+from django.utils.translation import gettext_lazy as _
+
+from django_iban.fields import IBANField
 
 from aleksis.core.mixins import ExtensibleModel
-from aleksis.core.models import Group
+from aleksis.core.models import Group, Person
+
+
+class FeedbackAspect(ExtensibleModel):
+    aspect = models.CharField(max_length=100)
+
+    def __str__(self) -> str:
+        return self.aspect
 
 
 class Event(ExtensibleModel):
@@ -22,3 +33,144 @@ class Event(ExtensibleModel):
     # Other details
     cost = models.IntegerField(verbose_name=_("Cost in €"))
     max_participants = models.PositiveSmallIntegerField(verbose_name=_("Maximum participants"))
+
+    # Feedback
+    feedback_aspects = models.ManyToManyField(
+        FeedbackAspect, verbose_name=_("Feedback aspects"), related_name="event"
+    )
+
+    def __str__(self) -> str:
+        return self.display_name
+
+    def can_register(self, request=None):
+        now = timezone.now()
+
+        if request and request.user.is_authenticated:
+            if (
+                Voucher.objects.filter(event=self, person=request.user.person, used=False).count()
+                > 0
+            ):
+                return True
+
+        if self.group.members.count() >= self.max_participants:
+            return False
+
+        if self.date_registration:
+            return self.date_registration >= timezone.now()
+        return self.date_event > timezone.now()
+
+    @property
+    def booked_percentage(self):
+        return self.group.members.count() / self.max_participants * 100
+
+    @property
+    def members_persons(self):
+        return self.group.members.all()
+
+    @property
+    def owners_persons(self):
+        return self.group.owners.all()
+
+
+class EventFeedback(ExtensibleModel):
+    class Meta:
+        verbose_name = _("Event feedback")
+        verbose_name_plural = _("Event feedbacks")
+
+    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 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
+
+
+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="")
+    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,
+    )
+
+    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}"
diff --git a/poetry.lock b/poetry.lock
index 07e15fa..7e3cd94 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1175,6 +1175,19 @@ type = "legacy"
 url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
 reference = "gitlab"
 
+[[package]]
+name = "django-iban-field"
+version = "0.8"
+description = "IBAN field for django with validation and optional postgresql in database constraint checking"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.source]
+type = "legacy"
+url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
+reference = "gitlab"
+
 [[package]]
 name = "django-impersonate"
 version = "1.7.3"
@@ -3868,7 +3881,7 @@ reference = "gitlab"
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.9"
-content-hash = "1daf52479c94c478c93578347499b38a06fae34b9921aa7a08d5d7501def6a43"
+content-hash = "4fba522bc9b8e3ead49950003648e14b7dcd33d404ec2689344e23b1b3974c35"
 
 [metadata.files]
 alabaster = [
@@ -4231,6 +4244,9 @@ django-health-check = [
     {file = "django-health-check-3.16.4.tar.gz", hash = "sha256:334bcbbb9273a6dbd9c928e78474306e623dfb38cc442281cb9fd230a20a7fdb"},
     {file = "django_health_check-3.16.4-py2.py3-none-any.whl", hash = "sha256:86a8869d67e72394a1dd73e37819a7d2cfd915588b96927fda611d7451fd4735"},
 ]
+django-iban-field = [
+    {file = "django_iban_field-0.8-py2.py3-none-any.whl", hash = "sha256:9d11eacb49b939702aa169aa0a3c9880970ed087c236279c32c26f86c7e10092"},
+]
 django-impersonate = [
     {file = "django-impersonate-1.7.3.tar.gz", hash = "sha256:282003957577c7143fe31e5861f8fffdf6fe0c25557aedb28fcf8b11474eaa23"},
 ]
diff --git a/pyproject.toml b/pyproject.toml
index 922f285..c917331 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -27,6 +27,7 @@ secondary = true
 [tool.poetry.dependencies]
 python = "^3.9"
 aleksis-core = "^2.2"
+django-iban-field = "^0.8"
 
 [tool.poetry.dev-dependencies]
 aleksis-builddeps = "*"
-- 
GitLab