Skip to content

Commit

Permalink
Ability to notify submissions status change (#4353)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcoacierno authored Feb 9, 2025
1 parent 073383e commit b652530
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 2 deletions.
3 changes: 1 addition & 2 deletions backend/notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ class EmailTemplate(TimeStampedModel):
*BASE_PLACEHOLDERS,
"conference_name",
"proposal_title",
"invitation_url",
"proposal_type",
"speaker_name",
"is_reminder",
],
EmailTemplateIdentifier.proposal_scheduled: [
*BASE_PLACEHOLDERS,
Expand Down
49 changes: 49 additions & 0 deletions backend/submissions/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from django.urls import reverse
from grants.tasks import get_name
from notifications.models import EmailTemplate, EmailTemplateIdentifier
from custom_admin.admin import (
confirm_pending_status,
reset_pending_status_back_to_status,
Expand All @@ -8,6 +10,7 @@

from django import forms
from django.db.models import F
from django.db import transaction
from django.contrib import admin, messages
from django.utils.html import mark_safe
from django.utils.translation import gettext_lazy as _
Expand Down Expand Up @@ -322,6 +325,51 @@ class SubmissionCommentAdmin(admin.ModelAdmin):
list_display = ("submission", "author", "text")


NEW_STATUS_TO_EMAIL_TEMPLATE = {
Submission.STATUS.accepted: EmailTemplateIdentifier.proposal_accepted,
Submission.STATUS.rejected: EmailTemplateIdentifier.proposal_rejected,
Submission.STATUS.waiting_list: EmailTemplateIdentifier.proposal_in_waiting_list,
}


@admin.action(description="Apply and notify status change")
@validate_single_conference_selection
@transaction.atomic
def apply_and_notify_status_change(modeladmin, request, queryset):
conference = queryset.first().conference
objs = list(queryset.select_related("speaker").prefetch_related("type"))
count = len(objs)

for submission in objs:
submission.status = submission.pending_status
placeholders = {
"conference_name": conference.name.localize("en"),
"proposal_title": submission.title.localize("en"),
"proposal_type": submission.type.name,
"speaker_name": get_name(submission.speaker, "there"),
}

template = NEW_STATUS_TO_EMAIL_TEMPLATE[submission.status]
email_template = EmailTemplate.objects.for_conference(
conference
).get_by_identifier(template)
email_template.send_email(
recipient=submission.speaker,
placeholders=placeholders,
)

Submission.objects.bulk_update(
objs,
["status"],
)

messages.add_message(
request,
messages.SUCCESS,
f"Confirmed and notified {count} proposals",
)


@admin.register(SubmissionConfirmPendingStatusProxy)
class SubmissionConfirmPendingStatusProxyAdmin(admin.ModelAdmin):
list_display = (
Expand All @@ -338,6 +386,7 @@ class SubmissionConfirmPendingStatusProxyAdmin(admin.ModelAdmin):
search_fields = ("speaker__full_name", "speaker__email", "title")
list_display_links = None
actions = [
apply_and_notify_status_change,
confirm_pending_status,
reset_pending_status_back_to_status,
]
Expand Down
85 changes: 85 additions & 0 deletions backend/submissions/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from unittest.mock import call
from conferences.tests.factories import ConferenceFactory
from notifications.tests.factories import EmailTemplateFactory
from notifications.models import EmailTemplateIdentifier, SentEmail
import pytest
from submissions.admin import (
apply_and_notify_status_change,
send_proposal_in_waiting_list_email_action,
send_proposal_rejected_email_action,
)
Expand Down Expand Up @@ -59,3 +63,84 @@ def test_send_proposal_in_waiting_list_email_action(rf, mocker):
],
any_order=True,
)


def test_apply_and_notify_status_change(rf, mocker):
mocker.patch("submissions.admin.messages")

conference = ConferenceFactory()
proposal_accepted_template = EmailTemplateFactory(
identifier=EmailTemplateIdentifier.proposal_accepted,
conference=conference,
)
proposal_rejected_template = EmailTemplateFactory(
identifier=EmailTemplateIdentifier.proposal_rejected,
conference=conference,
)
proposal_in_waiting_list_template = EmailTemplateFactory(
identifier=EmailTemplateIdentifier.proposal_in_waiting_list,
conference=conference,
)

accepted_submission = SubmissionFactory(
conference=conference,
status=Submission.STATUS.proposed,
pending_status=Submission.STATUS.accepted,
speaker__full_name="Marco",
)

rejected_submission = SubmissionFactory(
conference=conference,
status=Submission.STATUS.proposed,
pending_status=Submission.STATUS.rejected,
speaker__full_name="Jane",
)

waiting_list_proposal = SubmissionFactory(
conference=conference,
status=Submission.STATUS.proposed,
pending_status=Submission.STATUS.waiting_list,
speaker__full_name="John",
)

apply_and_notify_status_change(
None,
rf.post("/"),
queryset=Submission.objects.filter(status=Submission.STATUS.proposed),
)

assert SentEmail.objects.filter(
recipient=accepted_submission.speaker,
email_template=proposal_accepted_template,
conference=conference,
placeholders={
"conference_name": conference.name.localize("en"),
"proposal_title": accepted_submission.title.localize("en"),
"proposal_type": accepted_submission.type.name,
"speaker_name": "Marco",
},
).exists()

assert SentEmail.objects.filter(
recipient=rejected_submission.speaker,
email_template=proposal_rejected_template,
conference=conference,
placeholders={
"conference_name": conference.name.localize("en"),
"proposal_title": rejected_submission.title.localize("en"),
"proposal_type": rejected_submission.type.name,
"speaker_name": "Jane",
},
).exists()

assert SentEmail.objects.filter(
recipient=waiting_list_proposal.speaker,
email_template=proposal_in_waiting_list_template,
conference=conference,
placeholders={
"conference_name": conference.name.localize("en"),
"proposal_title": waiting_list_proposal.title.localize("en"),
"proposal_type": waiting_list_proposal.type.name,
"speaker_name": "John",
},
).exists()

0 comments on commit b652530

Please sign in to comment.