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:
# .env file (default: 3, 7, 14 days before duty date)
NOTIFICATION_REMINDER_DAYS=1,3,7,14Examples:
- 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:
# .env file
DEFAULT_DOMAIN=example.orgThis 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_USERNAMEXYNLE_API_SECRETXYNLE_API_KEYXYNLE_API_SENDER_ID(Sender ID)
Usage
Triggering Notifications
Notifications are automatically queued when a schedule is marked as Published.
- Go to the Schedule Detail view.
- Click the Publish button.
- 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.
- Email for members with
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:
python manage.py db_worker2. Retry Mechanism If tasks fail or get stuck, use the management command to re-enqueue them:
python manage.py process_notificationsTechnical Details
Models
The Notification model (obed.notifications.models) stores the message content and status.
| Field | Description |
|---|---|
id | UUID Primary Key |
status | pending, sent, failed |
channel | email or sms |
content | Markdown 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 enqueuessend_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: Definessend_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.