Skip to content

Commit

Permalink
feat(programme,mailings): status, category and form based groups for …
Browse files Browse the repository at this point in the history
…programme mailings
  • Loading branch information
japsu committed Apr 16, 2023
1 parent 327e3ba commit 719ebb9
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 13 deletions.
2 changes: 2 additions & 0 deletions events/ropecon2023/management/commands/setup_ropecon2023.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,8 @@ def setup_programme(self):
]:
Tag.objects.get_or_create(event=self.event, title=tag_title)

self.event.programme_event_meta.create_groups()

def setup_tickets(self):
from tickets.models import TicketsEventMeta, LimitGroup, Product

Expand Down
24 changes: 24 additions & 0 deletions mailings/migrations/0010_recipientgroup_programme_form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 4.1.7 on 2023-04-15 15:28

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):
dependencies = [
("programme", "0118_alter_programme_photography_and_more"),
("mailings", "0009_recipientgroup_programme_category_and_more"),
]

operations = [
migrations.AddField(
model_name="recipientgroup",
name="programme_form",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="programme.alternativeprogrammeform",
),
),
]
17 changes: 17 additions & 0 deletions mailings/migrations/0011_alter_recipientgroup_verbose_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.1.7 on 2023-04-15 15:30

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("mailings", "0010_recipientgroup_programme_form"),
]

operations = [
migrations.AlterField(
model_name="recipientgroup",
name="verbose_name",
field=models.CharField(blank=True, default="", max_length=255, verbose_name="Nimi"),
),
]
6 changes: 6 additions & 0 deletions programme/models/alternative_programme_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class AlternativeProgrammeForm(models.Model):
AlternativeProgrammeForms are specified, the default form is used.
"""

id: int

event = models.ForeignKey("core.Event", on_delete=models.CASCADE, verbose_name=_("event"))

slug = models.CharField(**NONUNIQUE_SLUG_FIELD_PARAMS)
Expand Down Expand Up @@ -91,6 +93,10 @@ class AlternativeProgrammeForm(models.Model):
def __str__(self):
return self.title

@property
def qualified_slug(self):
return f"form-{self.slug}"

@property
def programme_form_class(self):
if not getattr(self, "_programme_form_class", None):
Expand Down
6 changes: 6 additions & 0 deletions programme/models/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@


class Category(models.Model):
id: int

event = models.ForeignKey("core.Event", on_delete=models.CASCADE)
title = models.CharField(max_length=1023)
slug = models.CharField(**NONUNIQUE_SLUG_FIELD_PARAMS)
Expand Down Expand Up @@ -38,6 +40,10 @@ def get_or_create_dummy(cls):
),
)

@property
def qualified_slug(self):
return f"category-{self.slug}"


@receiver(pre_save, sender=Category)
def populate_category_slug(sender, instance, **kwargs):
Expand Down
38 changes: 37 additions & 1 deletion programme/models/programme.py
Original file line number Diff line number Diff line change
Expand Up @@ -1580,8 +1580,9 @@ def apply_state_update_signup_extras(self):
signup_extra.apply_state()

def apply_state_group_membership(self):
from django.contrib.auth.models import Group
from core.utils import ensure_user_group_membership
from .alternative_programme_form import AlternativeProgrammeForm
from .category import Category
from .programme_role import ProgrammeRole

for person in self.organizers.all():
Expand All @@ -1590,6 +1591,7 @@ def apply_state_group_membership(self):
groups_to_add = []
groups_to_remove = []

# Status based groups
for group, states in [
(self.event.programme_event_meta.get_group_if_exists("new"), PROGRAMME_STATES_NEW),
(self.event.programme_event_meta.get_group_if_exists("hosts"), PROGRAMME_STATES_ACTIVE),
Expand All @@ -1610,6 +1612,40 @@ def apply_state_group_membership(self):
# inactive programmist
groups_to_remove.append(group)

# Category groups
for category in Category.objects.filter(event=self.event):
group = self.event.programme_event_meta.get_group_if_exists(category.qualified_slug)
if not group:
continue

if ProgrammeRole.objects.filter(
programme__category=category,
programme__state__in=PROGRAMME_STATES_LIVE,
person=person,
).exists():
# active programmist
groups_to_add.append(group)
else:
# inactive programmist
groups_to_remove.append(group)

# Form groups
for form in AlternativeProgrammeForm.objects.filter(event=self.event):
group = self.event.programme_event_meta.get_group_if_exists(form.qualified_slug)
if not group:
continue

if ProgrammeRole.objects.filter(
programme__form_used=form,
programme__state__in=PROGRAMME_STATES_LIVE,
person=person,
).exists():
# active programmist
groups_to_add.append(group)
else:
# inactive programmist
groups_to_remove.append(group)

ensure_user_group_membership(person.user, groups_to_add=groups_to_add, groups_to_remove=groups_to_remove)

def apply_state_send_messages(self, resend=False):
Expand Down
29 changes: 19 additions & 10 deletions programme/models/programme_event_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

GROUP_VERBOSE_NAMES_BY_SUFFIX = dict(
admins="Ohjelmavastaavat",
hosts="Ohjelmanjärjestäjät",
hosts="Kaikki ohjelmanjärjestäjät (odottavat ja hyväksytyt)",
live="Hyväksyttyjen ohjelmien järjestäjät",
new="Hyväksyntää odottavat ohjelmanjärjestäjät",
)


Expand Down Expand Up @@ -104,46 +106,53 @@ def get_or_create_dummy(cls):
return meta, created

def create_groups(self):
from .alternative_programme_form import AlternativeProgrammeForm
from .category import Category

subjects: list[str | Category] = ["new", "hosts", "live", "rejected"]
subjects: list[str | Category | AlternativeProgrammeForm] = ["new", "hosts", "live", "rejected"]

for category in Category.objects.filter(event=self.event):
subjects.append(category)

# for category in Category.objects.filter(event=self.event):
# subjects.append(category)
for form in AlternativeProgrammeForm.objects.filter(event=self.event):
subjects.append(form)

return self.get_or_create_groups(self.event, subjects)

@classmethod
def get_or_create_groups(cls, event, subjects):
from mailings.models import RecipientGroup
from .category import Category
from .alternative_programme_form import AlternativeProgrammeForm

suffixes = [subject if isinstance(subject, str) else subject.slug for subject in subjects]
suffixes = [subject if isinstance(subject, str) else subject.qualified_slug for subject in subjects]

groups = super().get_or_create_groups(event, suffixes)

for subject, group in zip(subjects, groups):
if isinstance(subject, Category):
verbose_name = subject.title
category = subject
# elif isinstance(jc_or_suffix, PersonnelClass):
# verbose_name = jc_or_suffix.name
# job_category = None
# personnel_class = jc_or_suffix
programme_form = None
elif isinstance(subject, AlternativeProgrammeForm):
verbose_name = subject.title
category = None
programme_form = subject
else:
if subject not in GROUP_VERBOSE_NAMES_BY_SUFFIX:
continue

verbose_name = GROUP_VERBOSE_NAMES_BY_SUFFIX[subject]
category = None
personnel_class = None
programme_form = None

RecipientGroup.objects.get_or_create(
event=event,
app_label="programme",
group=group,
defaults=dict(
programme_category=category,
programme_form=programme_form,
verbose_name=verbose_name,
),
)
Expand Down
2 changes: 0 additions & 2 deletions programme/templates/programme_admin_mail_view.pug
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ block admin_content
table.table.table-striped
thead
tr
//- th.hidden-xs Kanava
th Otsikko
th.hidden-xs Vastaanottaja
th.hidden-xs Lähetetty
th.hidden-xs Vanhennettu
tbody
for message in messages
tr
//- td.hidden-xs {{ message.get_channel_display }}
td: a(href='{% url "programme:admin_mail_editor_view" event.slug message.pk %}') {{ message.subject_template }}
td.hidden-xs {{ message.recipient }}
td.hidden-xs {{ message.sent_at|date }}
Expand Down
5 changes: 5 additions & 0 deletions programme/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ def test_programmes_without_end_time_showing_as_past(self):

@pytest.mark.django_db
def test_programme_mass_messages():
"""
Tests two programme message use cases:
1. A programme message is sent before a programme host is added. They get the message when added.
2. Another programme message is sent after. They get that too.
"""
meta, _ = ProgrammeEventMeta.get_or_create_dummy()
EmailAliasDomain.get_or_create_dummy()
InternalEmailAlias.ensure_internal_email_aliases()
Expand Down

0 comments on commit 719ebb9

Please sign in to comment.