freeleaps-service-hub/apps/notification/backend/application/tenant_notification_hub.py

156 lines
6.2 KiB
Python

from typing import Dict, List, Optional
from datetime import datetime
from common.log.module_logger import ModuleLogger
from common.exception.exceptions import InvalidDataError
from backend.business.tenant_notification_manager import TenantNotificationManager
from backend.application.template_message_hub import TemplateMessageHub
from backend.application.email_sender_hub import EmailSenderHub
from backend.models.constants import NotificationConstants
class TenantNotificationHub:
def __init__(self):
self.tenant_notification_manager = TenantNotificationManager()
self.template_message_hub = TemplateMessageHub()
self.email_sender_hub = EmailSenderHub()
self.module_logger = ModuleLogger(sender_id="TenantNotificationHub")
self.notification_constants = NotificationConstants()
async def send_tenant_email(
self,
tenant_id: str,
template_id: str,
recipient_emails: List[str],
region: int,
subject_properties: Dict = {},
body_properties: Dict = {},
sender_emails: Optional[List[str]] = None,
priority: str = "normal",
tracking_enabled: bool = True
):
"""Send email using tenant's template and email senders"""
try:
# 1. check if tenant has access to template
await self.template_message_hub.verify_tenant_access(template_id, tenant_id, region)
# 2. render template
rendered_template = await self.template_message_hub.render_template(
tenant_id=tenant_id,
template_id=template_id,
properties={**subject_properties, **body_properties},
region=region
)
# 3. get tenant email senders
default_sender_email = self.notification_constants.DEFAULT_EMAIL_SENDER
if sender_emails is None:
tenant_email_senders = await self.email_sender_hub.get_email_senders(tenant_id)
if not tenant_email_senders:
sender_emails = [default_sender_email]
await self.module_logger.log_info(
"Using default email sender for tenant",
properties={
"tenant_id": tenant_id,
"default_sender": default_sender_email
}
)
else:
sender_emails = tenant_email_senders
# 4. check if sender_emails are valid
if sender_emails != [default_sender_email]:
tenant_senders = await self.email_sender_hub.get_email_senders(tenant_id)
invalid_senders = [email for email in sender_emails if email not in tenant_senders]
if invalid_senders:
raise InvalidDataError(f"Invalid email senders for tenant: {invalid_senders}")
# 5. call TenantNotificationManager to send email
result = await self.tenant_notification_manager.send_tenant_email(
tenant_id=tenant_id,
template_id=template_id,
rendered_template=rendered_template,
recipient_emails=recipient_emails,
sender_emails=sender_emails,
region=region,
priority=priority,
tracking_enabled=tracking_enabled
)
await self.module_logger.log_info(
"Tenant email sent successfully",
properties={
"tenant_id": tenant_id,
"template_id": template_id,
"recipient_count": len(recipient_emails),
"sender_count": len(sender_emails),
"message_id": result.get("message_id")
}
)
return result
except Exception as e:
await self.module_logger.log_error(
"Failed to send tenant email",
properties={
"tenant_id": tenant_id,
"template_id": template_id,
"error": str(e)
}
)
raise
async def get_tenant_email_status(self, tenant_id: str, email_id: str = None, recipient_email: str = None):
"""Get tenant email status"""
try:
status = await self.tenant_notification_manager.get_tenant_email_status(tenant_id, email_id, recipient_email)
await self.module_logger.log_info(
"Tenant email status retrieved",
properties={
"tenant_id": tenant_id,
"email_id": email_id,
"status": status.get("status") if status else None
}
)
return status
except Exception as e:
await self.module_logger.log_error(
"Failed to get tenant email status",
properties={
"tenant_id": tenant_id,
"email_id": email_id,
"error": str(e)
}
)
raise
async def get_tenant_email_status_list(self, tenant_id: str, limit: int = 50, offset: int = 0):
"""Get list of email statuses for a tenant"""
try:
status_list = await self.tenant_notification_manager.get_tenant_email_status_list(tenant_id, limit, offset)
await self.module_logger.log_info(
"Tenant email status list retrieved",
properties={
"tenant_id": tenant_id,
"count": len(status_list.get("emails", [])),
"total_count": status_list.get("pagination", {}).get("total_count", 0)
}
)
return status_list
except Exception as e:
await self.module_logger.log_error(
"Failed to get tenant email status list",
properties={
"tenant_id": tenant_id,
"error": str(e)
}
)
raise