diff --git a/amy/extforms/tests/test_training_request_form.py b/amy/extforms/tests/test_training_request_form.py index 9b4791701..c3265665c 100644 --- a/amy/extforms/tests/test_training_request_form.py +++ b/amy/extforms/tests/test_training_request_form.py @@ -1,5 +1,6 @@ from datetime import date, timedelta +from django.conf import settings from django.core import mail from django.forms import CheckboxInput, HiddenInput from django.test import override_settings @@ -13,6 +14,10 @@ class TestTrainingRequestForm(TestBase): INVALID_MEMBER_CODE_ERROR = "This code is invalid." + MEMBER_CODE_OVERRIDE_LABEL = "Continue with registration code marked as invalid" + MEMBER_CODE_OVERRIDE_EMAIL_WARNING = ( + "A member of our team will check the code and follow up with you" + ) def setUp(self): self._setUpUsersAndLogin() @@ -108,6 +113,8 @@ def test_request_added(self): # Arrange email = self.data.get("email") self.passCaptcha(self.data) + # before tests, check if the template invalid string exists + self.assertTrue(settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"]) # Act rv = self.client.post(reverse("training_request"), self.data, follow=True) @@ -123,6 +130,11 @@ def test_request_added(self): self.assertEqual(msg.to, [email]) self.assertEqual(msg.subject, TrainingRequestCreate.autoresponder_subject) self.assertIn("A copy of your request", msg.body) + self.assertNotIn(self.MEMBER_CODE_OVERRIDE_LABEL, msg.body) + self.assertNotIn(self.MEMBER_CODE_OVERRIDE_EMAIL_WARNING, msg.body) + self.assertNotIn( + settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"], msg.body + ) def test_invalid_request_not_added(self): # Arrange @@ -409,6 +421,8 @@ def test_member_code_validation__code_valid_override_full_request(self): self.data["member_code"] = "valid123" self.data["member_code_override"] = True self.passCaptcha(self.data) + # before tests, check if the template invalid string exists + self.assertTrue(settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"]) # Act rv = self.client.post(reverse("training_request"), data=self.data, follow=True) @@ -419,3 +433,41 @@ def test_member_code_validation__code_valid_override_full_request(self): self.assertFalse( TrainingRequest.objects.get(member_code="valid123").member_code_override ) + + # Test that the sender was emailed with correct content + self.assertEqual(len(mail.outbox), 1) + msg = mail.outbox[0] + self.assertNotIn(self.MEMBER_CODE_OVERRIDE_LABEL, msg.body) + self.assertNotIn(self.MEMBER_CODE_OVERRIDE_EMAIL_WARNING, msg.body) + self.assertNotIn( + settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"], msg.body + ) + + def test_member_code_validation__code_invalid_override_full_request(self): + """Sent email should include the member_code_override field if used.""" + # Arrange + self.setUpMembership() + self.data["member_code"] = "invalid" + self.data["member_code_override"] = True + self.passCaptcha(self.data) + # before tests, check if the template invalid string exists + self.assertTrue(settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"]) + + # Act + rv = self.client.post(reverse("training_request"), data=self.data, follow=True) + + # Assert + self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.resolver_match.view_name, "training_request_confirm") + self.assertTrue( + TrainingRequest.objects.get(member_code="invalid").member_code_override + ) + + # Test that the sender was emailed with correct content + self.assertEqual(len(mail.outbox), 1) + msg = mail.outbox[0] + self.assertIn(self.MEMBER_CODE_OVERRIDE_LABEL, msg.body) + self.assertIn(self.MEMBER_CODE_OVERRIDE_EMAIL_WARNING, msg.body) + self.assertNotIn( + settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"], msg.body + ) diff --git a/amy/templates/includes/trainingrequest_details.html b/amy/templates/includes/trainingrequest_details.html index c874c1dfc..80ac3eaa3 100644 --- a/amy/templates/includes/trainingrequest_details.html +++ b/amy/templates/includes/trainingrequest_details.html @@ -26,8 +26,10 @@
- We receive hundreds of applications, and we cannot provide no-cost training for every applicant. Please, don't let that discourage you! We'd like to help you bring workshops and instructor training to your organisation. In the meantime, please get involved! + We receive hundreds of applications, and we cannot provide no-cost training for every applicant. Please, don't let that discourage you! We'd like to help you bring workshops and instructor training to your organisation.
In the meantime, please get involved! @@ -50,5 +50,14 @@ The Carpentries Instructor Training Team ++ Warning: Your registration code "{{object.member_code}}" seems to be invalid. This may be due to a typo, an expired code, a code that has not yet been activated, or a code with no training seats remaining. A member of our team will check the code and follow up with you if there are any problems that require your attention. +
+{% endif %} {% include "includes/trainingrequest_details.html" with admin=False object=object %} diff --git a/amy/templates/mailing/training_request.txt b/amy/templates/mailing/training_request.txt index 3dd6ca81d..270a4dff0 100644 --- a/amy/templates/mailing/training_request.txt +++ b/amy/templates/mailing/training_request.txt @@ -7,7 +7,7 @@ Open Training applications are placed in an application queue to be considered f If you have a specific need to be trained sooner (e.g. an upcoming workshop) please let us know. Multiple applicants from a single institution generally will not be invited at once, but may be accepted individually over time. To more rapidly build an Instructor community at your institution, consider becoming a Member. For more information see: https://carpentries.org/membership/ or get in touch with memberships@carpentries.org to learn more about how we can help you make the case at your organisation. -We receive hundreds of applications, and we cannot provide no-cost training for every applicant. Please, don't let that discourage you! We'd like to help you bring workshops and instructor training to your organisation. In the meantime, please get involved! +We receive hundreds of applications, and we cannot provide no-cost training for every applicant. Please, don't let that discourage you! We'd like to help you bring workshops and instructor training to your organisation. In the meantime, please get involved! Join our discussion email list: https://carpentries.topicbox.com/groups/discuss @@ -27,9 +27,16 @@ The Carpentries Instructor Training Team A copy of your request is included below for your reference. +{% if object.member_code_override %} +**Warning:** Your registration code "{{object.member_code}}" seems to be invalid. This may be due to a typo, an expired code, a code that has not yet been activated, or a code with no training seats remaining. A member of our team will check the code and follow up with you if there are any problems that require your attention. +{% endif %} + Submission date: {{ object.created_at }} Application Type: {{ object.get_review_process_display|default:"---" }} Registration Code: {{ object.member_code|default:"—" }} +{% if object.member_code_override %} +Continue with registration code marked as invalid: {{object.member_code_override|yesno}} +{% endif %} Person: {{object.personal}} {{object.middle}} {{object.family}} <{{object.email}}> Github: {{ object.github|default:"---" }} Occupation: {{ object.get_occupation_display }} {{ object.occupation_other }} diff --git a/amy/templates/mailing/workshoprequest.txt b/amy/templates/mailing/workshoprequest.txt index 505569db7..e02427ef1 100644 --- a/amy/templates/mailing/workshoprequest.txt +++ b/amy/templates/mailing/workshoprequest.txt @@ -32,6 +32,7 @@ instructors in such short time. Submission date: {{ object.created_at }} Person: {{ object.personal }} {{ object.family }} <{{ object.email }}> Institution: {% if object.institution %}{{ object.institution }}{% else %}{{ object.institution_other_name }}{% endif %}{% if object.institution_department %}, {{ object.institution_department }}{% endif %} +Member registration code: {{ object.member_code|default:"—" }} Workshop location: {{ object.location }} Country: {{ object.country.name }} Requested workshop types: {% for type in object.requested_workshop_types.all %}{{ type }}{% if not forloop.last %}, {% endif %}{% endfor %}