diff --git a/taiga/projects/api.py b/taiga/projects/api.py index 914c4f77..114b78a0 100644 --- a/taiga/projects/api.py +++ b/taiga/projects/api.py @@ -193,6 +193,7 @@ class MembershipViewSet(ModelCrudViewSet): data = serializer.data project = models.Project.objects.get(id=data["project_id"]) + invitation_extra_text = data.get("invitation_extra_text", None) self.check_permissions(request, 'bulk_create', project) # TODO: this should be moved to main exception handler instead @@ -201,6 +202,7 @@ class MembershipViewSet(ModelCrudViewSet): try: members = services.create_members_in_bulk(data["bulk_memberships"], project=project, + invitation_extra_text=invitation_extra_text, callback=self.post_save, precall=self.pre_save) except ValidationError as err: diff --git a/taiga/projects/migrations/0005_membership_invitation_extra_text.py b/taiga/projects/migrations/0005_membership_invitation_extra_text.py new file mode 100644 index 00000000..b4fffdd8 --- /dev/null +++ b/taiga/projects/migrations/0005_membership_invitation_extra_text.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0004_auto_20141002_2337'), + ] + + operations = [ + migrations.AddField( + model_name='membership', + name='invitation_extra_text', + field=models.TextField(null=True, verbose_name='invitation extra text', blank=True), + preserve_default=True, + ), + ] diff --git a/taiga/projects/models.py b/taiga/projects/models.py index 092d5b7f..ce95161a 100644 --- a/taiga/projects/models.py +++ b/taiga/projects/models.py @@ -70,6 +70,9 @@ class Membership(models.Model): invited_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="ihaveinvited+", null=True, blank=True) + invitation_extra_text = models.TextField(null=True, blank=True, + verbose_name=_("invitation extra text")) + def clean(self): # TODO: Review and do it more robust memberships = Membership.objects.filter(user=self.user, project=self.project) diff --git a/taiga/projects/serializers.py b/taiga/projects/serializers.py index fae3f7f1..43ae4629 100644 --- a/taiga/projects/serializers.py +++ b/taiga/projects/serializers.py @@ -251,3 +251,4 @@ class MemberBulkSerializer(RoleExistsValidator, serializers.Serializer): class MembersBulkSerializer(ProjectExistsValidator, serializers.Serializer): project_id = serializers.IntegerField() bulk_memberships = MemberBulkSerializer(many=True) + invitation_extra_text = serializers.CharField(required=False, max_length=255) diff --git a/taiga/projects/services/invitations.py b/taiga/projects/services/invitations.py index e7cf7339..59da4b80 100644 --- a/taiga/projects/services/invitations.py +++ b/taiga/projects/services/invitations.py @@ -11,6 +11,7 @@ def send_invitation(invitation): template = mbuilder.membership_notification else: template = mbuilder.membership_invitation + email = template(invitation.email, {"membership": invitation}) email.send() diff --git a/taiga/projects/templates/emails/membership_invitation-body-html.jinja b/taiga/projects/templates/emails/membership_invitation-body-html.jinja index 35ffaf41..f388d2bc 100644 --- a/taiga/projects/templates/emails/membership_invitation-body-html.jinja +++ b/taiga/projects/templates/emails/membership_invitation-body-html.jinja @@ -11,6 +11,14 @@

you have been invited to the project '{{ membership.project }}'.

If you want to join to this project go to this link for accept this invitation.

+ + {% if membership.invitation_extra_text %} +

+ Some words from your Taiga Ambassador:
+ {{ membership.invitation_extra_text }} +

+ {% endif %} + diff --git a/taiga/projects/templates/emails/membership_invitation-body-text.jinja b/taiga/projects/templates/emails/membership_invitation-body-text.jinja index 8802a0a4..c08ae538 100644 --- a/taiga/projects/templates/emails/membership_invitation-body-text.jinja +++ b/taiga/projects/templates/emails/membership_invitation-body-text.jinja @@ -7,5 +7,12 @@ you have been invited to the project '{{ membership.project }}'. If you want to join to this project go to {{ final_url }} for accept this invitation. +{% if membership.invitation_extra_text %} + +Some words from your Taiga Ambassador: + +{{ membership.invitation_extra_text }} + +{% endif %} ** More info at ({{ final_url }}) ** diff --git a/tests/integration/test_memberships.py b/tests/integration/test_memberships.py index 389f1fe2..c717cbbf 100644 --- a/tests/integration/test_memberships.py +++ b/tests/integration/test_memberships.py @@ -51,6 +51,29 @@ def test_api_create_bulk_members(client): assert response.data[0]["email"] == john.email assert response.data[1]["email"] == joseph.email +def test_api_create_bulk_members_with_extra_text(client, outbox): + project = f.ProjectFactory() + tester = f.RoleFactory(project=project, name="Tester") + url = reverse("memberships-bulk-create") + + invitation_extra_text = "this is a not so random invitation text" + data = { + "project_id": project.id, + "bulk_memberships": [ + {"role_id": tester.pk, "email": "john@email.com"}, + ], + "invitation_extra_text": invitation_extra_text + } + client.login(project.owner) + response = client.json.post(url, json.dumps(data)) + + assert response.status_code == 200 + assert response.data[0]["email"] == "john@email.com" + + message = outbox[0] + assert len(outbox) == 1 + assert message.to == ["john@email.com"] + assert "this is a not so random invitation text" in message.body def test_api_resend_invitation(client, outbox): invitation = f.create_invitation()