Skip to content

Commit cc9713d

Browse files
authored
Add/update email templates for user deactivation (#2678)
* feat: add user deactivated template ID and migration for service suspension handling * fix: shorten migration name * feat: add comments to SERVICE_SUSPENDED_TEMPLATE_ID and USER_DEACTIVATED_TEMPLATE_ID for clarity * fix: correct variable name in service suspension notification template * fix: final content updates per figma * chore: update subject lines
1 parent 28600c1 commit cc9713d

File tree

2 files changed

+217
-2
lines changed

2 files changed

+217
-2
lines changed

app/config.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,10 @@ class Config(object):
326326
REACHED_DAILY_EMAIL_LIMIT_TEMPLATE_ID = "ee036547-e51b-49f1-862b-10ea982cfceb"
327327
DAILY_EMAIL_LIMIT_UPDATED_TEMPLATE_ID = "97dade64-ea8d-460f-8a34-900b74ee5eb0"
328328
REPORT_DOWNLOAD_TEMPLATE_ID = "8b5c14e1-2c78-4b87-9797-5b8cc8d9a86c"
329-
SERVICE_SUSPENDED_TEMPLATE_ID = "65bbee1b-9c2a-48a6-b95a-d7d70e8f6726"
330-
USER_DEACTIVATED_TEMPLATE_ID = "d0fe2b8c-ddcf-4f9b-8bb7-d79006e7cfa7"
329+
SERVICE_SUSPENDED_TEMPLATE_ID = (
330+
"65bbee1b-9c2a-48a6-b95a-d7d70e8f6726" # Sent when a service is deactivated due to a user being deactivated
331+
)
332+
USER_DEACTIVATED_TEMPLATE_ID = "d0fe2b8c-ddcf-4f9b-8bb7-d79006e7cfa7" # Sent when a user deactivates their own account
331333

332334
# Templates for annual limits
333335
REACHED_ANNUAL_LIMIT_TEMPLATE_ID = "ca6d9205-d923-4198-acdd-d0aa37725c37"
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
"""
2+
3+
Revision ID: 0491_split_deactivate_templates
4+
Revises: 0490_add_service_susp_template
5+
Create Date: 2025-10-28 00:00:00
6+
7+
"""
8+
from datetime import datetime
9+
10+
from alembic import op
11+
from flask import current_app
12+
13+
revision = "0491_split_deactivate_templates"
14+
down_revision = "0490_add_service_susp_template"
15+
16+
# IDs from config
17+
service_suspended_template_id = current_app.config["SERVICE_SUSPENDED_TEMPLATE_ID"]
18+
user_deactivated_template_id = current_app.config["USER_DEACTIVATED_TEMPLATE_ID"]
19+
20+
21+
def _new_service_suspended_content():
22+
return "\n".join(
23+
[
24+
"[[fr]](la version française suit)[[/fr]]",
25+
"",
26+
"[[en]]",
27+
"We’ve suspended ((service_name)) because you’re now the only team member for that service. The other team member deactivated their account.",
28+
"",
29+
"GC Notify requires at least 2 team members per service.",
30+
"",
31+
"To remove the suspension, we need:",
32+
"- Suspended service’s name",
33+
"- Name of a new team member who already has a GC Notify account.",
34+
"",
35+
"When you have this information, [contact us](https://notification.canada.ca/en/contact).",
36+
"",
37+
"The GC Notify Team",
38+
"[[/en]]",
39+
"",
40+
"---",
41+
"",
42+
"[[fr]]",
43+
"Nous avons suspendu le service ((service_name)) parce que vous êtes maintenant la seule personne affectée à ce service. Les autres membres de l’équipe ont désactivé leur compte.",
44+
"",
45+
"Notification GC exige qu’au moins 2 personnes soient affectées à un service.",
46+
"",
47+
"Pour rétablir le service, il faudra nous faire parvenir les éléments suivants :",
48+
"- Le nom du service suspendu",
49+
"- Le nom d’un nouveau membre d’équipe qui a déjà un compte Notification GC.",
50+
"",
51+
"Lorsque vous aurez ces renseignements en main, [contactez-nous](https://notification.canada.ca/fr/contact).",
52+
"",
53+
"L’équipe Notification GC",
54+
"[[/fr]]",
55+
]
56+
)
57+
58+
59+
def _new_user_deactivated_content():
60+
# content from the previous migration 0490 which should now be moved to USER_DEACTIVATED_TEMPLATE_ID
61+
return "\n".join(
62+
[
63+
"[[fr]](la version française suit)[[/fr]]",
64+
"",
65+
"[[en]]",
66+
"You’ve deactivated your GC Notify account.",
67+
"",
68+
"You cannot:",
69+
"- Access GC Notify services.",
70+
"- Manage teams or make changes on GC Notify.",
71+
"",
72+
"If you did not want to deactivate your account, immediately [contact us](https://notification.canada.ca/en/contact).",
73+
"",
74+
"The GC Notify Team",
75+
"[[/en]]",
76+
"",
77+
"---",
78+
"",
79+
"[[fr]]",
80+
"Vous avez désactivé votre compte GC Notify.",
81+
"",
82+
"Vous ne pouvez plus :",
83+
"- Accéder aux services GC Notify ;",
84+
"- Gérer des équipes ou apporter des modifications dans Notification GC.",
85+
"",
86+
"En cas de désactivation involontaire de votre compte, [contactez-nous](https://notification.canada.ca/fr/contact) immédiatement.",
87+
"",
88+
"L’équipe Notification GC",
89+
"[[/fr]]",
90+
]
91+
)
92+
93+
94+
def upgrade():
95+
conn = op.get_bind()
96+
97+
# prepare templates to update/insert
98+
templates_to_update = [
99+
{
100+
"id": service_suspended_template_id,
101+
"name": "Service suspended",
102+
"template_type": "email",
103+
"content": _new_service_suspended_content(),
104+
"subject": "((service_name)) suspended | ((service_name)) suspendu",
105+
"process_type": "normal",
106+
}
107+
]
108+
109+
templates_to_insert = [
110+
{
111+
"id": user_deactivated_template_id,
112+
"name": "User deactivated",
113+
"template_type": "email",
114+
"content": _new_user_deactivated_content(),
115+
"subject": "Account closed | Votre compte a été désactivé",
116+
"process_type": "normal",
117+
}
118+
]
119+
120+
# bump versions for updates
121+
for t in templates_to_update:
122+
current_version = conn.execute("select version from templates where id='{}'".format(t["id"])).fetchone()
123+
t["version"] = (current_version[0] if current_version and current_version[0] is not None else 0) + 1
124+
125+
template_update = """
126+
UPDATE templates SET content = '{}', subject = '{}', version = '{}', updated_at = '{}'
127+
WHERE id = '{}'
128+
"""
129+
130+
template_history_insert = """
131+
INSERT INTO templates_history (id, name, template_type, created_at, content, archived, service_id, subject,
132+
created_by_id, version, process_type, hidden)
133+
VALUES ('{}', '{}', '{}', '{}', '{}', False, '{}', '{}', '{}', {}, '{}', false)
134+
"""
135+
136+
# perform updates
137+
for t in templates_to_update:
138+
op.execute(
139+
template_update.format(
140+
t["content"],
141+
t["subject"],
142+
t["version"],
143+
datetime.utcnow(),
144+
t["id"],
145+
)
146+
)
147+
148+
op.execute(
149+
template_history_insert.format(
150+
t["id"],
151+
t["name"],
152+
t["template_type"],
153+
datetime.utcnow(),
154+
t["content"],
155+
current_app.config["NOTIFY_SERVICE_ID"],
156+
t["subject"],
157+
current_app.config["NOTIFY_USER_ID"],
158+
t["version"],
159+
t["process_type"],
160+
)
161+
)
162+
163+
# insert new template for user_deactivated
164+
template_insert = """
165+
INSERT INTO templates (id, name, template_type, created_at, content, archived, service_id, subject,
166+
created_by_id, version, process_type, hidden)
167+
VALUES ('{}', '{}', '{}', '{}', '{}', False, '{}', '{}', '{}', 1, '{}', false)
168+
"""
169+
170+
template_history_insert_simple = """
171+
INSERT INTO templates_history (id, name, template_type, created_at, content, archived, service_id, subject,
172+
created_by_id, version, process_type, hidden)
173+
VALUES ('{}', '{}', '{}', '{}', '{}', False, '{}', '{}', '{}', 1, '{}', false)
174+
"""
175+
176+
for t in templates_to_insert:
177+
op.execute(
178+
template_insert.format(
179+
t["id"],
180+
t["name"],
181+
t["template_type"],
182+
datetime.utcnow(),
183+
t["content"],
184+
current_app.config["NOTIFY_SERVICE_ID"],
185+
t["subject"],
186+
current_app.config["NOTIFY_USER_ID"],
187+
t["process_type"],
188+
)
189+
)
190+
191+
op.execute(
192+
template_history_insert_simple.format(
193+
t["id"],
194+
t["name"],
195+
t["template_type"],
196+
datetime.utcnow(),
197+
t["content"],
198+
current_app.config["NOTIFY_SERVICE_ID"],
199+
t["subject"],
200+
current_app.config["NOTIFY_USER_ID"],
201+
t["process_type"],
202+
)
203+
)
204+
205+
206+
def downgrade():
207+
# remove both the user_deactivated template and the service_suspended template
208+
for template_id in (user_deactivated_template_id, service_suspended_template_id):
209+
op.execute("DELETE FROM notifications WHERE template_id = '{}'".format(template_id))
210+
op.execute("DELETE FROM notification_history WHERE template_id = '{}'".format(template_id))
211+
op.execute("DELETE FROM template_redacted WHERE template_id = '{}'".format(template_id))
212+
op.execute("DELETE FROM templates_history WHERE id = '{}'".format(template_id))
213+
op.execute("DELETE FROM templates WHERE id = '{}'".format(template_id))

0 commit comments

Comments
 (0)