Skip to content

Notification System

The Notification System handles the creation, queuing, and delivery of messages to members via Email and SMS. It is designed to be extensible and integrates directly with the Schedule Management workflow.

Overview

Notifications are generated based on system events (e.g., publishing a schedule) and are stored in the database before being sent. This asynchronous approach allows for reliability and the ability to retry failed messages.

  • Channels: Email (Markdown-based) and SMS (Text-based).
  • Triggers: Schedule Publication (via explicit service call).
  • Processing: Background tasks via django-tasks (and a retry management command).

Configuration

The system relies on Django settings for email/SMS and django-tasks configuration.

Reminder Intervals

Customize when reminders are sent by setting the NOTIFICATION_REMINDER_DAYS environment variable:

bash
# .env file (default: 3, 7, 14 days before duty date)
NOTIFICATION_REMINDER_DAYS=1,3,7,14

Examples:

  • Production: NOTIFICATION_REMINDER_DAYS=1,3,7,14 (full reminder schedule)
  • Development: NOTIFICATION_REMINDER_DAYS=1,3 (fewer reminders for testing)
  • Testing: NOTIFICATION_REMINDER_DAYS=1 (single reminder for fast tests)

Domain Configuration

Set your site's domain for generating links in notifications:

bash
# .env file
DEFAULT_DOMAIN=example.org

This setting is used as a fallback when the Django Sites framework is unavailable.

Processing

The system uses django-tasks to process notifications in the background. Ensure the db_worker is running in production.

Email

The system uses Anymail for email delivery.

Production Settings

Ensure ANYMAIL settings (e.g., SendGrid API key) are correctly configured in your production environment variables.

SMS

SMS delivery is handled by django-sendsms with a custom XynleSmsBackend.

SMS Credentials

The following environment variables are required for SMS sending:

  • XYNLE_API_USERNAME
  • XYNLE_API_SECRET
  • XYNLE_API_KEY
  • XYNLE_API_SENDER_ID (Sender ID)

Usage

Triggering Notifications

Notifications are automatically queued when a schedule is marked as Published.

  1. Go to the Schedule Detail view.
  2. Click the Publish button.
  3. The system will generate:
    • Email for members with notify_email=True.
    • SMS for members with notify_sms=True.
    • This triggers NotificationService.queue_schedule_notifications(), which creates:
      • Consolidated Assignment Summary (Email): One email per steward listing all duties.
      • Reminders (3, 7, 14 days before): Both Email and SMS (stored as pending, sent when due).
      • Note: Immediate SMS notifications for assignments are disabled.

Reminders

Reminders are automatically created for each assignment.

  • Intervals: 1, 3, 7, and 14 days before the duty.
  • Deduplication: Reminders are not sent if the duty is in the past or if the interval is invalid (e.g., trying to send a 14-day reminder for a duty tomorrow).

Processing the Queue

Notifications are processed asynchronously by django-tasks.

1. Database Worker (Production) In production, run the database worker to process tasks as they come in:

bash
python manage.py db_worker

2. Retry Mechanism If tasks fail or get stuck, use the management command to re-enqueue them:

bash
python manage.py process_notifications

Technical Details

Models

The Notification model (obed.notifications.models) stores the message content and status.

FieldDescription
idUUID Primary Key
statuspending, sent, failed
channelemail or sms
contentMarkdown source (email) or plain text (SMS)

Templates

Templates are located in obed/notifications/templates/notifications/.

  • Email:
    • schedule_assignment_summary.md: Consolidated list of duties (sent immediately).
    • assignment_notification.md: Individual reminder email.
  • SMS: assignment_sms.txt (Used for reminders).

Service Layer

The NotificationService handles the logic:

  • create_notification(): Creates DB record and enqueues send_notification_task.
  • queue_schedule_notifications(): Bulk creates notifications for a schedule.
  • process_queue(): Re-enqueues stuck/pending notifications (used by retry command).

Background Tasks

  • tasks.py: Defines send_notification_task(notification_id), which executes the sending logic via the service.

Testing

Run tests with pytest obed/notifications/tests/ to verify the notification flow.