diff --git a/aleksis/apps/paweljong/filters.py b/aleksis/apps/paweljong/filters.py index 430b07b5d05a626d0d53254c0bf4517cf679e392..7ae7dc2ae39c7bc2ca965b8befd7b864d08a63e3 100644 --- a/aleksis/apps/paweljong/filters.py +++ b/aleksis/apps/paweljong/filters.py @@ -11,13 +11,13 @@ from .models import Event, EventRegistration, Terms, Voucher class EventRegistrationFilter(FilterSet): class Meta: model = EventRegistration - fields = ["person", "event", "accept_sepa", "date_registered"] + fields = ["person", "event", "accept_sepa", "date_registered", "states"] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form.layout = Layout( - Row("person", "event"), + Row("person", "event", "states"), Row("accept_sepa", "date_registered"), ) diff --git a/aleksis/apps/paweljong/forms.py b/aleksis/apps/paweljong/forms.py index 8a51d714bb6b574bc8412ed83d535800d6f16fb3..d710f90b299d7a74250df8b2967223f1d453bc6a 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, InfoMailing, Terms, Voucher +from .models import Event, EventRegistration, InfoMailing, Terms, Voucher, RegistrationState COMMENT_CHOICES = [ ("first", _("Only first name")), @@ -404,20 +404,13 @@ class RegisterEventConsent(ExtensibleForm): class EditEventRegistrationForm(forms.ModelForm): layout = Layout( - Fieldset( - _("General event information"), - Row("event", "person"), - Row("comment"), - ), - Fieldset( - _("Financial data"), - "voucher_code", - Row("iban", "donation", "accept_sepa"), - ), - Fieldset( - _("Declaration of consent"), - Row("accept_terms", "accept_data", "accept_general_terms"), - ), + Row("event", "person"), + Row("comment", "medical_information"), + "voucher", + Row("iban", "donation", "accept_sepa"), + "accepted_terms", + Row("school", "school_class", "school_place"), + "states", ) class Meta: @@ -490,3 +483,9 @@ class RegistrationNotificationForm(forms.ModelForm): class Meta: model = InfoMailing exclude = ["sent_to", "active"] + + +class RegistrationStatesForm(forms.ModelForm): + class Meta: + model = RegistrationState + exclude = [] diff --git a/aleksis/apps/paweljong/menus.py b/aleksis/apps/paweljong/menus.py index afe3056df07a741f0bd94d2bb1db4a015c532907..149cd54a637869ca14489f308f5caaf87ec7c370 100644 --- a/aleksis/apps/paweljong/menus.py +++ b/aleksis/apps/paweljong/menus.py @@ -44,6 +44,17 @@ MENUS = { ) ], }, + { + "name": _("Registration states"), + "url": "registration_states", + "icon": "list", + "validators": [ + ( + "aleksis.core.util.predicates.permission_validator", + "paweljong.view_registration_states_rule", + ) + ], + }, { "name": _("Info mailings"), "url": "info_mailings", diff --git a/aleksis/apps/paweljong/migrations/0015_registrationstate.py b/aleksis/apps/paweljong/migrations/0015_registrationstate.py new file mode 100644 index 0000000000000000000000000000000000000000..6375c85243be833a5959998dcaac47c7a8e08197 --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0015_registrationstate.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.12 on 2022-03-06 20:09 + +import colorfield.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', '0014_move_sent_to_to_through'), + ] + + operations = [ + migrations.CreateModel( + name='RegistrationState', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('extended_data', models.JSONField(default=dict, editable=False)), + ('name', models.CharField(max_length=255, verbose_name='Name of State')), + ('colour', colorfield.fields.ColorField(blank=True, default='', image_field=None, max_length=18, samples=None, verbose_name='Colour')), + ('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()), + ], + ), + ] diff --git a/aleksis/apps/paweljong/migrations/0016_eventregistration_states.py b/aleksis/apps/paweljong/migrations/0016_eventregistration_states.py new file mode 100644 index 0000000000000000000000000000000000000000..28e9964684d80e108fcff1e8a89ef18f34268ecf --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0016_eventregistration_states.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2022-03-06 20:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('paweljong', '0015_registrationstate'), + ] + + operations = [ + migrations.AddField( + model_name='eventregistration', + name='states', + field=models.ManyToManyField(related_name='registrations', to='paweljong.RegistrationState', verbose_name='States'), + ), + ] diff --git a/aleksis/apps/paweljong/models.py b/aleksis/apps/paweljong/models.py index 976b74470226a61ccf67a24835c5833388e64230..0fb4b3c407f2336dfe0b39bf72dd166fc4b5a642 100644 --- a/aleksis/apps/paweljong/models.py +++ b/aleksis/apps/paweljong/models.py @@ -8,6 +8,7 @@ from django.utils.translation import gettext_lazy as _ from ckeditor.fields import RichTextField from django_iban.fields import IBANField +from colorfield.fields import ColorField from aleksis.core.mixins import ExtensibleModel from aleksis.core.models import Group, Person @@ -15,6 +16,15 @@ from aleksis.core.util.core_helpers import generate_random_code, get_site_prefer from aleksis.core.util.email import send_email +class RegistrationState(ExtensibleModel): + + name = models.CharField(verbose_name=_("Name"), max_length=255) + colour = ColorField(blank=True, verbose_name=_("Colour")) + + def __str__(self) -> str: + return self.name + + class Terms(ExtensibleModel): title = models.CharField(max_length=255, verbose_name=_("Title")) term = RichTextField(verbose_name=_("Term")) @@ -261,6 +271,8 @@ class EventRegistration(ExtensibleModel): blank=True, ) + states = models.ManyToManyField(RegistrationState, verbose_name=_("States"), related_name="registrations") + 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 2e7ac691d402d6c72ac1437eb5a7666146fe1e20..8795e17ab9a60770558f6013a682db13ecfba49a 100644 --- a/aleksis/apps/paweljong/tables.py +++ b/aleksis/apps/paweljong/tables.py @@ -1,3 +1,4 @@ +from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ import django_tables2 as tables @@ -56,13 +57,23 @@ class EventRegistrationsTable(tables.Table): person = tables.Column() event = tables.Column() date_registered = tables.Column() + states = tables.Column() view = tables.LinkColumn( "registration_by_pk", args=[A("id")], verbose_name=_("View registration"), text=_("View"), ) + edit = tables.LinkColumn( + "edit_registration_by_pk", + args=[A("pk")], + verbose_name=_("Edit"), + text=_("Edit"), + ) + def render_states(self, value, record): + context = dict(states=value.all()) + return render_to_string("paweljong/registration_state/chip.html", context) class TermsTable(tables.Table): class Meta: @@ -96,3 +107,21 @@ class InfoMailingsTable(tables.Table): verbose_name=_("Delete"), text=_("Delete"), ) + + +class RegistrationStatesTable(tables.Table): + class Meta: + attrs = {"class": "responsive-table highlight"} + + name = tables.Column() + + edit = tables.LinkColumn( + "edit_registration_state_by_pk", + args=[A("id")], + verbose_name=_("Edit"), + text=_("Edit"), + ) + + def render_name(self, value, record): + context = dict(state=record) + return render_to_string("paweljong/registration_state/chip.html", context) diff --git a/aleksis/apps/paweljong/templates/paweljong/event_registration/edit.html b/aleksis/apps/paweljong/templates/paweljong/event_registration/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..4238fe2f1e0a2876f4bc3dd2e21007f550b03e53 --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/event_registration/edit.html @@ -0,0 +1,22 @@ +{% extends "core/base.html" %} +{% load material_form i18n any_js %} + +{% block page_title %}{% blocktrans %}Edit registration{% endblocktrans %}{% endblock %} +{% block browser_title %}{% blocktrans %}Edit registration{% endblocktrans %}{% endblock %} + +{% block extra_head %} + {{ form.media.css }} + {% include_css "select2-materialize" %} +{% endblock %} + +{% block content %} + + <form method="post"> + {% csrf_token %} + {% form form=form %}{% form %} + {% include "core/partials/save_button.html" %} + </form> + {% include_js "select2-materialize" %} + {{ form.media.js }} + +{% endblock %} diff --git a/aleksis/apps/paweljong/templates/paweljong/registration_state/chip.html b/aleksis/apps/paweljong/templates/paweljong/registration_state/chip.html new file mode 100644 index 0000000000000000000000000000000000000000..91aa0ef0694bf36b42c4f2f904718aa4b5c02520 --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/registration_state/chip.html @@ -0,0 +1,19 @@ +{# -*- engine:django -*- #} + +{% if states %} + {% for state in states %} + <div class="chip white-text" style="background-color: {{ state.colour|default:"black" }};"> + {{ state }} + {% if small %} + <small>({{ small }})</small> + {% endif %} + </div> + {% endfor %} +{% else %} + <div class="chip white-text" style="background-color: {{ state.colour|default:"black" }};"> + {{ state.name }} + {% if small %} + <small>({{ small }})</small> + {% endif %} + </div> +{% endif %} diff --git a/aleksis/apps/paweljong/templates/paweljong/registration_state/create.html b/aleksis/apps/paweljong/templates/paweljong/registration_state/create.html new file mode 100644 index 0000000000000000000000000000000000000000..d8215a976213042538a433af65d2d68ef224319d --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/registration_state/create.html @@ -0,0 +1,19 @@ +{% extends "core/base.html" %} +{% load material_form i18n %} + +{% block page_title %}{% blocktrans %}Create registration state{% endblocktrans %}{% endblock %} +{% block browser_title %}{% blocktrans %}Create registration state{% 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/registration_state/edit.html b/aleksis/apps/paweljong/templates/paweljong/registration_state/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..da8ec67d9060ac6460c0f9477111d8c684b40b0c --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/registration_state/edit.html @@ -0,0 +1,18 @@ +{% extends "core/base.html" %} +{% load material_form i18n %} + +{% block page_title %}{% blocktrans %}Edit registration state{% endblocktrans %}{% endblock %} +{% block browser_title %}{% blocktrans %}Edit registration state{% 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/registration_state/list.html b/aleksis/apps/paweljong/templates/paweljong/registration_state/list.html new file mode 100644 index 0000000000000000000000000000000000000000..40771901ce17d65dfbc09a61917eb498dcca62c6 --- /dev/null +++ b/aleksis/apps/paweljong/templates/paweljong/registration_state/list.html @@ -0,0 +1,14 @@ +{% extends "core/base.html" %} +{% load material_form i18n %} + +{% load render_table from django_tables2 %} + +{% block page_title %}{% blocktrans %}Registration states{% endblocktrans %}{% endblock %} +{% block browser_title %}{% blocktrans %}Registration states{% endblocktrans %}{% endblock %} + +{% block content %} + + <a class="btn colour-primary waves-effect waves-light" href="{% url 'create_registration_state' %}">{% trans "Create registration state" %}</a> + {% render_table table %} + +{% endblock %} diff --git a/aleksis/apps/paweljong/urls.py b/aleksis/apps/paweljong/urls.py index d2a43fd5c9a994cdc33720944ea85d12b3ce79ce..5568600668fe34105b8ceb8f5df8b8f51ef1d0b0 100644 --- a/aleksis/apps/paweljong/urls.py +++ b/aleksis/apps/paweljong/urls.py @@ -107,6 +107,21 @@ urlpatterns = [ views.TermEditView.as_view(), name="edit_term_by_pk", ), + path( + "event/registrations/states/list", + views.RegistrationStateListView.as_view(), + name="registration_states", + ), + path( + "event/registrations/states/create", + views.RegistrationStateCreateView.as_view(), + name="create_registration_state", + ), + path( + "event/registrations/states/<int:pk>/edit", + views.RegistrationStateEditView.as_view(), + name="edit_registration_state_by_pk", + ), path( "info_mailings/list", views.InfoMailingListView.as_view(), diff --git a/aleksis/apps/paweljong/views.py b/aleksis/apps/paweljong/views.py index 9786d3140eb75f828fe516c4f27ce29b47eb1e8c..a5251d9d11d11d929bcce83a385400f31c40513e 100644 --- a/aleksis/apps/paweljong/views.py +++ b/aleksis/apps/paweljong/views.py @@ -37,14 +37,16 @@ from .forms import ( EditVoucherForm, GenerateListForm, RegistrationNotificationForm, + RegistrationStatesForm, ) -from .models import Event, EventRegistration, InfoMailing, Terms, Voucher +from .models import Event, EventRegistration, InfoMailing, Terms, Voucher, RegistrationState from .tables import ( EventRegistrationsTable, InfoMailingsTable, ManageEventsTable, TermsTable, VouchersTable, + RegistrationStatesTable, ) User = get_user_model() @@ -160,7 +162,7 @@ class EventRegistrationCreateView(PermissionRequiredMixin, AdvancedCreateView): form_class = EditEventRegistrationForm permission_required = "paweljong.manage_registration" template_name = "paweljong/event_registration/create.html" - success_url = reverse_lazy("event_registrations") + success_url = reverse_lazy("registrations") success_message = _("The event registration has been created.") @@ -172,7 +174,7 @@ class EventRegistrationEditView(PermissionRequiredMixin, AdvancedEditView): form_class = EditEventRegistrationForm permission_required = "paweljong.manage_eventregistration" template_name = "paweljong/event_registration/edit.html" - success_url = reverse_lazy("event_registrations") + success_url = reverse_lazy("registrations") success_message = _("The event registration has been saved.") @@ -860,3 +862,36 @@ class SendMailFromRegistration(PermissionRequiredMixin, FormView): ) return super().form_valid(self) + + +class RegistrationStateListView(PermissionRequiredMixin, SingleTableView): + """Table of all terms.""" + + model = RegistrationState + table_class = RegistrationStatesTable + permission_required = "paweljong.view_registration_states" + template_name = "paweljong/registration_state/list.html" + + +@method_decorator(never_cache, name="dispatch") +class RegistrationStateCreateView(PermissionRequiredMixin, AdvancedCreateView): + """Create view for terms.""" + + model = RegistrationState + form_class = RegistrationStatesForm + permission_required = "paweljong.add_registration_states" + template_name = "paweljong/registration_state/create.html" + success_url = reverse_lazy("registration_states") + success_message = _("The term has been created.") + + +@method_decorator(never_cache, name="dispatch") +class RegistrationStateEditView(PermissionRequiredMixin, AdvancedEditView): + """Edit view for terms.""" + + model = RegistrationState + form_class = RegistrationStatesForm + permission_required = "paweljong.edit_registration_states" + template_name = "paweljong/registration_state/edit.html" + success_url = reverse_lazy("registration_states") + success_message = _("The term has been saved.")