From 5498dc97c67906575971925135af6dcc122e4bc8 Mon Sep 17 00:00:00 2001 From: Tom Teichler <tom.teichler@teckids.org> Date: Sun, 20 Feb 2022 18:03:01 +0100 Subject: [PATCH] Add term management --- aleksis/apps/paweljong/filters.py | 7 +- aleksis/apps/paweljong/forms.py | 52 +++++++-------- .../apps/paweljong/migrations/0007_terms.py | 65 +++++++++++++++++++ .../0008_remove_terms_from_event.py | 25 +++++++ aleksis/apps/paweljong/model_extensions.py | 10 --- aleksis/apps/paweljong/models.py | 26 ++++---- aleksis/apps/paweljong/tables.py | 48 +++++--------- .../templates/paweljong/term/create.html | 19 ++++++ .../templates/paweljong/term/edit.html | 13 ++++ .../templates/paweljong/term/list.html | 14 ++++ aleksis/apps/paweljong/urls.py | 28 ++++++-- 11 files changed, 219 insertions(+), 88 deletions(-) create mode 100644 aleksis/apps/paweljong/migrations/0007_terms.py create mode 100644 aleksis/apps/paweljong/migrations/0008_remove_terms_from_event.py delete mode 100644 aleksis/apps/paweljong/model_extensions.py create mode 100644 aleksis/apps/paweljong/templates/paweljong/term/create.html create mode 100644 aleksis/apps/paweljong/templates/paweljong/term/edit.html create mode 100644 aleksis/apps/paweljong/templates/paweljong/term/list.html diff --git a/aleksis/apps/paweljong/filters.py b/aleksis/apps/paweljong/filters.py index be18c0e..3cbf0a0 100644 --- a/aleksis/apps/paweljong/filters.py +++ b/aleksis/apps/paweljong/filters.py @@ -5,7 +5,7 @@ from material import Layout, Row from aleksis.core.filters import MultipleCharFilter -from .models import Event, EventRegistration, FeedbackAspect, Voucher +from .models import Event, EventRegistration, FeedbackAspect, Voucher, Terms class EventRegistrationFilter(FilterSet): @@ -53,6 +53,11 @@ class FeedbackAspectsFilter(FilterSet): model = FeedbackAspect fields = ["aspect"] +class TermsFilter(FilterSet): + class Meta: + model = Terms + fields = ["title"] + class EventFilter(FilterSet): class Meta: diff --git a/aleksis/apps/paweljong/forms.py b/aleksis/apps/paweljong/forms.py index 44c1fd6..176fe16 100644 --- a/aleksis/apps/paweljong/forms.py +++ b/aleksis/apps/paweljong/forms.py @@ -11,7 +11,7 @@ from phonenumber_field.formfields import PhoneNumberField from aleksis.core.mixins import ExtensibleForm from aleksis.core.models import Group, Person -from .models import Event, EventRegistration, FeedbackAspect, Voucher +from .models import Event, EventRegistration, FeedbackAspect, Voucher, Terms COMMENT_CHOICES = [ ("first", _("Only first name")), @@ -126,6 +126,7 @@ class EditEventForm(ExtensibleForm): Fieldset(_("Date data"), Row("date_event", "date_registration", "date_retraction")), Fieldset(_("Event details"), Row("cost", "max_participants"), "information"), Fieldset(_("Feedback aspects"), "feedback_aspects"), + Fieldset(_("Terms"), "terms"), ), ) @@ -143,6 +144,7 @@ class EditEventForm(ExtensibleForm): "cost", "max_participants", "feedback_aspects", + "terms", "information", ] widgets = { @@ -154,6 +156,10 @@ class EditEventForm(ExtensibleForm): search_fields=["aspect__icontains"], attrs={"data-minimum-input-length": 0, "class": "browser-default"}, ), + "terms": ModelSelect2MultipleWidget( + search_fields=["aspect__icontains"], + attrs={"data-minimum-input-length": 0, "class": "browser-default"}, + ), } @@ -249,7 +255,7 @@ class RegisterEventGuardians(ExtensibleForm): class RegisterEventContactDetails(ExtensibleForm): class Meta: - model = EventRegistration + model = Group fields = [] layout = Layout( @@ -427,34 +433,21 @@ class RegisterEventFinancial(ExtensibleForm): class RegisterEventConsent(ExtensibleForm): - layout = Layout( - Fieldset( - _("Declaration of consent"), - Row("accept_terms", "accept_data", "accept_general_terms"), - ), - ) - class Meta: model = EventRegistration - fields = ["accept_terms", "accept_data", "accept_general_terms"] - help_texts = { - "accept_terms": _( - "Parents: My child filled out the registration form themselves, and in my presence. " - "I agree with the participation, the terms of use and the terms and conditions. " - "I am aware that the registration is binding and that withdrawal is only possible " - "in exceptional cases with an important reason. In addition, I agree to pay the " - "participation fee in advance and agree to the reimbursement guidelines " - "mentioned above." - ), - "accept_data": _( - "I consent to the processing of my data as stated in the " - "terms of use and all the data provided is correct. If I am under the " - "age of 16, my parents also agree to this and I can prove this on request " - "(e.g. by making contact with my parents)." - ), - "accept_general_terms": _("I agree with the terms and conditions and have read them."), - } + fields = [] + def __init__(self, event, *args, **kwargs): + super().__init__(*args, **kwargs) + + for field in event.terms.all(): + field_instance = forms.BooleanField( + help_text=field.term, + required=True, + ) + self.fields[field.title] = field_instance + node = Fieldset(f"{field.title}", f"{field.title}") + self.add_node_to_layout(node) class EditEventRegistrationForm(forms.ModelForm): @@ -527,6 +520,11 @@ class EditFeedbackAspectForm(forms.ModelForm): model = FeedbackAspect exclude = [] +class EditTermForm(forms.ModelForm): + class Meta: + model = Terms + exclude = [] + class RegisterEventAccount(SignupForm, ExtensibleForm): """Form to register new user accounts.""" diff --git a/aleksis/apps/paweljong/migrations/0007_terms.py b/aleksis/apps/paweljong/migrations/0007_terms.py new file mode 100644 index 0000000..71a1002 --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0007_terms.py @@ -0,0 +1,65 @@ +# 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'), + ), + ] diff --git a/aleksis/apps/paweljong/migrations/0008_remove_terms_from_event.py b/aleksis/apps/paweljong/migrations/0008_remove_terms_from_event.py new file mode 100644 index 0000000..244a64b --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0008_remove_terms_from_event.py @@ -0,0 +1,25 @@ +# 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', + ), + ] diff --git a/aleksis/apps/paweljong/model_extensions.py b/aleksis/apps/paweljong/model_extensions.py deleted file mode 100644 index 09f8924..0000000 --- a/aleksis/apps/paweljong/model_extensions.py +++ /dev/null @@ -1,10 +0,0 @@ -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"))) diff --git a/aleksis/apps/paweljong/models.py b/aleksis/apps/paweljong/models.py index 2b325aa..7fa1cf9 100644 --- a/aleksis/apps/paweljong/models.py +++ b/aleksis/apps/paweljong/models.py @@ -8,8 +8,7 @@ from django_iban.fields import IBANField from aleksis.core.mixins import ExtensibleModel from aleksis.core.models import Group, Person - -from .util import generate_code +from aleksis.core.util.core_helpers import generate_random_code class FeedbackAspect(ExtensibleModel): @@ -19,6 +18,14 @@ class FeedbackAspect(ExtensibleModel): return self.aspect +class Terms(ExtensibleModel): + title = models.CharField(max_length=255, verbose_name=_("Title")) + term = RichTextField(verbose_name=_("Term")) + + def __str__(self) -> str: + return self.title + + class Event(ExtensibleModel): # Event details display_name = models.CharField(verbose_name=_("Display name"), max_length=255) @@ -38,13 +45,13 @@ class Event(ExtensibleModel): cost = models.IntegerField(verbose_name=_("Cost in €")) max_participants = models.PositiveSmallIntegerField(verbose_name=_("Maximum participants")) 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", - null=True, blank=True, ) @@ -167,7 +174,7 @@ class Voucher(ExtensibleModel): def save(self, *args, **kwargs): if not self.code: - self.code = generate_code() + self.code = generate_random_code(5, 3) super().save(*args, **kwargs) @@ -177,11 +184,14 @@ class EventRegistration(ExtensibleModel): person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person")) date_registred = 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="") 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, @@ -199,12 +209,6 @@ class EventRegistration(ExtensibleModel): 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}" diff --git a/aleksis/apps/paweljong/tables.py b/aleksis/apps/paweljong/tables.py index 2194650..fa44166 100644 --- a/aleksis/apps/paweljong/tables.py +++ b/aleksis/apps/paweljong/tables.py @@ -4,38 +4,6 @@ import django_tables2 as tables from django_tables2.utils import A -class EventsTable(tables.Table): - class Meta: - attrs = {"class": "responsive-table highlight"} - - display_name = tables.Column(verbose_name=_("Event")) - date_event = tables.Column(verbose_name=_("Date")) - max_participants = tables.Column(verbose_name=_("Max. participants")) - date_registration = tables.Column(verbose_name=_("Registration until")) - - register = tables.LinkColumn( - "register_event_by_pk", - args=[A("id")], - verbose_name=_("Register"), - text=_("Register"), - ) - - -class ParticipatedEventsTable(tables.Table): - class Meta: - attrs = {"class": "responsive-table highlight"} - - display_name = tables.Column(verbose_name=_("Event")) - date_event = tables.Column(verbose_name=_("Date")) - - feedback = tables.LinkColumn( - "feedback_event_by_pk", - args=[A("id")], - verbose_name=_("Feedback"), - text=_("Feedback"), - ) - - class ManageEventsTable(tables.Table): class Meta: attrs = {"class": "responsive-table highlight"} @@ -46,7 +14,7 @@ class ManageEventsTable(tables.Table): date_registration = tables.Column(verbose_name=_("Registration until")) edit = tables.LinkColumn( - "edit_event_by_pk", args=[A("id")], verbose_name=_("Edit"), text=_("Edit") + "edit_event_by_slug", args=[A("linked_group__short_name")], verbose_name=_("Edit"), text=_("Edit") ) @@ -99,3 +67,17 @@ class FeedbackAspectsTable(tables.Table): verbose_name=_("Edit"), text=_("Edit"), ) + + +class TermsTable(tables.Table): + class Meta: + attrs = {"class": "responsive-table highlight"} + + title = tables.Column() + + edit = tables.LinkColumn( + "edit_term_by_pk", + args=[A("id")], + verbose_name=_("Edit"), + text=_("Edit"), + ) diff --git a/aleksis/apps/paweljong/templates/paweljong/term/create.html b/aleksis/apps/paweljong/templates/paweljong/term/create.html new file mode 100644 index 0000000..e3db75f --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/term/create.html @@ -0,0 +1,19 @@ +{% extends "core/base.html" %} +{% load material_form i18n %} + +{% block page_title %}{% blocktrans %}Create term{% endblocktrans %}{% endblock %} +{% block browser_title %}{% blocktrans %}Create term{% endblocktrans %}{% endblock %} + +{% block extra_head %} + {{ form.media.css }} +{% endblock %} + +{% block content %} + <form method="post"> + {% csrf_token %} + {% form form=form %}{% endform %} + {% include "core/partials/save_button.html" %} + </form> + + {{ form.media.js }} +{% endblock %} diff --git a/aleksis/apps/paweljong/templates/paweljong/term/edit.html b/aleksis/apps/paweljong/templates/paweljong/term/edit.html new file mode 100644 index 0000000..1a467f0 --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/term/edit.html @@ -0,0 +1,13 @@ +{% extends "core/base.html" %} +{% load material_form i18n %} + +{% block page_title %}{% blocktrans %}Edit term{% endblocktrans %}{% endblock %} +{% block browser_title %}{% blocktrans %}Edit term{% endblocktrans %}{% endblock %} + +{% block content %} + <form method="post"> + {% csrf_token %} + {% form form=form %}{% endform %} + {% include "core/partials/save_button.html" %} + </form> +{% endblock %} diff --git a/aleksis/apps/paweljong/templates/paweljong/term/list.html b/aleksis/apps/paweljong/templates/paweljong/term/list.html new file mode 100644 index 0000000..9af6321 --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/term/list.html @@ -0,0 +1,14 @@ +{% extends "core/base.html" %} +{% load material_form i18n %} + +{% load render_table from django_tables2 %} + +{% block page_title %}{% blocktrans %}Terms{% endblocktrans %}{% endblock %} +{% block browser_title %}{% blocktrans %}Terms{% endblocktrans %}{% endblock %} + +{% block content %} + + <a class="btn colour-primary waves-effect waves-light" href="{% url 'create_term' %}">{% trans "Create term" %}</a> + {% render_table table %} + +{% endblock %} diff --git a/aleksis/apps/paweljong/urls.py b/aleksis/apps/paweljong/urls.py index 7b97f61..6b3ac9d 100644 --- a/aleksis/apps/paweljong/urls.py +++ b/aleksis/apps/paweljong/urls.py @@ -27,16 +27,16 @@ condition_dict = { } urlpatterns = [ - path("event/<int:pk>/edit", views.EditEventView.as_view(), name="edit_event_by_pk"), - path("event/<int:pk>/feedback", views.feedback_event, name="feedback_event_by_pk"), + path("event/<slug:slug>/edit", views.EditEventView.as_view(), name="edit_event_by_slug"), + path("event/<slug:slug>/feedback", views.feedback_event, name="feedback_event_by_slug"), path( - "event/<int:pk>/register", + "event/<slug:slug>/register", views.RegisterEventWizardView.as_view(register_forms, condition_dict=condition_dict), - name="register_event_by_id", + name="register_event_by_slug", ), path("event/<slug:slug>", views.EventFullView.as_view(), name="event_by_name"), - path("event/<slug:slug>/register", views.RegisterEventStart.as_view(), name="register_event_by_name"), - path("misc/set_email_needed/<int:pk>", views.set_email_needed, name="set_email_needed"), + path("event/<slug:slug>/start", views.RegisterEventStart.as_view(), name="register_event_by_slug_start"), + path("misc/set_email_needed/<slug:slug>", views.set_email_needed, name="set_email_needed"), path("events/create", views.CreateEventView.as_view(), name="create_event"), path("events/manage", views.manage_events, name="manage_events"), path("vouchers/create", views.VoucherCreateView.as_view(), name="create_vouchers"), @@ -78,4 +78,20 @@ urlpatterns = [ views.FeedbackAspectEditView.as_view(), name="edit_feedback_aspect_by_pk", ), + path( + "event/terms/list", + views.TermListView.as_view(), + name="terms", + ), + path( + "event/terms/create", + views.TermCreateView.as_view(), + name="create_term", + ), + path( + "event/terms/<int:pk>/edit", + views.TermEditView.as_view(), + name="edit_term_by_pk", + ), + ] -- GitLab