From 3fd5ac314e134fc8d9eb25088027406c92e3a721 Mon Sep 17 00:00:00 2001 From: Chris Mutel Date: Tue, 30 Apr 2024 15:00:47 +0200 Subject: [PATCH] Free events with simplified registration --- dds_registration/forms.py | 6 +- ...07_event_free_alter_registration_option.py | 24 +++ dds_registration/models.py | 3 +- dds_registration/views/event_registration.py | 166 +++++++++++------- 4 files changed, 129 insertions(+), 70 deletions(-) create mode 100644 dds_registration/migrations/0007_event_free_alter_registration_option.py diff --git a/dds_registration/forms.py b/dds_registration/forms.py index 3a77fee3..27e2ccde 100644 --- a/dds_registration/forms.py +++ b/dds_registration/forms.py @@ -43,6 +43,10 @@ class MembershipForm(forms.Form): ) +class FreeRegistrationForm(forms.Form): + send_update_emails = forms.BooleanField(label="Send me emails about this event", required=False, initial=True) + + class RegistrationForm(forms.Form): option = forms.ChoiceField( choices=[], @@ -70,7 +74,7 @@ class RegistrationForm(forms.Form): # See stylization in `src/assets/common/fix-django-forms.scss`, by option element' id. widget=forms.RadioSelect, label="Payment method", - help_text="Choose something even if the event is free", + help_text="Choose something even if your registration is free", ) def __init__(self, option_choices, *args, **kwargs): diff --git a/dds_registration/migrations/0007_event_free_alter_registration_option.py b/dds_registration/migrations/0007_event_free_alter_registration_option.py new file mode 100644 index 00000000..acb1cfa6 --- /dev/null +++ b/dds_registration/migrations/0007_event_free_alter_registration_option.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0.3 on 2024-04-30 12:58 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dds_registration', '0006_message_subject'), + ] + + operations = [ + migrations.AddField( + model_name='event', + name='free', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='registration', + name='option', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='registrations', to='dds_registration.registrationoption'), + ), + ] diff --git a/dds_registration/models.py b/dds_registration/models.py index 123c0daf..caa23a25 100644 --- a/dds_registration/models.py +++ b/dds_registration/models.py @@ -401,6 +401,7 @@ class Event(Model): default=0, help_text="Maximum number of participants (0 = no limit)", ) + free = models.BooleanField(default=False) class Meta: constraints = [ @@ -512,7 +513,7 @@ class Registration(Model): payment = models.OneToOneField(Payment, on_delete=models.SET_NULL, null=True, blank=True) event = models.ForeignKey(Event, related_name="registrations", on_delete=models.CASCADE) user = models.ForeignKey(User, related_name="registrations", on_delete=models.CASCADE) - option = models.ForeignKey(RegistrationOption, on_delete=models.CASCADE, related_name="registrations") + option = models.ForeignKey(RegistrationOption, on_delete=models.CASCADE, related_name="registrations", null=True, blank=True) status = models.TextField(choices=REGISTRATION_STATUS) send_update_emails = models.BooleanField(default=False) diff --git a/dds_registration/views/event_registration.py b/dds_registration/views/event_registration.py index f7306a75..de5aa708 100644 --- a/dds_registration/views/event_registration.py +++ b/dds_registration/views/event_registration.py @@ -5,7 +5,7 @@ from django.http import Http404, HttpRequest from django.shortcuts import redirect, render -from ..forms import RegistrationForm +from ..forms import RegistrationForm, FreeRegistrationForm from ..models import Event, Payment, Registration, RegistrationOption # from .event_registration_cancel import ( @@ -39,82 +39,112 @@ def event_registration(request: HttpRequest, event_code: str): return redirect("profile") if request.method == "POST": - form = RegistrationForm( - data=request.POST, - option_choices=[(obj.id, obj.form_label) for obj in event.options.all()], - ) - - if form.is_valid(): - option = RegistrationOption.objects.get(id=form.cleaned_data["option"]) - if registration: - # Set up new payment - if registration.payment: - registration.payment.mark_obsolete() - registration.option = option - registration.send_update_emails = form.cleaned_data["send_update_emails"] - registration.status = "SUBMITTED" - else: - registration = Registration( - event=event, - status="SUBMITTED", - user=request.user, - send_update_emails=form.cleaned_data["send_update_emails"], - option=option, - ) - registration.save() - - if not registration.option.price: + if event.free: + form = FreeRegistrationForm( + data=request.POST, + ) + if form.is_valid(): + if registration: + # Set up new payment + registration.send_update_emails = form.cleaned_data["send_update_emails"] + registration.status = "SUBMITTED" + else: + registration = Registration( + event=event, + status="SUBMITTED", + user=request.user, + send_update_emails=form.cleaned_data["send_update_emails"], + ) + registration.save() + registration.complete_registration() messages.success(request, f"You have successfully registered for {event.title}.") return redirect("profile") + else: + form = RegistrationForm( + data=request.POST, + option_choices=[(obj.id, obj.form_label) for obj in event.options.all()], + ) - registration.complete_registration() - - payment = Payment( - status="CREATED", - data={ - "user": { - "id": request.user.id, - "name": form.cleaned_data["name"], - "address": form.cleaned_data["address"], - }, - "extra": form.cleaned_data["extra"], - "kind": "event", - "method": form.cleaned_data["payment_method"], - "event": { - "id": event.id, - "title": event.title, - }, - "registration": { - "id": registration.id, - }, - "option": { - "id": option.id, - "item": option.item, + if form.is_valid(): + option = RegistrationOption.objects.get(id=form.cleaned_data["option"]) + if registration: + # Set up new payment + if registration.payment: + registration.payment.mark_obsolete() + registration.option = option + registration.send_update_emails = form.cleaned_data["send_update_emails"] + registration.status = "SUBMITTED" + else: + registration = Registration( + event=event, + status="SUBMITTED", + user=request.user, + send_update_emails=form.cleaned_data["send_update_emails"], + option=option, + ) + registration.save() + + if not registration.option.price: + messages.success(request, f"You have successfully registered for {event.title}.") + return redirect("profile") + + registration.complete_registration() + + payment = Payment( + status="CREATED", + data={ + "user": { + "id": request.user.id, + "name": form.cleaned_data["name"], + "address": form.cleaned_data["address"], + }, + "extra": form.cleaned_data["extra"], + "kind": "event", + "method": form.cleaned_data["payment_method"], + "event": { + "id": event.id, + "title": event.title, + }, + "registration": { + "id": registration.id, + }, + "option": { + "id": option.id, + "item": option.item, + }, + "price": option.price, + "currency": option.currency, }, - "price": option.price, - "currency": option.currency, + ) + payment.save() + + registration.payment = payment + registration.save() + + if payment.data["method"] == "INVOICE": + payment.email_invoice() + payment.status = "ISSUED" + payment.save() + messages.success( + request, + f"Your registration for {event.title} has been created! An invoice has been sent to {request.user.email} from events@d-d-s.ch. The invoice can also be downloaded from your profile. Please note your registration is not in force until the invoice is paid.", + ) + return redirect("profile") + elif payment.data["method"] == "STRIPE": + return redirect("payment_stripe", payment_id=payment.id) + elif event.free: + if registration: + form = FreeRegistrationForm( + initial={ + "send_update_emails": registration.send_update_emails, }, ) - payment.save() - - registration.payment = payment - registration.save() - - if payment.data["method"] == "INVOICE": - payment.email_invoice() - payment.status = "ISSUED" - payment.save() - messages.success( - request, - f"Your registration for {event.title} has been created! An invoice has been sent to {request.user.email} from events@d-d-s.ch. The invoice can also be downloaded from your profile. Please note your registration is not in force until the invoice is paid.", - ) - return redirect("profile") - elif payment.data["method"] == "STRIPE": - return redirect("payment_stripe", payment_id=payment.id) + else: + form = FreeRegistrationForm() else: # TODO: Populate template with existing choices instead of defaults if registration: - # TODO: What to do if there no payment property in the registration object (as a result of a incosistency)? + # TODO: What to do if there no payment property in the registration object (as a result of a inconsistency)? messages.success( request, "You are now editing an existing registration application. Please be careful not to make unwanted changes.",