Skip to content

Commit

Permalink
Update organization invitation email templates and remove unwanted st…
Browse files Browse the repository at this point in the history
…atuses from the model
  • Loading branch information
rajpatel24 committed Jan 16, 2025
1 parent 1674881 commit c230f54
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@ class Migration(migrations.Migration):
choices=[
('accepted', 'Accepted'),
('cancelled', 'Cancelled'),
('complete', 'Complete'),
('declined', 'Declined'),
('expired', 'Expired'),
('failed', 'Failed'),
('in_progress', 'In Progress'),
('pending', 'Pending'),
('resent', 'Resent'),
],
Expand Down
14 changes: 10 additions & 4 deletions kobo/apps/organizations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,8 @@ class OrganizationInviteStatusChoices(models.TextChoices):

ACCEPTED = 'accepted'
CANCELLED = 'cancelled'
COMPLETE = 'complete'
DECLINED = 'declined'
EXPIRED = 'expired'
FAILED = 'failed'
IN_PROGRESS = 'in_progress'
PENDING = 'pending'
RESENT = 'resent'

Expand Down Expand Up @@ -328,6 +325,14 @@ def send_invite_email(self):
if is_registered_user
else self.invitee_identifier
)

# Get recipient role with an article
recipient_role = self.invitee_role
if recipient_role and recipient_role[0].lower() in 'aeiou':
recipient_role = 'an ' + recipient_role
else:
recipient_role = 'a ' + recipient_role

# To avoid circular import
User = apps.get_model('kobo_auth', 'User')
has_multiple_accounts = User.objects.filter(email=to_email).count() > 1
Expand All @@ -341,7 +346,8 @@ def send_invite_email(self):
if is_registered_user
else self.invitee_identifier
),
'recipient_role': self.invitee_role,
'recipient_email': to_email,
'recipient_role': recipient_role,
'organization_name': organization_name,
'base_url': settings.KOBOFORM_URL,
'invite_uid': self.guid,
Expand Down
106 changes: 53 additions & 53 deletions kobo/apps/organizations/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,47 +247,6 @@ class Meta:
'modified'
]

def _handle_invitee_assignment(self, instance):
"""
Assigns the invitee to the invite after the external user registers
and accepts the invite
"""
invitee_identifier = instance.invitee_identifier
if invitee_identifier and not instance.invitee:
try:
instance.invitee = User.objects.get(email=invitee_identifier)
instance.save(update_fields=['invitee'])
except User.DoesNotExist:
raise NotFound({'detail': t(INVITE_NOT_FOUND_ERROR)})

def _handle_status_update(self, instance, status):
instance.status = getattr(
OrganizationInviteStatusChoices, status.upper()
)
instance.save(update_fields=['status'])
self._send_status_email(instance, status)

def _send_status_email(self, instance, status):
status_map = {
'accepted': instance.send_acceptance_email,
'declined': instance.send_refusal_email,
'resent': instance.send_invite_email
}

email_func = status_map.get(status)
if email_func:
email_func()

def _update_invitee_organization(self, instance):
"""
Update the organization of the invitee after accepting the invitation
"""
org_user = OrganizationUser.objects.get(user=instance.invitee)
Organization.objects.filter(organization_users=org_user).delete()
org_user.organization = instance.invited_by.organization
org_user.is_admin = instance.invitee_role == 'admin'
org_user.save()

def create(self, validated_data):
"""
Create multiple invitations for the provided invitees.
Expand Down Expand Up @@ -336,6 +295,59 @@ def create(self, validated_data):

return invites

def update(self, instance, validated_data):
status = validated_data.get('status')
if status == 'accepted':
self._handle_invitee_assignment(instance)
self.validate_invitation_acceptance(instance)
self._update_invitee_organization(instance)

# Transfer ownership of invitee's assets to the organization
transfer_member_data_ownership_to_org(instance.invitee.id)
self._handle_status_update(instance, status)
return instance

def _handle_invitee_assignment(self, instance):
"""
Assigns the invitee to the invite after the external user registers
and accepts the invite
"""
invitee_identifier = instance.invitee_identifier
if invitee_identifier and not instance.invitee:
try:
instance.invitee = User.objects.get(email=invitee_identifier)
instance.save(update_fields=['invitee'])
except User.DoesNotExist:
raise NotFound({'detail': t(INVITE_NOT_FOUND_ERROR)})

def _handle_status_update(self, instance, status):
instance.status = getattr(
OrganizationInviteStatusChoices, status.upper()
)
instance.save(update_fields=['status'])
self._send_status_email(instance, status)

def _send_status_email(self, instance, status):
status_map = {
'accepted': instance.send_acceptance_email,
'declined': instance.send_refusal_email,
'resent': instance.send_invite_email
}

email_func = status_map.get(status)
if email_func:
email_func()

def _update_invitee_organization(self, instance):
"""
Update the organization of the invitee after accepting the invitation
"""
org_user = OrganizationUser.objects.get(user=instance.invitee)
Organization.objects.filter(organization_users=org_user).delete()
org_user.organization = instance.invited_by.organization
org_user.is_admin = instance.invitee_role == 'admin'
org_user.save()

def get_invited_by(self, invite):
return reverse(
'user-kpi-detail',
Expand Down Expand Up @@ -370,18 +382,6 @@ def to_representation(self, instance):
representation['invitee'] = None
return representation

def update(self, instance, validated_data):
status = validated_data.get('status')
if status == 'accepted':
self._handle_invitee_assignment(instance)
self.validate_invitation_acceptance(instance)
self._update_invitee_organization(instance)

# Transfer ownership of invitee's assets to the organization
transfer_member_data_ownership_to_org.delay(instance.invitee.id)
self._handle_status_update(instance, status)
return instance

def validate_invitation_acceptance(self, instance):
"""
Validate the acceptance of an invitation
Expand Down
2 changes: 0 additions & 2 deletions kobo/apps/organizations/templates/emails/accepted_invite.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

<p>{% trans "All projects, submissions, data storage, transcription and translation usage for their projects will be transferred to you." %}</p>

<p>{% trans "Note: You will continue to have permissions to manage these projects until the user permissions are changed." %}</p>

<p>
&nbsp;-&nbsp;KoboToolbox
</p>
2 changes: 0 additions & 2 deletions kobo/apps/organizations/templates/emails/accepted_invite.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@

{% trans "All projects, submissions, data storage, transcription and translation usage for their projects will be transferred to you." %}

{% trans "Note: You will continue to have permissions to manage these projects until the user permissions are changed." %}

- KoboToolbox
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{% load i18n %}
<p>{% trans "Hello," %}</p>
{% if has_multiple_accounts %}
<p>{% trans "Hello" %} {{ recipient_email }},</p>
{% else %}
<p>{% trans "Hello" %} {{ recipient_username }},</p>
{% endif %}

<p>{% blocktrans %}{{ sender_name }} ({{ sender_email }}, username: {{ sender_username }}) has invited you (username: {{ recipient_username }}) to join {{ organization_name }} organization as {{recipient_role}}.{% endblocktrans %}</p>
<p>{% blocktrans %}{{ sender_name }} ({{ sender_email }}, username {{ sender_username }}) has invited you to join {{ organization_name }} organization as {{recipient_role}}.{% endblocktrans %}</p>
{% if has_multiple_accounts %}
<p>If you already have an account (or have several accounts), please sign in with the correct account.</p>
<p>{% blocktrans %}If you already have an account (or have several accounts), please sign in with the correct account. If you don't already have a KoboToolbox account, you can create one <a href="{{ base_url }}/accounts/signup/" target="_blank">here</a>. After creating your account, click on the link below to accept the invite.{% endblocktrans %}</p>
{% endif %}

<p>{% trans "What joining the organization means for you:" %}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{% load i18n %}
{% trans "Hello," %}
{% if has_multiple_accounts %}
{% trans "Hello" %} {{ recipient_email }},
{% else %}
{% trans "Hello" %} {{ recipient_username }},
{% endif %}

{% blocktrans %}{{ sender_name }} ({{ sender_email }}, username: {{ sender_username }}) has invited you (username: {{ recipient_username }}) to join {{ organization_name }} organization as {{recipient_role}}.{% endblocktrans %}
{% blocktrans %}{{ sender_name }} ({{ sender_email }}, username {{ sender_username }}) has invited you to join {{ organization_name }} organization as {{recipient_role}}.{% endblocktrans %}
{% if has_multiple_accounts %}
If you already have an account (or have several accounts), please sign in with the correct account.
{% blocktrans %}If you already have an account (or have several accounts), please sign in with the correct account. If you don't already have a KoboToolbox account, you can create one <a href="{{ base_url }}/accounts/signup/" target="_blank">here</a>. After creating your account, click on the link below to accept the invite.{% endblocktrans %}
{% endif %}

{% trans "What joining the organization means for you:" %}
Expand Down

0 comments on commit c230f54

Please sign in to comment.