"""HTML email builders for scheduled admin notifications. Each builder is registered in ``BUILDERS`` keyed by ``NotificationSchedule.notification_type`` and returns ``(subject, html_body)``. Add new types by appending to the registry and extending ``NotificationSchedule.TYPE_CHOICES``. Week bounds for ``events_expiring_this_week`` are computed in Asia/Kolkata so the "this week" semantics match the operations team's wall-clock week regardless of ``settings.TIME_ZONE`` (currently UTC). """ from datetime import date, datetime, timedelta from html import escape try: from zoneinfo import ZoneInfo except ImportError: # pragma: no cover — fallback for py<3.9 from backports.zoneinfo import ZoneInfo # type: ignore from django.conf import settings from django.core.mail import EmailMessage from django.db.models import Q from eventify_logger.services import log IST = ZoneInfo('Asia/Kolkata') def _today_in_ist() -> date: return datetime.now(IST).date() def _upcoming_week_bounds(today: date) -> tuple[date, date]: """Return (next Monday, next Sunday) inclusive. If today is Monday the result is *this week* (today..Sunday). If today is any other weekday the result is *next week* (next Monday..next Sunday). Mon=0 per Python ``weekday()``. """ days_until_monday = (7 - today.weekday()) % 7 monday = today + timedelta(days=days_until_monday) sunday = monday + timedelta(days=6) return monday, sunday def _build_events_expiring_this_week(schedule) -> tuple[str, str]: from events.models import Event today = _today_in_ist() monday, sunday = _upcoming_week_bounds(today) qs = ( Event.objects .select_related('partner', 'event_type') .filter(event_status='published') .filter( Q(end_date__isnull=False, end_date__gte=monday, end_date__lte=sunday) | Q(end_date__isnull=True, start_date__gte=monday, start_date__lte=sunday) ) .order_by('end_date', 'start_date', 'name') ) events = list(qs) rows_html = '' for e in events: end = e.end_date or e.start_date title = e.title or e.name or '(untitled)' partner_name = '' if e.partner_id: try: partner_name = e.partner.name or '' except Exception: partner_name = '' category = '' if e.event_type_id and e.event_type: category = getattr(e.event_type, 'event_type', '') or '' rows_html += ( '