diff --git a/CHANGELOG.rst b/CHANGELOG.rst index af498e3afba63f46f5e8ada77fdbfc7102584cf5..50a4022f36b0aa9fd426c105628b73a3d0a692aa 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog`_, and this project adheres to `Semantic Versioning`_. +Unreleased +---------- + +Changed +~~~~~~~ + +* Allow re-using mailings for multiple events by moving sent_to to the per-event table + `1.3.1`_ -------- diff --git a/aleksis/apps/paweljong/migrations/0014_move_sent_to_to_through.py b/aleksis/apps/paweljong/migrations/0014_move_sent_to_to_through.py new file mode 100644 index 0000000000000000000000000000000000000000..e7955744e634b7ac56cb96656059de0463c6d52e --- /dev/null +++ b/aleksis/apps/paweljong/migrations/0014_move_sent_to_to_through.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.12 on 2022-03-02 19:50 + +import django.contrib.sites.managers +from django.db import migrations, models +import django.db.models.deletion + + +def migrate_to_new_through(apps, schema_editor): + Event = apps.get_model("paweljong", "Event") + EventRegistration = apps.get_model("paweljong", "EventRegistration") + Through = apps.get_model("paweljong", "EventInfoMailingThrough") + + db_alias = schema_editor.connection.alias + + for through_old in Event.info_mailings.through.objects.all(): + event = through_old.event + info_mailing = through_old.infomailing + + through = Through.objects.create(event=event, info_mailing=info_mailing) + for person in info_mailing.sent_to.all(): + if EventRegistration.objects.filter(person_id=person.id, event_id=event.id).exists(): + through.sent_to.add(person) + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0035_preference_model_unique'), + ('sites', '0002_alter_domain_unique'), + ('paweljong', '0013_info_mailings'), + ] + + operations = [ + migrations.CreateModel( + name='EventInfoMailingThrough', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('extended_data', models.JSONField(default=dict, editable=False)), + ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='paweljong.event')), + ('info_mailing', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='paweljong.infomailing')), + ('sent_to', models.ManyToManyField(blank=True, editable=False, related_name='received_info_mailings', to='core.Person', verbose_name='Sent to persons')), + ('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='info_mailings_new', + field=models.ManyToManyField(blank=True, related_name='events', through='paweljong.EventInfoMailingThrough', to='paweljong.InfoMailing', verbose_name='Info mailings'), + ), + migrations.RunPython(migrate_to_new_through), + migrations.RemoveField( + model_name='event', + name='info_mailings', + ), + migrations.RenameField( + 'event', + 'info_mailings_new', + 'info_mailings', + ), + migrations.RemoveField( + model_name='infomailing', + name='sent_to', + ), + ] diff --git a/aleksis/apps/paweljong/models.py b/aleksis/apps/paweljong/models.py index 55a067ad82e33466938c75670b2e2d1bd2955087..1cd803879f3c27f4c7bc43b1daaf3767327cfccb 100644 --- a/aleksis/apps/paweljong/models.py +++ b/aleksis/apps/paweljong/models.py @@ -35,14 +35,6 @@ class InfoMailing(ExtensibleModel): send_to_person = models.BooleanField(verbose_name=_("Send to registered person"), default=True) send_to_guardians = models.BooleanField(verbose_name=_("Send to guardians"), default=False) - sent_to = models.ManyToManyField( - Person, - verbose_name=_("Sent to persons"), - related_name="received_info_mailings", - editable=False, - blank=True, - ) - def __str__(self) -> str: return self.subject @@ -51,9 +43,10 @@ class InfoMailing(ExtensibleModel): return cls.objects.filter(active=True) def send(self): - sent_to = self.sent_to.all() - for event in self.events.all(): + through = EventInfoMailingThrough.objects.get(info_mailing=self, event=event) + sent_to = through.sent_to.all() + for registration in event.registrations.all(): if registration.person in sent_to: continue @@ -90,7 +83,7 @@ class InfoMailing(ExtensibleModel): }, ) - self.sent_to.add(registration.person) + through.sent_to.add(registration.person) class Event(ExtensibleModel): @@ -115,7 +108,7 @@ class Event(ExtensibleModel): information = RichTextField(verbose_name=_("Information about the event")) terms = models.ManyToManyField(Terms, verbose_name=_("Terms"), related_name="event", blank=True) info_mailings = models.ManyToManyField( - InfoMailing, verbose_name=_("Info mailings"), related_name="events", blank=True + InfoMailing, verbose_name=_("Info mailings"), related_name="events", through="EventInfoMailingThrough", blank=True ) def save(self, *args, **kwargs): @@ -173,6 +166,19 @@ class Event(ExtensibleModel): return Event.objects.filter(published=True, date_event__gte=now()) +class EventInfoMailingThrough(ExtensibleModel): + event = models.ForeignKey(Event, on_delete=models.CASCADE) + info_mailing = models.ForeignKey(InfoMailing, on_delete=models.CASCADE) + + sent_to = models.ManyToManyField( + Person, + verbose_name=_("Sent to persons"), + related_name="received_info_mailings", + editable=False, + blank=True, + ) + + class Voucher(ExtensibleModel): class Meta: verbose_name = _("Vouchers")