from backend.models.models import MessageTemplateDoc from datetime import datetime 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, "tenant_id": tenant_id, "region": region, "is_active": True }) # 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 # Custom 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 {"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} # 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