# shared/clients/notification_client.py """ Notification Service Client for Inter-Service Communication Provides access to notification and email sending from other services """ import structlog from typing import Dict, Any, Optional from uuid import UUID from shared.clients.base_service_client import BaseServiceClient from shared.config.base import BaseServiceSettings logger = structlog.get_logger() class NotificationServiceClient(BaseServiceClient): """Client for communicating with the Notification Service""" def __init__(self, config: BaseServiceSettings): super().__init__("notification", config) def get_service_base_path(self) -> str: return "/api/v1/notifications" # ================================================================ # NOTIFICATION ENDPOINTS # ================================================================ async def send_notification( self, tenant_id: str, notification_type: str, message: str, recipient_email: Optional[str] = None, subject: Optional[str] = None, html_content: Optional[str] = None, priority: str = "normal", metadata: Optional[Dict[str, Any]] = None ) -> Optional[Dict[str, Any]]: """ Send a notification Args: tenant_id: Tenant ID (UUID as string) notification_type: Type of notification (email, sms, push, in_app) message: Notification message recipient_email: Recipient email address (for email notifications) subject: Email subject (for email notifications) html_content: HTML content for email (optional) priority: Priority level (low, normal, high, urgent) metadata: Additional metadata Returns: Dictionary with notification details """ try: notification_data = { "type": notification_type, "message": message, "priority": priority, "recipient_email": recipient_email, "subject": subject, "html_content": html_content, "metadata": metadata or {} } result = await self.post("send", data=notification_data, tenant_id=tenant_id) if result: logger.info("Notification sent successfully", tenant_id=tenant_id, notification_type=notification_type) return result except Exception as e: logger.error("Error sending notification", error=str(e), tenant_id=tenant_id, notification_type=notification_type) return None async def send_email( self, tenant_id: str, to_email: str, subject: str, message: str, html_content: Optional[str] = None, priority: str = "normal" ) -> Optional[Dict[str, Any]]: """ Send an email notification (convenience method) Args: tenant_id: Tenant ID (UUID as string) to_email: Recipient email address subject: Email subject message: Email message (plain text) html_content: HTML version of email (optional) priority: Priority level (low, normal, high, urgent) Returns: Dictionary with notification details """ return await self.send_notification( tenant_id=tenant_id, notification_type="email", message=message, recipient_email=to_email, subject=subject, html_content=html_content, priority=priority ) # ================================================================ # UTILITY METHODS # ================================================================ async def health_check(self) -> bool: """Check if notification service is healthy""" try: result = await self.get("../health") # Health endpoint is not tenant-scoped return result is not None except Exception as e: logger.error("Notification service health check failed", error=str(e)) return False # Factory function for dependency injection def create_notification_client(config: BaseServiceSettings) -> NotificationServiceClient: """Create notification service client instance""" return NotificationServiceClient(config)