Skip to content
Snippets Groups Projects
Commit 1eab6c70 authored by Tom Teichler's avatar Tom Teichler :beers:
Browse files

Merge branch 'copy-from-ticdesk' into 'master'

Reformat and cleanup

See merge request !1
parents 0a93d060 51e1353a
No related branches found
No related tags found
1 merge request!1Reformat and cleanup
Pipeline #56208 passed
Showing
with 1390 additions and 1298 deletions
...@@ -64,6 +64,8 @@ docs/_build/ ...@@ -64,6 +64,8 @@ docs/_build/
# Generated files # Generated files
aleksis/node_modules/ aleksis/node_modules/
aleksis/static/ aleksis/static/
aleksis/whoosh_index/
poetry.lock
.coverage .coverage
.mypy_cache/ .mypy_cache/
...@@ -72,3 +74,8 @@ htmlcov/ ...@@ -72,3 +74,8 @@ htmlcov/
maintenance_mode_state.txt maintenance_mode_state.txt
media/ media/
package-lock.json package-lock.json
# VSCode
.vscode/
.history/
*.code-workspace
include: include:
- project: "AlekSIS/official/AlekSIS" - project: "AlekSIS/official/AlekSIS"
file: /ci/general.yml file: /ci/general.yml
# - project: "AlekSIS/official/AlekSIS" - project: "AlekSIS/official/AlekSIS"
# file: /ci/test.yml file: /ci/prepare/lock.yml
- project: "AlekSIS/official/AlekSIS" - project: "AlekSIS/official/AlekSIS"
file: /ci/test/lint.yml file: /ci/test/lint.yml
- project: "AlekSIS/official/AlekSIS" - project: "AlekSIS/official/AlekSIS"
file: /ci/test/security.yml file: /ci/test/security.yml
- project: "AlekSIS/official/AlekSIS" - project: "AlekSIS/official/AlekSIS"
file: /ci/build/dist.yml file: /ci/build/dist.yml
- project: "AlekSIS/official/AlekSIS"
file: /ci/docker/dist.yml
variables:
GIT_SUBMODULE_STRATEGY: recursive
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
FF_NETWORK_PER_BUILD: "true"
POETRY_REPOSITORIES_GITLAB_URL: "$CI_API_V4_URL/projects/${CI_PROJECT_ID}/packages/pypi"
POETRY_HTTP_BASIC_GITLAB_USERNAME: gitlab-ci-token
POETRY_HTTP_BASIC_GITLAB_PASSWORD: "$CI_JOB_TOKEN"
POETRY_PYPI_TOKEN_PYPI: "$TICDESK_PUBLISH_TOKEN"
deploy_gitlab:
interruptible: true
stage: publish
script:
- if [ x$CI_COMMIT_REF_NAME = x$CI_COMMIT_TAG ]; then
if ! [ "$(poetry version | cut -d" " -f2)" = $CI_COMMIT_REF_NAME ]; then
echo "Package version does not match tag. Aborting build of tag!" >/dev/fd/2 ;
exit 1 ;
fi ;
else
poetry version $(poetry version | cut -d" " -f2)+$(date --date=${CI_COMMIT_TIMESTAMP} +%Y%m%d%H%M%S).${CI_COMMIT_SHORT_SHA} ;
fi
- poetry publish -r gitlab
...@@ -16,7 +16,8 @@ Licence ...@@ -16,7 +16,8 @@ Licence
:: ::
Copyright © 2021 Dominik George <dominik.george@teckids.org> Copyright © 2018, 2021 Dominik George <dominik.george@teckids.org>
Copyright © 2019, 2022 Tom Teichler <tom.teichler@teckids.org>
Licenced under the EUPL, version 1.2 or later Licenced under the EUPL, version 1.2 or later
...@@ -32,6 +33,6 @@ AlekSIS® is a registered trademark of the AlekSIS open source project, represen ...@@ -32,6 +33,6 @@ AlekSIS® is a registered trademark of the AlekSIS open source project, represen
by Teckids e.V. Please refer to the `trademark policy`_ for hints on using the trademark by Teckids e.V. Please refer to the `trademark policy`_ for hints on using the trademark
AlekSIS®. AlekSIS®.
.. _AlekSIS: https://edugit.org/AlekSIS/AlekSIS .. _AlekSIS®: https://edugit.org/AlekSIS/AlekSIS
.. _European Union Public Licence: https://eupl.eu/ .. _European Union Public Licence: https://eupl.eu/
.. _trademark policy: https://aleksis.org/pages/about .. _trademark policy: https://aleksis.org/pages/about
...@@ -7,7 +7,10 @@ class DefaultConfig(AppConfig): ...@@ -7,7 +7,10 @@ class DefaultConfig(AppConfig):
dist_name = "AlekSIS-App-Paweljong" dist_name = "AlekSIS-App-Paweljong"
urls = { urls = {
"Repository": "https://edugit.org//hacknfun//AlekSIS-App-Paweljong", "Repository": "https://edugit.org/Teckids/hacknfun/AlekSIS-App-Paweljong",
} }
licence = "EUPL-1.2+" licence = "EUPL-1.2+"
copyright_info = (([2021], "Dominik George", "dominik.george@.org"),) copyright_info = (
([2018, 2021], "Dominik George", "dominik.george@teckids.org"),
([2019, 2022], "Tom Teichler", "tom.teichler@teckids.org"),
)
...@@ -5,27 +5,27 @@ from material import Layout, Row ...@@ -5,27 +5,27 @@ from material import Layout, Row
from aleksis.core.filters import MultipleCharFilter from aleksis.core.filters import MultipleCharFilter
from .models import EventRegistration, FeedbackAspect, Voucher from .models import Event, EventRegistration, Terms, Voucher
class EventRegistrationFilter(FilterSet): class EventRegistrationFilter(FilterSet):
class Meta: class Meta:
model = EventRegistration model = EventRegistration
fields = ["person", "event", "accept_sepa", "date_registred"] fields = ["person", "event", "accept_sepa", "date_registered"]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.form.layout = Layout( self.form.layout = Layout(
Row("person", "event"), Row("person", "event"),
Row("accept_sepa", "date_registred"), Row("accept_sepa", "date_registered"),
) )
class VoucherFilter(FilterSet): class VoucherFilter(FilterSet):
event = MultipleCharFilter( event = MultipleCharFilter(
[ [
"event__short_name__icontains", "event__display_name__icontains",
], ],
label=_("Search by event"), label=_("Search by event"),
) )
...@@ -48,7 +48,21 @@ class VoucherFilter(FilterSet): ...@@ -48,7 +48,21 @@ class VoucherFilter(FilterSet):
self.form.layout = Layout(Row("event", "name")) self.form.layout = Layout(Row("event", "name"))
class FeedbackAspectsFilter(FilterSet): class TermsFilter(FilterSet):
class Meta: class Meta:
model = FeedbackAspect model = Terms
fields = ["aspect"] fields = ["title"]
class EventFilter(FilterSet):
class Meta:
model = Event
fields = ["display_name", "published", "place"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form.layout = Layout(
Row("display_name"),
Row("published", "place"),
)
This diff is collapsed.
This diff is collapsed.
...@@ -4,47 +4,6 @@ MENUS = { ...@@ -4,47 +4,6 @@ MENUS = {
"NAV_MENU_CORE": [ "NAV_MENU_CORE": [
{ {
"name": _("Events"), "name": _("Events"),
"url": "events",
"icon": "event",
},
{
"name": _("Vouchers"),
"url": "#",
"icon": "confirmation_number",
"root": True,
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"paweljong.view_vouchers_rule",
)
],
"submenu": [
{
"name": _("Voucher overview"),
"url": "vouchers",
"icon": "confirmation_number",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"paweljong.change_vouchers_rule",
)
],
},
{
"name": _("Create voucher"),
"url": "create_vouchers",
"icon": "post_add",
"validator": [
(
"aleksis.core.util.predicates.permission_validator",
"paweljong.create_vouchers_rule",
)
],
},
],
},
{
"name": _("Event management"),
"url": "#", "url": "#",
"icon": "event_note", "icon": "event_note",
"root": True, "root": True,
...@@ -56,24 +15,24 @@ MENUS = { ...@@ -56,24 +15,24 @@ MENUS = {
], ],
"submenu": [ "submenu": [
{ {
"name": _("Create event"), "name": _("Vouchers"),
"url": "create_event", "url": "vouchers",
"icon": "event_available", "icon": "confirmation_number",
"validators": [ "validators": [
( (
"aleksis.core.util.predicates.permission_validator", "aleksis.core.util.predicates.permission_validator",
"paweljong.create_events_rule", "paweljong.view_vouchers_rule",
) )
], ],
}, },
{ {
"name": _("Manage feedback aspects"), "name": _("Terms"),
"url": "feedback_aspects", "url": "terms",
"icon": "rate_review", "icon": "gavel",
"validators": [ "validators": [
( (
"aleksis.core.util.predicates.permission_validator", "aleksis.core.util.predicates.permission_validator",
"paweljong.view_feedback_aspects_rule", "paweljong.view_terms_rule",
) )
], ],
}, },
...@@ -89,9 +48,9 @@ MENUS = { ...@@ -89,9 +48,9 @@ MENUS = {
], ],
}, },
{ {
"name": _("Manage upcoming events"), "name": _("Upcoming events"),
"url": "manage_events", "url": "manage_events",
"icon": "change", "icon": "edit",
"validators": [ "validators": [
( (
"aleksis.core.util.predicates.permission_validator", "aleksis.core.util.predicates.permission_validator",
...@@ -100,7 +59,7 @@ MENUS = { ...@@ -100,7 +59,7 @@ MENUS = {
], ],
}, },
{ {
"name": _("Manage registrations"), "name": _("Registrations"),
"url": "registrations", "url": "registrations",
"icon": "how_to_reg", "icon": "how_to_reg",
"validators": [ "validators": [
......
...@@ -11,7 +11,7 @@ class Migration(migrations.Migration): ...@@ -11,7 +11,7 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('core', '0028_alter_globalpermissions_options'), ('core', '0035_preference_model_unique'),
('sites', '0002_alter_domain_unique'), ('sites', '0002_alter_domain_unique'),
] ]
...@@ -80,7 +80,7 @@ class Migration(migrations.Migration): ...@@ -80,7 +80,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('extended_data', models.JSONField(default=dict, editable=False)), ('extended_data', models.JSONField(default=dict, editable=False)),
('date_registred', models.DateTimeField(auto_now_add=True, verbose_name='Registration date')), ('date_registered', models.DateTimeField(auto_now_add=True, verbose_name='Registration date')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment / remarks')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment / remarks')),
('channel', models.CharField(blank=True, default='', max_length=255, verbose_name='Channel')), ('channel', models.CharField(blank=True, default='', max_length=255, verbose_name='Channel')),
('donation', models.PositiveIntegerField(blank=True, null=True, verbose_name='Donation')), ('donation', models.PositiveIntegerField(blank=True, null=True, verbose_name='Donation')),
......
# 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'),
),
]
# 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)'),
),
]
# 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'),
),
]
# 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'),
),
]
# Generated by Django 3.2.12 on 2022-02-20 15:24
import ckeditor.fields
import django.contrib.sites.managers
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('sites', '0002_alter_domain_unique'),
('paweljong', '0006_unique_constraints'),
]
operations = [
migrations.RemoveField(
model_name='eventregistration',
name='channel',
),
migrations.AddField(
model_name='eventregistration',
name='school',
field=models.CharField(default='', max_length=255, verbose_name='Name of school'),
preserve_default=False,
),
migrations.AddField(
model_name='eventregistration',
name='school_class',
field=models.CharField(default='', max_length=255, verbose_name='School class'),
preserve_default=False,
),
migrations.AddField(
model_name='eventregistration',
name='school_place',
field=models.CharField(default='', max_length=255, verbose_name='Place of the school'),
preserve_default=False,
),
migrations.AlterField(
model_name='event',
name='feedback_aspects',
field=models.ManyToManyField(blank=True, related_name='event', to='paweljong.FeedbackAspect', verbose_name='Feedback aspects'),
),
migrations.CreateModel(
name='Terms',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('extended_data', models.JSONField(default=dict, editable=False)),
('title', models.CharField(max_length=255, verbose_name='Title')),
('term', ckeditor.fields.RichTextField(verbose_name='Term')),
('site', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.site')),
],
options={
'abstract': False,
},
managers=[
('objects', django.contrib.sites.managers.CurrentSiteManager()),
],
),
migrations.AddField(
model_name='event',
name='terms',
field=models.ManyToManyField(blank=True, related_name='event', to='paweljong.Terms', verbose_name='Terms'),
),
]
# Generated by Django 3.2.12 on 2022-02-20 16:53
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('paweljong', '0007_terms'),
]
operations = [
migrations.RemoveField(
model_name='eventregistration',
name='accept_data',
),
migrations.RemoveField(
model_name='eventregistration',
name='accept_general_terms',
),
migrations.RemoveField(
model_name='eventregistration',
name='accept_terms',
),
]
# Generated by Django 3.2.12 on 2022-02-20 17:36
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('paweljong', '0008_remove_terms_from_event'),
]
operations = [
migrations.RemoveField(
model_name='feedbackaspect',
name='site',
),
migrations.RemoveField(
model_name='event',
name='feedback_aspects',
),
migrations.DeleteModel(
name='EventFeedback',
),
migrations.DeleteModel(
name='FeedbackAspect',
),
]
# Generated by Django 3.2.12 on 2022-02-20 21:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('paweljong', '0009_remove_feedback'),
]
operations = [
migrations.AddField(
model_name='terms',
name='confirmation_text',
field=models.TextField(default='', verbose_name='Confirmation text'),
preserve_default=False,
),
]
# Generated by Django 3.2.12 on 2022-02-20 22:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('paweljong', '0010_term_confirmation_text'),
]
operations = [
migrations.AddField(
model_name='eventregistration',
name='accepted_terms',
field=models.ManyToManyField(related_name='registrations', to='paweljong.Terms', verbose_name='Accepted terms'),
),
]
from django.utils.translation import gettext_lazy as _
from jsonstore import CharField
from aleksis.core.models import Person
# Additional fields for persons
Person.field(school=CharField(verbose_name=_("Name of school")))
Person.field(school_class=CharField(verbose_name=_("School class")))
Person.field(school_place=CharField(verbose_name=_("Place of the school")))
from datetime import datetime
from django.db import models from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from ckeditor.fields import RichTextField
from django_iban.fields import IBANField from django_iban.fields import IBANField
from aleksis.core.mixins import ExtensibleModel from aleksis.core.mixins import ExtensibleModel
from aleksis.core.models import Group, Person from aleksis.core.models import Group, Person
from aleksis.core.util.core_helpers import generate_random_code
class FeedbackAspect(ExtensibleModel): class Terms(ExtensibleModel):
aspect = models.CharField(max_length=100) title = models.CharField(max_length=255, verbose_name=_("Title"))
term = RichTextField(verbose_name=_("Term"))
confirmation_text = models.TextField(verbose_name=_("Confirmation text"))
def __str__(self) -> str: def __str__(self) -> str:
return self.aspect return self.title
class Event(ExtensibleModel): class Event(ExtensibleModel):
...@@ -33,85 +38,46 @@ class Event(ExtensibleModel): ...@@ -33,85 +38,46 @@ class Event(ExtensibleModel):
# Other details # Other details
cost = models.IntegerField(verbose_name=_("Cost in €")) cost = models.IntegerField(verbose_name=_("Cost in €"))
max_participants = models.PositiveSmallIntegerField(verbose_name=_("Maximum participants")) 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"))
terms = models.ManyToManyField(Terms, verbose_name=_("Terms"), related_name="event", blank=True)
# Feedback
feedback_aspects = models.ManyToManyField(
FeedbackAspect, verbose_name=_("Feedback aspects"), related_name="event"
)
def __str__(self) -> str: def __str__(self) -> str:
return self.display_name return self.display_name
def can_register(self, request=None): def can_register(self, request=None):
now = timezone.now() now = datetime.today().date()
if request and request.user.is_authenticated: if request and request.user.is_authenticated:
if request.user.person in self.linked_group.members.all():
return False
if EventRegistration.objects.filter(person=request.user.person).exists():
return False
if ( if (
Voucher.objects.filter(event=self, person=request.user.person, used=False).count() Voucher.objects.filter(event=self, person=request.user.person, used=False).count()
> 0 > 0
): ):
return True return True
if self.group.members.count() >= self.max_participants: if self.linked_group.members.count() >= self.max_participants:
return False return False
if self.date_registration: if self.date_registration:
return self.date_registration >= timezone.now() return self.date_registration >= now
return self.date_event > timezone.now() return self.date_event > now
@property @property
def booked_percentage(self): def booked_percentage(self):
return self.group.members.count() / self.max_participants * 100 return self.linked_group.members.count() / self.max_participants * 100
@property @property
def members_persons(self): def members_persons(self):
return self.group.members.all() return self.linked_group.members.all()
@property @property
def owners_persons(self): 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")),
("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 Voucher(ExtensibleModel):
...@@ -148,18 +114,26 @@ class Voucher(ExtensibleModel): ...@@ -148,18 +114,26 @@ class Voucher(ExtensibleModel):
def __str__(self) -> str: def __str__(self) -> str:
return self.code return self.code
def save(self, *args, **kwargs):
if not self.code:
self.code = generate_random_code(5, 3)
super().save(*args, **kwargs)
class EventRegistration(ExtensibleModel): class EventRegistration(ExtensibleModel):
class Meta:
verbose_name = _("Registration")
verbose_name_plural = _("Registrations")
event = models.ForeignKey(Event, on_delete=models.CASCADE, verbose_name=_("Event")) event = models.ForeignKey(Event, on_delete=models.CASCADE, verbose_name=_("Event"))
person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person")) person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person"))
date_registred = models.DateTimeField(auto_now_add=True, verbose_name=_("Registration date")) date_registered = models.DateTimeField(auto_now_add=True, verbose_name=_("Registration date"))
school = models.CharField(verbose_name=_("Name of school"), max_length=255)
school_class = models.CharField(verbose_name=_("School class"), max_length=255)
school_place = models.CharField(verbose_name=_("Place of the school"), max_length=255)
comment = models.TextField(verbose_name=_("Comment / remarks"), blank=True, default="") comment = models.TextField(verbose_name=_("Comment / remarks"), blank=True, default="")
channel = models.CharField(verbose_name=_("Channel"), max_length=255, blank=True, default="") medical_information = models.TextField(
verbose_name=_("Medical information / intolerances"), blank=True, default=""
)
voucher = models.ForeignKey( voucher = models.ForeignKey(
Voucher, Voucher,
on_delete=models.CASCADE, on_delete=models.CASCADE,
...@@ -168,19 +142,28 @@ class EventRegistration(ExtensibleModel): ...@@ -168,19 +142,28 @@ class EventRegistration(ExtensibleModel):
null=True, null=True,
) )
donation = models.PositiveIntegerField(verbose_name=_("Donation"), blank=True, null=True) donation = models.PositiveIntegerField(verbose_name=_("Donation"), blank=True, null=True)
accepted_terms = models.ManyToManyField(
Terms,
verbose_name=_("Accepted terms"),
related_name="registrations",
)
accept_sepa = models.BooleanField(verbose_name=_("SEPA direct debit")) accept_sepa = models.BooleanField(verbose_name=_("SEPA direct debit"))
iban = IBANField( iban = IBANField(
verbose_name=_("IBAN (for SEPA direct debit)"), verbose_name=_("IBAN (for SEPA direct debit)"),
enforce_database_constraint=True, enforce_database_constraint=True,
null=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: def __str__(self) -> str:
return f"{self.event}, {self.person.first_name} {self.person.last_name}" 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"
)
]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment