diff --git a/banquet/admin.py b/banquet/admin.py index 4aa48ee22..858320979 100644 --- a/banquet/admin.py +++ b/banquet/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin from .models import ( Banquet, + DietaryPreference, Participant, InvitationGroup, Invitation, @@ -59,3 +60,8 @@ class AfterPartyInvitationAdmin(ModelAdminImproved): class AfterPartyTicketAdmin(ModelAdminImproved): list_filter = ["banquet", "has_paid"] list_display = ["name", "email_address", "has_paid"] + + +@admin.register(DietaryPreference) +class DietaryPreferenceAdmin(ModelAdminImproved): + pass diff --git a/banquet/forms.py b/banquet/forms.py index 4b9d4060f..20a3fc409 100644 --- a/banquet/forms.py +++ b/banquet/forms.py @@ -15,6 +15,7 @@ import csv from .models import ( + DietaryPreference, Participant, InvitationGroup, Invitation, @@ -51,6 +52,24 @@ def fix_phone_number(n): class ParticipantForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + participant = kwargs.pop("instance", None) + banquet = participant.banquet + + # Set empty_label to None to remove the default "------" + self.fields["dietary_preference"].empty_label = None + + if banquet: + self.fields["dietary_preference"].queryset = self.get_dietary_preferences( + banquet + ) + + def get_dietary_preferences(self, banquet): + # Custom function to retrieve dietary preferences for the given banquet + return DietaryPreference.objects.filter(banquet=banquet) + def clean(self): super(ParticipantForm, self).clean() @@ -83,6 +102,7 @@ class Meta: "name", "email_address", "phone_number", + "dietary_preference", "dietary_restrictions", "other_dietary_restrictions", "alcohol", @@ -91,6 +111,7 @@ class Meta: widgets = { "name": forms.TextInput(attrs={"readonly": "readonly"}), "email_address": forms.TextInput(attrs={"readonly": "readonly"}), + "dietary_preference": forms.RadioSelect(), "dietary_restrictions": forms.CheckboxSelectMultiple(), "other_dietary_restrictions": forms.TextInput(), "alcohol": forms.RadioSelect(), diff --git a/banquet/migrations/0048_add_dietary_preferences.py b/banquet/migrations/0048_add_dietary_preferences.py new file mode 100644 index 000000000..d0b703cff --- /dev/null +++ b/banquet/migrations/0048_add_dietary_preferences.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.24 on 2024-09-10 11:08 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("people", "0014_add_dietary_preferences"), + ("banquet", "0047_has_sent_mail"), + ] + + operations = [ + migrations.AddField( + model_name="participant", + name="dietary_preference", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="people.DietaryPreference", + ), + ), + ] diff --git a/banquet/migrations/0049_change_dietary_preferences.py b/banquet/migrations/0049_change_dietary_preferences.py new file mode 100644 index 000000000..dff619863 --- /dev/null +++ b/banquet/migrations/0049_change_dietary_preferences.py @@ -0,0 +1,50 @@ +# Generated by Django 2.2.24 on 2024-09-10 11:14 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("banquet", "0048_add_dietary_preferences"), + ] + + operations = [ + migrations.CreateModel( + name="DietaryPreference", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255)), + ("order", models.IntegerField(default=0)), + ( + "banquet", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="banquet.Banquet", + ), + ), + ], + options={ + "ordering": ["order", "name"], + }, + ), + migrations.AlterField( + model_name="participant", + name="dietary_preference", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="banquet.DietaryPreference", + ), + ), + ] diff --git a/banquet/migrations/0050_change_dietary_preferences.py b/banquet/migrations/0050_change_dietary_preferences.py new file mode 100644 index 000000000..24fca90c8 --- /dev/null +++ b/banquet/migrations/0050_change_dietary_preferences.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.24 on 2024-09-10 11:20 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("banquet", "0049_change_dietary_preferences"), + ] + + operations = [ + migrations.AlterField( + model_name="participant", + name="dietary_preference", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="banquet.DietaryPreference", + ), + ), + ] diff --git a/banquet/models.py b/banquet/models.py index efee6ce83..9314b3842 100644 --- a/banquet/models.py +++ b/banquet/models.py @@ -129,6 +129,18 @@ class Meta: ordering = ["year"] +class DietaryPreference(models.Model): + name = models.CharField(max_length=255) + order = models.IntegerField(default=0) + banquet = models.ForeignKey(Banquet, on_delete=models.CASCADE) + + class Meta: + ordering = ["order", "name"] + + def __str__(self): + return self.name + + class Participant(models.Model): token = models.CharField( max_length=32, unique=True, default=get_random_32_length_string @@ -148,6 +160,9 @@ class Participant(models.Model): max_length=75, blank=True, null=True ) # None if a user is provided, required for others dietary_restrictions = models.ManyToManyField(DietaryRestriction, blank=True) + dietary_preference = models.ForeignKey( + DietaryPreference, null=True, on_delete=models.CASCADE + ) other_dietary_restrictions = models.CharField(max_length=75, blank=True, null=True) alcohol = models.BooleanField(choices=[(True, "Yes"), (False, "No")], default=True) seat = models.OneToOneField(Seat, blank=True, null=True, on_delete=models.CASCADE) diff --git a/banquet/views.py b/banquet/views.py index 8ae62e15e..3deb27933 100644 --- a/banquet/views.py +++ b/banquet/views.py @@ -1212,6 +1212,7 @@ def send_invitation_button(request, year, banquet_pk, invitation_pk): "email": email, }, ) + send_invitation_mail(invitation, name, banquet.date, banquet.location, link, email) return render( diff --git a/people/admin.py b/people/admin.py index 36c976b5f..be6ae19d3 100644 --- a/people/admin.py +++ b/people/admin.py @@ -1,6 +1,3 @@ -from django.contrib.auth.admin import UserAdmin -from django.contrib.auth.models import User - from django.contrib import admin from .models import Language, Programme, Profile, DietaryRestriction from improved_admin import ModelAdminImproved diff --git a/people/migrations/0014_add_dietary_preferences.py b/people/migrations/0014_add_dietary_preferences.py new file mode 100644 index 000000000..8c787348e --- /dev/null +++ b/people/migrations/0014_add_dietary_preferences.py @@ -0,0 +1,37 @@ +# Generated by Django 2.2.24 on 2024-09-10 11:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("people", "0013_add_armada_email"), + ] + + operations = [ + migrations.CreateModel( + name="DietaryPreference", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255)), + ("order", models.IntegerField(default=0)), + ], + options={ + "ordering": ["order", "name"], + }, + ), + migrations.AlterField( + model_name="profile", + name="no_dietary_restrictions", + field=models.BooleanField(default=False), + ), + ] diff --git a/people/migrations/0015_remove_dietary_preferences.py b/people/migrations/0015_remove_dietary_preferences.py new file mode 100644 index 000000000..da147c63c --- /dev/null +++ b/people/migrations/0015_remove_dietary_preferences.py @@ -0,0 +1,16 @@ +# Generated by Django 2.2.24 on 2024-09-10 11:14 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("people", "0014_add_dietary_preferences"), + ] + + operations = [ + migrations.DeleteModel( + name="DietaryPreference", + ), + ]