From 2d3adb093607a1813fa05ae9792561d1364b6ec4 Mon Sep 17 00:00:00 2001 From: YuehuCao Date: Fri, 25 Jul 2025 19:16:40 +0800 Subject: [PATCH] fix: re-submit due to missing some contents --- .../backend/services/email_sender_service.py | 68 ++++++++++++++ .../services/template_message_service.py | 90 ++++++++++++++++++- 2 files changed, 155 insertions(+), 3 deletions(-) diff --git a/apps/notification/backend/services/email_sender_service.py b/apps/notification/backend/services/email_sender_service.py index e69de29..a91b680 100644 --- a/apps/notification/backend/services/email_sender_service.py +++ b/apps/notification/backend/services/email_sender_service.py @@ -0,0 +1,68 @@ +from backend.models.models import EmailSenderDoc + +class EmailSenderService: + # get the email sender list for the tenant + async def get_email_sender(self, tenant_id: str): + doc = await EmailSenderDoc.find_one({"tenant_id": tenant_id, "is_active": True}) + return doc.email_senders if doc else [] + + # set the email sender list for the tenant + async def set_email_sender(self, tenant_id: str, email_senders: list): + doc = await EmailSenderDoc.find_one({"tenant_id": tenant_id}) + if doc: + await doc.set({"email_senders": email_senders}) + return {"success": True, "email_senders": doc.email_senders} + else: + doc = EmailSenderDoc(tenant_id=tenant_id, email_senders=email_senders) + await doc.create() + return {"success": True, "email_senders": doc.email_senders} + + # add new email senders to the tenant + async def add_email_senders(self, tenant_id: str, new_senders: list): + if not new_senders or not isinstance(new_senders, list): + return {"success": False, "msg": "No sender provided"} + + doc = await EmailSenderDoc.find_one({"tenant_id": tenant_id, "is_active": True}) + if doc: + original_set = set(doc.email_senders) + new_set = set(new_senders) + to_add = new_set - original_set + if not to_add: + return {"success": False, "msg": "All senders already exist"} + updated_list = list(original_set | new_set) + await doc.set({"email_senders": updated_list}) + return {"success": True, "email_senders": updated_list} + else: + if not new_senders: + return {"success": False, "msg": "No sender provided"} + doc = await self.set_email_sender(tenant_id, new_senders) + return {"success": True, "email_senders": doc.email_senders} + + # remove the email sender from the list + async def remove_email_senders(self, tenant_id: str, emails_to_remove: list): + doc = await EmailSenderDoc.find_one({"tenant_id": tenant_id, "is_active": True}) + if not doc or not doc.email_senders: + return {"success": False, "msg": "No sender found"} + + original_count = len(doc.email_senders) + doc.email_senders = [s for s in doc.email_senders if s not in emails_to_remove] + if len(doc.email_senders) == original_count: + return {"success": False, "msg": "No sender matched for removal"} + await doc.set({"email_senders": doc.email_senders}) + return {"success": True, "remaining": doc.email_senders} + + # clear the email sender list for the tenant + async def clear_email_senders(self, tenant_id: str): + doc = await EmailSenderDoc.find_one({"tenant_id": tenant_id, "is_active": True}) + if doc: + await doc.set({"email_senders": []}) + return {"success": True} + return {"success": False, "msg": "No sender config found"} + + # delete the email sender list for the tenant + async def delete_email_sender(self, tenant_id: str): + doc = await EmailSenderDoc.find_one({"tenant_id": tenant_id}) + if doc: + await doc.delete() + return {"success": True} + return {"success": False, "msg": "No sender config found"} \ No newline at end of file diff --git a/apps/notification/backend/services/template_message_service.py b/apps/notification/backend/services/template_message_service.py index 6c7ca21..11cf2b1 100644 --- a/apps/notification/backend/services/template_message_service.py +++ b/apps/notification/backend/services/template_message_service.py @@ -1,6 +1,30 @@ from backend.models.models import MessageTemplateDoc class TemplateMessageService: + ## operations for global templates, conducted by platform admin + # Create global template operated by platform admin + async def create_global_template(self, template: MessageTemplateDoc): + template.tenant_id = None + return await template.create() + + # Update global template operated by platform admin + async def update_global_template(self, id: str, data: dict): + template = await MessageTemplateDoc.get(id) + if not template or template.tenant_id is not None: + raise PermissionError("Not a global template") + await template.set(data) + return {"success": True} + + # Delete global template operated by platform admin + async def delete_global_template(self, id: str): + template = await MessageTemplateDoc.get(id) + if not template or template.tenant_id is not None: + raise PermissionError("Not a global template") + await template.delete() + return {"success": True} + + + # Just for Facilitating later addition of permissions, logging, and exception handling, etc. async def get_template(self, template_id, tenant_id, region): return await MessageTemplateDoc.find_one({ "template_id": template_id, @@ -9,19 +33,79 @@ class TemplateMessageService: "is_active": True }) - async def create_template(self, template:MessageTemplateDoc): + # Query global template + async def list_global_templates(self, region): + return await MessageTemplateDoc.find({"tenant_id": None, "region": region}).to_list() + + # Look up templates belonging to the tenant + async def list_tenant_templates(self, tenant_id, region): + return await MessageTemplateDoc.find({"tenant_id": tenant_id, "region": region}).to_list() + + # Tenant selects template(s) (copies one or more global templates as their own) + async def assign_template_to_tenant(self, template_ids: list, region, tenant_id: str): + results = [] + # assign a global template to a tenant + for template_id in template_ids: + # lookup global template + global_template = await MessageTemplateDoc.find_one({ + "template_id": template_id, + "tenant_id": None, + "region": region + }) + if not global_template: + results.append({"template_id": template_id, "success": False, "msg": "Template not found"}) + continue + + # check if the tenant already has the template + existing = await MessageTemplateDoc.find_one({ + "template_id": template_id, + "tenant_id": tenant_id, + "region": region + }) + if existing: + results.append({"template_id": template_id, "success": False, "msg": "Template already assigned"}) + continue + + # copy the template + new_template = MessageTemplateDoc( + template_id=global_template.template_id, + tenant_id=tenant_id, + region=global_template.region, + subject=global_template.subject, + body=global_template.body, + created_at=datetime.utcnow() + ) + await new_template.create() + results.append({"template_id": template_id, "success": True, "template_db_id": str(new_template.id)}) + return results + + # Custome templates by tenant + async def create_template(self, template:MessageTemplateDoc, tenant_id: str): + template.tenant_id = tenant_id return await template.create() + # Update template under certain tenant async def update_template(self, id: str, tenant_id: str, data: dict): template = await MessageTemplateDoc.get(id) if not template or template.tenant_id != tenant_id: raise PermissionError("Forbidden") await template.set(data) - return template + return {"success": True} + # Delete template under certain tenant async def delete_template(self, id: str, tenant_id: str): template = await MessageTemplateDoc.get(id) if not template or template.tenant_id != tenant_id: raise PermissionError("Forbidden") await template.delete() - return {"success": True} \ No newline at end of file + return {"success": True} + + # Render template + async def render_template(self, template: MessageTemplateDoc, properties: dict): + # Use properties to replace the placeholders in the template, and return the rendered body + try: + subject = template.subject.format(**properties) + body = template.body.format(**properties) + except KeyError as e: + raise ValueError(f"Missing template parameter: {e}") + return subject, body \ No newline at end of file