Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions backend/api/submissions/mutations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from urllib.parse import urljoin
from django.conf import settings
from grants.tasks import get_name
from notifications.models import EmailTemplate, EmailTemplateIdentifier
from strawberry.scalars import JSON

from django.db import transaction
Expand Down Expand Up @@ -383,6 +387,24 @@ def send_submission(
"cfp",
)

email_template = EmailTemplate.objects.for_conference(
conference
).get_by_identifier(EmailTemplateIdentifier.proposal_received_confirmation)

proposal_url = urljoin(
settings.FRONTEND_URL,
f"/submission/{instance.hashid}",
)

email_template.send_email(
recipient=request.user,
placeholders={
"user_name": get_name(request.user, "there"),
"proposal_title": instance.title.localize("en"),
"proposal_url": proposal_url,
},
)

def _notify_new_submission():
notify_new_cfp_submission.delay(
submission_id=instance.id,
Expand Down
92 changes: 90 additions & 2 deletions backend/api/submissions/tests/test_send_submission.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from notifications.models import EmailTemplateIdentifier
from notifications.tests.factories import EmailTemplateFactory
from privacy_policy.models import PrivacyPolicyAcceptanceRecord
from files_upload.tests.factories import FileFactory
from conferences.tests.factories import (
Expand Down Expand Up @@ -138,7 +140,11 @@ def _submit_proposal(client, conference, submission, **kwargs):
)


def test_submit_talk(graphql_client, user, django_capture_on_commit_callbacks, mocker):
def test_submit_talk(
graphql_client, user, django_capture_on_commit_callbacks, mocker, settings
):
settings.FRONTEND_URL = "http://testserver"
mock_email_template = mocker.patch("api.submissions.mutations.EmailTemplate")
mock_notify = mocker.patch("api.submissions.mutations.notify_new_cfp_submission")
graphql_client.force_login(user)

Expand All @@ -151,6 +157,11 @@ def test_submit_talk(graphql_client, user, django_capture_on_commit_callbacks, m
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

speaker_photo = FileFactory().id

with django_capture_on_commit_callbacks(execute=True):
Expand Down Expand Up @@ -208,6 +219,15 @@ def test_submit_talk(graphql_client, user, django_capture_on_commit_callbacks, m

mock_notify.delay.assert_called_once()

mock_email_template.objects.for_conference().get_by_identifier().send_email.assert_called_once_with(
recipient=user,
placeholders={
"user_name": user.full_name,
"proposal_title": "English",
"proposal_url": f"http://testserver/submission/{talk.hashid}",
},
)


def test_submit_talk_with_photo_to_upload(graphql_client, user, mocker):
graphql_client.force_login(user)
Expand All @@ -220,7 +240,10 @@ def test_submit_talk_with_photo_to_upload(graphql_client, user, mocker):
durations=("50",),
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)
speaker_photo = FileFactory().id

resp, variables = _submit_talk(
Expand Down Expand Up @@ -253,6 +276,11 @@ def test_submit_talk_without_photo_fails(graphql_client, user, mocker):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, variables = _submit_talk(
graphql_client,
conference,
Expand Down Expand Up @@ -282,6 +310,11 @@ def test_submit_talk_with_existing_participant(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

participant = Participant.objects.create(
conference=conference, user_id=user.id, bio="old bio"
)
Expand Down Expand Up @@ -339,6 +372,11 @@ def test_submit_talk_with_missing_data_of_other_language_fails(graphql_client, u
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_talk(
graphql_client,
conference,
Expand Down Expand Up @@ -370,6 +408,11 @@ def test_submit_talk_with_missing_data_fails(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_talk(
graphql_client,
conference,
Expand Down Expand Up @@ -413,6 +456,11 @@ def test_submit_talk_with_multiple_languages(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, variables = _submit_talk(
graphql_client,
conference,
Expand Down Expand Up @@ -707,6 +755,11 @@ def test_cannot_propose_a_talk_if_a_cfp_is_not_specified(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_talk(graphql_client, conference)

assert resp["data"]["sendSubmission"]["__typename"] == "SendSubmissionErrors"
Expand All @@ -729,6 +782,11 @@ def test_same_user_can_propose_multiple_talks_to_the_same_conference(
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_talk(graphql_client, conference, title={"en": "My first talk"})

assert resp["data"]["sendSubmission"]["title"] == "My first talk"
Expand Down Expand Up @@ -760,6 +818,11 @@ def test_submit_tutorial(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_tutorial(
graphql_client, conference, title={"en": "My first tutorial"}
)
Expand All @@ -785,6 +848,11 @@ def test_submit_tutorial_and_talk_to_the_same_conference(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_tutorial(
graphql_client, conference, title={"en": "My first tutorial"}
)
Expand Down Expand Up @@ -818,6 +886,11 @@ def test_notes_are_not_required(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_tutorial(graphql_client, conference, notes="")

assert resp["data"]["sendSubmission"]["__typename"] == "Submission"
Expand Down Expand Up @@ -850,6 +923,16 @@ def test_same_user_can_submit_talks_to_different_conferences(graphql_client, use
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference1,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

EmailTemplateFactory(
conference=conference2,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

resp, _ = _submit_talk(graphql_client, conference1, title={"en": "My first talk"})

assert resp["data"]["sendSubmission"]["title"] == "My first talk"
Expand Down Expand Up @@ -889,6 +972,11 @@ def test_create_submission_tags(graphql_client, user):
audience_levels=("Beginner",),
)

EmailTemplateFactory(
conference=conference,
identifier=EmailTemplateIdentifier.proposal_received_confirmation,
)

python, _ = SubmissionTag.objects.get_or_create(name="python")
graphql, _ = SubmissionTag.objects.get_or_create(name="GraphQL")

Expand Down
2 changes: 1 addition & 1 deletion backend/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

@pytest.fixture()
def user(db):
return UserFactory(email="[email protected]", is_staff=False)
return UserFactory(email="[email protected]", is_staff=False, full_name="Jane Doe")


@pytest.fixture()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.1.1 on 2024-12-01 14:41

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('notifications', '0018_alter_emailtemplate_identifier'),
]

operations = [
migrations.AlterField(
model_name='emailtemplate',
name='identifier',
field=models.CharField(choices=[('proposal_accepted', 'Proposal accepted'), ('proposal_rejected', 'Proposal rejected'), ('proposal_in_waiting_list', 'Proposal in waiting list'), ('proposal_scheduled_time_changed', 'Proposal scheduled time changed'), ('proposal_received_confirmation', 'Proposal received confirmation'), ('speaker_communication', 'Speaker communication'), ('voucher_code', 'Voucher code'), ('reset_password', '[System] Reset password'), ('grant_application_confirmation', 'Grant application confirmation'), ('grant_approved', 'Grant approved'), ('grant_rejected', 'Grant rejected'), ('grant_waiting_list', 'Grant waiting list'), ('grant_waiting_list_update', 'Grant waiting list update'), ('grant_voucher_code', 'Grant voucher code'), ('sponsorship_brochure', 'Sponsorship brochure'), ('custom', 'Custom')], max_length=200, verbose_name='identifier'),
),
]
10 changes: 10 additions & 0 deletions backend/notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class EmailTemplateIdentifier(models.TextChoices):
"proposal_scheduled_time_changed",
_("Proposal scheduled time changed"),
)
proposal_received_confirmation = (
"proposal_received_confirmation",
_("Proposal received confirmation"),
)
speaker_communication = "speaker_communication", _("Speaker communication")

voucher_code = "voucher_code", _("Voucher code")
Expand Down Expand Up @@ -88,6 +92,12 @@ class EmailTemplate(TimeStampedModel):
*BASE_PLACEHOLDERS,
"user_name",
],
EmailTemplateIdentifier.proposal_received_confirmation: [
*BASE_PLACEHOLDERS,
"user_name",
"proposal_title",
"proposal_url",
],
EmailTemplateIdentifier.grant_approved: [
*BASE_PLACEHOLDERS,
"reply_url",
Expand Down