"""Notification engine. Resolves templates for a domain event from the database, renders them and dispatches through the configured provider. Business logic only emits events. """ from django.utils import timezone from apps.notifications.models import NotificationLog, NotificationTemplate from apps.notifications.providers import get_sms_provider, render_template class NotificationService: def send_event(self, event: str, context: dict, recipient: str = "") -> list: results = [] templates = NotificationTemplate.objects.filter(event=event, enabled=True) for template in templates: body = render_template(template.body, context) if template.channel == NotificationTemplate.Channel.SMS: results.append(self._send_sms(template, recipient, body)) return results def _send_sms(self, template, recipient: str, body: str) -> dict: status = "sent" error = "" reference = "" try: reference = get_sms_provider().send(recipient, body) except Exception as exc: # pragma: no cover - provider failures status = "failed" error = str(exc) NotificationLog.objects.create( template=template, recipient=recipient, channel="sms", status=status, error=error, sent_at=timezone.now() if status == "sent" else None, ) return {"channel": "sms", "status": status, "reference": reference}