Skip to content

Commit 08635be

Browse files
committed
✨(template) simplify message template type
1 parent d9d3853 commit 08635be

14 files changed

+126
-169
lines changed

src/backend/core/api/openapi.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2746,8 +2746,7 @@
27462746
"schema": {
27472747
"type": "string",
27482748
"enum": [
2749-
"new_message",
2750-
"reply",
2749+
"message",
27512750
"signature"
27522751
]
27532752
}
@@ -3521,8 +3520,7 @@
35213520
"schema": {
35223521
"type": "string",
35233522
"enum": [
3524-
"new_message",
3525-
"reply",
3523+
"message",
35263524
"signature"
35273525
]
35283526
}
@@ -6475,8 +6473,7 @@
64756473
"MessageTemplateTypeChoices": {
64766474
"type": "string",
64776475
"enum": [
6478-
"reply",
6479-
"new_message",
6476+
"message",
64806477
"signature"
64816478
]
64826479
},

src/backend/core/api/serializers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,9 @@ class MessageRecipientSerializer(serializers.ModelSerializer):
598598

599599
contact = ContactSerializer(read_only=True)
600600
delivery_status = IntegerChoicesField(
601-
choices_class=models.MessageDeliveryStatusChoices, read_only=True, allow_null=True
601+
choices_class=models.MessageDeliveryStatusChoices,
602+
read_only=True,
603+
allow_null=True,
602604
)
603605
retry_at = serializers.DateTimeField(read_only=True, allow_null=True)
604606
delivered_at = serializers.DateTimeField(read_only=True, allow_null=True)

src/backend/core/enums.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,8 @@ class MailboxAbilities(models.TextChoices):
117117
class MessageTemplateTypeChoices(models.IntegerChoices):
118118
"""Defines the possible types of message templates."""
119119

120-
REPLY = 1, "reply"
121-
NEW_MESSAGE = 2, "new_message"
122-
SIGNATURE = 3, "signature"
120+
MESSAGE = 1, "message"
121+
SIGNATURE = 2, "signature"
123122

124123

125124
EML_SUPPORTED_MIME_TYPES = ["message/rfc822", "application/eml"]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Generated by Django 5.1.13 on 2025-10-15 19:05
2+
3+
from django.db import migrations, models
4+
5+
6+
def migrate_messagetemplate_type(apps, schema_editor):
7+
"""Convert the type to the new values.
8+
Reply and new message are now message type (1)."""
9+
MessageTemplate = apps.get_model('core', 'MessageTemplate')
10+
# Set new message type to message type value (1)
11+
MessageTemplate.objects.filter(type=2).update(type=1)
12+
# Set signature type to new value for signature type (2)
13+
MessageTemplate.objects.filter(type=3).update(type=2)
14+
15+
16+
class Migration(migrations.Migration):
17+
18+
dependencies = [
19+
('core', '0010_thread_has_archived_alter_user_language'),
20+
]
21+
22+
operations = [
23+
migrations.RunPython(migrate_messagetemplate_type, reverse_code=migrations.RunPython.noop),
24+
migrations.AlterField(
25+
model_name='messagetemplate',
26+
name='type',
27+
field=models.SmallIntegerField(choices=[(1, 'message'), (2, 'signature')], default=1, help_text='Type of template (message, signature)', verbose_name='type'),
28+
),
29+
]

src/backend/core/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,8 +1683,8 @@ class MessageTemplate(BaseModel):
16831683
type = models.SmallIntegerField(
16841684
_("type"),
16851685
choices=MessageTemplateTypeChoices.choices,
1686-
default=MessageTemplateTypeChoices.REPLY,
1687-
help_text=_("Type of template (reply, new_message, signature)"),
1686+
default=MessageTemplateTypeChoices.MESSAGE,
1687+
help_text=_("Type of template (message, signature)"),
16881688
)
16891689

16901690
is_active = models.BooleanField(

src/backend/core/tests/api/test_admin_maildomains_message_template.py

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,11 @@ def test_list_templates(self, user, maildomain, admin_list_url):
8080
user=user,
8181
role=enums.MailDomainAccessRoleChoices.ADMIN,
8282
)
83-
reply_template = factories.MessageTemplateFactory(
84-
name="Reply Template",
85-
html_body="<p>Reply content</p>",
86-
text_body="Reply content",
87-
type=enums.MessageTemplateTypeChoices.REPLY,
88-
maildomain=maildomain,
89-
)
90-
new_message_template = factories.MessageTemplateFactory(
91-
name="New Message Template",
92-
html_body="<p>New message content</p>",
93-
text_body="New message content",
94-
type=enums.MessageTemplateTypeChoices.NEW_MESSAGE,
83+
message_template = factories.MessageTemplateFactory(
84+
name="Message Template",
85+
html_body="<p>Message content</p>",
86+
text_body="Message content",
87+
type=enums.MessageTemplateTypeChoices.MESSAGE,
9588
maildomain=maildomain,
9689
)
9790
signature_template = factories.MessageTemplateFactory(
@@ -108,11 +101,10 @@ def test_list_templates(self, user, maildomain, admin_list_url):
108101
# Test listing all templates
109102
response = client.get(admin_list_url)
110103
assert response.status_code == status.HTTP_200_OK
111-
assert len(response.data) == 3
104+
assert len(response.data) == 2
112105
templates_by_type = {t["type"]: t for t in response.data}
106+
assert templates_by_type["message"]["id"] == str(message_template.id)
113107
assert templates_by_type["signature"]["id"] == str(signature_template.id)
114-
assert templates_by_type["reply"]["id"] == str(reply_template.id)
115-
assert templates_by_type["new_message"]["id"] == str(new_message_template.id)
116108

117109
# Test filtering by single type
118110
response = client.get(admin_list_url, {"type": ["signature"]})
@@ -122,37 +114,22 @@ def test_list_templates(self, user, maildomain, admin_list_url):
122114
assert response.data[0]["id"] == str(signature_template.id)
123115

124116
# Test filtering by multiple types
125-
response = client.get(admin_list_url, {"type": ["signature", "reply"]})
117+
response = client.get(admin_list_url, {"type": ["signature", "message"]})
126118
assert response.status_code == status.HTTP_200_OK
127119
assert len(response.data) == 2
128120
templates_by_type = {t["type"]: t for t in response.data}
129121
assert "signature" in templates_by_type
130-
assert "reply" in templates_by_type
122+
assert "message" in templates_by_type
131123
assert templates_by_type["signature"]["id"] == str(signature_template.id)
132-
assert templates_by_type["reply"]["id"] == str(reply_template.id)
124+
assert templates_by_type["message"]["id"] == str(message_template.id)
133125

134126
# Test filtering by multiple types with some invalid types (should be ignored)
135-
response = client.get(
136-
admin_list_url, {"type": ["signature", "invalid_type", "new_message"]}
137-
)
127+
response = client.get(admin_list_url, {"type": ["signature", "invalid_type"]})
138128
assert response.status_code == status.HTTP_200_OK
139-
assert len(response.data) == 2
129+
assert len(response.data) == 1
140130
templates_by_type = {t["type"]: t for t in response.data}
141131
assert "signature" in templates_by_type
142-
assert "new_message" in templates_by_type
143-
assert templates_by_type["signature"]["id"] == str(signature_template.id)
144-
assert templates_by_type["new_message"]["id"] == str(new_message_template.id)
145-
146-
# Test filtering by all valid types
147-
response = client.get(
148-
admin_list_url, {"type": ["signature", "reply", "new_message"]}
149-
)
150-
assert response.status_code == status.HTTP_200_OK
151-
assert len(response.data) == 3
152-
templates_by_type = {t["type"]: t for t in response.data}
153132
assert templates_by_type["signature"]["id"] == str(signature_template.id)
154-
assert templates_by_type["reply"]["id"] == str(reply_template.id)
155-
assert templates_by_type["new_message"]["id"] == str(new_message_template.id)
156133

157134

158135
class TestAdminMailDomainMessageTemplateCreate:
@@ -164,7 +141,7 @@ def test_unauthorized(self, admin_list_url):
164141

165142
data = {
166143
"name": "Test Template",
167-
"type": "reply",
144+
"type": "message",
168145
"html_body": "<p>Hello {recipient_name}</p>",
169146
"text_body": "Hello {recipient_name}",
170147
"raw_body": RAW_DATA,
@@ -189,7 +166,7 @@ def test_forbidden(self, user, admin_list_url):
189166
"html_body": "<p>Hello {recipient_name}</p>",
190167
"text_body": "Hello {recipient_name}",
191168
"raw_body": RAW_DATA,
192-
"type": "reply",
169+
"type": "message",
193170
"is_active": True,
194171
"is_forced": False,
195172
}
@@ -519,7 +496,7 @@ def test_cannot_change_maildomain(self, user, maildomain, admin_detail_url):
519496
name="Original Template",
520497
html_body="<p>Original content</p>",
521498
text_body="Original content",
522-
type=enums.MessageTemplateTypeChoices.REPLY,
499+
type=enums.MessageTemplateTypeChoices.MESSAGE,
523500
maildomain=maildomain,
524501
raw_body=RAW_DATA_STRUCT,
525502
)
@@ -532,7 +509,7 @@ def test_cannot_change_maildomain(self, user, maildomain, admin_detail_url):
532509
"html_body": "<p>Updated content</p>",
533510
"text_body": "Updated content",
534511
"raw_body": RAW_DATA,
535-
"type": "reply",
512+
"type": "message",
536513
"is_active": False,
537514
"is_forced": False,
538515
"maildomain": str(other_maildomain.id),
@@ -604,11 +581,11 @@ def test_partial_update(self, user, maildomain, admin_detail_url):
604581
)
605582

606583
# Create a template with valid content
607-
reply_template = factories.MessageTemplateFactory(
584+
message_template = factories.MessageTemplateFactory(
608585
name="Original Template",
609586
html_body="<p>Original content</p>",
610587
text_body="Original content",
611-
type=enums.MessageTemplateTypeChoices.REPLY,
588+
type=enums.MessageTemplateTypeChoices.MESSAGE,
612589
maildomain=maildomain,
613590
raw_body=RAW_DATA_STRUCT,
614591
)
@@ -620,18 +597,18 @@ def test_partial_update(self, user, maildomain, admin_detail_url):
620597
"name": "Partially Updated Template",
621598
}
622599

623-
response = client.patch(admin_detail_url(reply_template.id), data)
600+
response = client.patch(admin_detail_url(message_template.id), data)
624601
assert response.status_code == status.HTTP_200_OK
625602
# only name should have been updated
626603
assert response.data["name"] == "Partially Updated Template"
627-
assert response.data["type"] == "reply"
604+
assert response.data["type"] == "message"
628605
assert response.data["html_body"] == "<p>Original content</p>"
629606
assert response.data["text_body"] == "Original content"
630607
assert response.data["is_active"]
631608

632609
# check that the template has been updated
633-
reply_template.refresh_from_db()
634-
assert reply_template.name == "Partially Updated Template"
610+
message_template.refresh_from_db()
611+
assert message_template.name == "Partially Updated Template"
635612

636613
def test_content_fields_atomic_validation(self, user, maildomain, admin_detail_url):
637614
"""Test that content fields must be updated together atomically."""

src/backend/core/tests/api/test_draft_message_signature.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,11 @@ def test_create_draft_with_non_signature_template(
242242
self, user, mailbox_sender, mailbox_access
243243
):
244244
"""Test creating a draft message with a non-signature template."""
245-
reply_template = factories.MessageTemplateFactory(
246-
name="Reply Template",
247-
html_body="<p>Reply content</p>",
248-
text_body="Reply content",
249-
type=enums.MessageTemplateTypeChoices.REPLY,
245+
message_template = factories.MessageTemplateFactory(
246+
name="Message Template",
247+
html_body="<p>Message content</p>",
248+
text_body="Message content",
249+
type=enums.MessageTemplateTypeChoices.MESSAGE,
250250
mailbox=mailbox_sender,
251251
is_active=True,
252252
)
@@ -260,7 +260,7 @@ def test_create_draft_with_non_signature_template(
260260
"senderId": str(mailbox_sender.id),
261261
"subject": "Test Message",
262262
"draftBody": "Test body",
263-
"signatureId": str(reply_template.id),
263+
"signatureId": str(message_template.id),
264264
},
265265
)
266266

0 commit comments

Comments
 (0)