membershipworks: Automatically send survey emails to event attendees
This commit is contained in:
parent
b1a7467eda
commit
dcf483d19e
@ -7,6 +7,7 @@ def post_migrate_callback(sender, **kwargs):
|
||||
|
||||
from cmsmanage.django_q2_helper import ensure_scheduled
|
||||
|
||||
from .tasks.event_survey_emails import send_survey_emails
|
||||
from .tasks.scrape import scrape_events, scrape_membershipworks
|
||||
from .tasks.ucsAccounts import sync_accounts
|
||||
|
||||
@ -29,6 +30,12 @@ def post_migrate_callback(sender, **kwargs):
|
||||
minutes=15,
|
||||
)
|
||||
|
||||
ensure_scheduled(
|
||||
sync_accounts.q_task_group,
|
||||
send_survey_emails,
|
||||
schedule_type=Schedule.HOURLY,
|
||||
)
|
||||
|
||||
|
||||
class MembershipworksConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
|
@ -0,0 +1,17 @@
|
||||
import logging
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from membershipworks.tasks.event_survey_emails import logger, send_survey_emails
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, verbosity: int, **options):
|
||||
verbosity_levels = {
|
||||
0: logging.ERROR,
|
||||
1: logging.WARNING,
|
||||
2: logging.INFO,
|
||||
3: logging.DEBUG,
|
||||
}
|
||||
logger.setLevel(verbosity_levels.get(verbosity, logging.WARNING))
|
||||
send_survey_emails()
|
@ -0,0 +1,22 @@
|
||||
# Generated by Django 5.0.6 on 2024-05-20 22:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("membershipworks", "0018_eventext_details_timestamp"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="eventext",
|
||||
name="should_survey",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="eventext",
|
||||
name="survey_email_sent",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@ -554,6 +554,9 @@ class EventExt(Event):
|
||||
|
||||
registrations = models.JSONField(null=True, blank=True)
|
||||
|
||||
should_survey = models.BooleanField(default=False)
|
||||
survey_email_sent = models.BooleanField(default=False)
|
||||
|
||||
def get_absolute_url(self) -> str:
|
||||
return reverse("membershipworks:event-detail", kwargs={"eid": self.eid})
|
||||
|
||||
|
62
membershipworks/tasks/event_survey_emails.py
Normal file
62
membershipworks/tasks/event_survey_emails.py
Normal file
@ -0,0 +1,62 @@
|
||||
import logging
|
||||
from collections.abc import Iterable
|
||||
from urllib.parse import quote, urlencode
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import mail
|
||||
from django.db.models.functions import Now
|
||||
|
||||
from cmsmanage.email import TemplatedMultipartEmail
|
||||
from membershipworks.models import EventExt
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EventSurveyEmail(TemplatedMultipartEmail):
|
||||
# TODO: better wording
|
||||
subject = (
|
||||
"[Claremont MakerSpace] Please fill out a survey for your recent CMS class!"
|
||||
)
|
||||
from_email = "CMS Classes <classes@claremontmakerspace.org>"
|
||||
|
||||
template = "membershipworks/email/event_survey.dj.html"
|
||||
|
||||
@staticmethod
|
||||
def survey_url(event: EventExt, attendee_name: str, attendee_email: str) -> str:
|
||||
return "https://claremontmakerspace.org/class-evaluation-form?" + urlencode(
|
||||
{
|
||||
"event_id": event.eid,
|
||||
"instructor_name": str(event.instructor) if event.instructor else "",
|
||||
"event_name": event.title,
|
||||
"event_date": event.start.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"participant_name": attendee_name,
|
||||
"participant_email": attendee_email,
|
||||
},
|
||||
quote_via=quote,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def render_for_event(cls, event: EventExt) -> Iterable[mail.EmailMessage]:
|
||||
for name, email in event.attendees.values_list("name", "email"):
|
||||
sanitized_email = mail.message.sanitize_address(
|
||||
(name, email), settings.DEFAULT_CHARSET
|
||||
)
|
||||
survey_url = cls.survey_url(event, name, email)
|
||||
yield cls.render(
|
||||
{"event": event, "attendee_name": name, "survey_url": survey_url},
|
||||
to=[sanitized_email],
|
||||
)
|
||||
|
||||
|
||||
def send_survey_emails():
|
||||
with mail.get_connection() as conn:
|
||||
for event in EventExt.objects.filter(
|
||||
occurred=True, should_survey=True, survey_email_sent=False, end__lt=Now()
|
||||
):
|
||||
logger.info("Sending survey messages for event: %s", event)
|
||||
|
||||
# mark as sent even if we don't finish, to prevent sending duplicates
|
||||
event.survey_email_sent = True
|
||||
event.save()
|
||||
|
||||
conn.send_messages(list(EventSurveyEmail.render_for_event(event)))
|
@ -0,0 +1,19 @@
|
||||
{% load nh3_tags %}
|
||||
|
||||
<p>Dear {{ attendee_name }},</p>
|
||||
<p>
|
||||
Thank you for recently attending "{{ event.details.ttl|nh3 }}" at CMS on {{ event.start|date }}! We hope you enjoyed the experience and found it both informative and inspiring.
|
||||
To help us continue to offer high-quality classes and improve our programs, we would greatly appreciate your feedback.
|
||||
We kindly ask you to take a few minutes to complete a brief survey about your experience.
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{ survey_url }}">Click here to fill out the survey</a>
|
||||
</p>
|
||||
<p>
|
||||
Your insights are invaluable to us and will directly contribute to enhancing our offerings and ensuring that we meet the needs and expectations of our community.
|
||||
Thank you in advance for your time and feedback. If you have any additional comments or questions, please feel free to reach out to us at <a href="mailto:info@claremontmakerspace.org">info@claremontmakerspace.org</a>.
|
||||
</p>
|
||||
<p>
|
||||
<div>Best regards,</div>
|
||||
<div>The Claremont MakerSpace Team</div>
|
||||
</p>
|
Loading…
Reference in New Issue
Block a user