Notification Scenario
Data Entity
Description
Configuration records defining the business rules and triggers that cause notifications to be automatically dispatched to users. Each scenario maps a platform event (e.g. assignment dispatch, certification expiry, inactivity) to a notification type, audience, and delivery channels.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key | PKrequiredunique |
organization_id |
uuid |
Organization this scenario belongs to. Scenarios are tenant-scoped; global defaults may be represented as null or a sentinel org. | required |
scenario_key |
string |
Machine-readable identifier for the scenario, e.g. 'assignment_dispatched', 'certification_expiry_warning', 'inactivity_reminder', 'pause_activated'. Used by the NotificationScenarioEngine to look up the correct scenario at runtime. | required |
name |
string |
Human-readable display name for the scenario, shown in admin configuration UIs. | required |
description |
text |
Explanation of when and why this scenario fires, for administrators managing notification configuration. | - |
trigger_event |
string |
The platform event that activates this scenario, e.g. 'activity.created', 'assignment.dispatched', 'certificate.expiring_soon', 'peer_mentor.paused', 'assignment.unread_10_days'. | required |
trigger_conditions |
json |
Optional structured conditions that must hold for the trigger to fire (e.g. {"days_since_dispatch": 10, "read": false}). Null means unconditional on the trigger event. | - |
audience |
enum |
Who receives the notification generated by this scenario. | required |
channels |
json |
Array of delivery channels this scenario uses, e.g. ["push", "email"], ["sms"], ["push"]. Must contain at least one channel. | required |
title_template |
string |
Notification title template with variable placeholders, e.g. 'New assignment from {{coordinator_name}}'. | required |
body_template |
text |
Notification body template with variable placeholders. Used for push body, email body, and SMS message. | required |
is_enabled |
boolean |
Whether this scenario is currently active and will fire when its trigger is detected. | required |
is_user_configurable |
boolean |
Whether end users can opt out of this scenario via Notification Settings. Some scenarios (e.g. security alerts) are mandatory and cannot be disabled by the user. | required |
delay_minutes |
integer |
Optional delay in minutes between trigger event and notification dispatch. 0 means immediate. Used for batching or giving users time to act before being notified. | - |
repeat_interval_hours |
integer |
If non-null and the trigger condition persists, the scenario fires again after this many hours. Used for reminder-type scenarios like unread assignment reminders. | - |
max_repeats |
integer |
Maximum number of times this scenario can repeat for a single trigger instance. Prevents infinite reminders. | - |
priority |
enum |
Delivery priority hint passed to push/SMS providers. | required |
deep_link_template |
string |
Optional deep-link URL template for push notifications, e.g. 'meander://assignments/{{assignment_id}}'. Rendered at dispatch time. | - |
metadata |
json |
Arbitrary key-value bag for scenario-specific configuration not covered by standard fields. | - |
created_at |
datetime |
Record creation timestamp (UTC). | required |
updated_at |
datetime |
Last modification timestamp (UTC). | required |
Database Indexes
idx_notification_scenarios_org_id
Columns: organization_id
idx_notification_scenarios_org_key
Columns: organization_id, scenario_key
idx_notification_scenarios_trigger_event
Columns: trigger_event
idx_notification_scenarios_enabled
Columns: is_enabled
Validation Rules
channels_valid_values
error
Validation failed
title_template_not_empty
error
Validation failed
body_template_not_empty
error
Validation failed
trigger_conditions_valid_json
error
Validation failed
delay_minutes_non_negative
error
Validation failed
scenario_key_format
error
Validation failed
deep_link_template_format
error
Validation failed
Business Rules
unique_scenario_key_per_org
Each (organization_id, scenario_key) pair must be unique. Two scenarios for the same org cannot share the same key, preventing duplicate trigger handling.
mandatory_scenarios_cannot_be_disabled
Scenarios marked is_user_configurable=false (e.g. security alerts, assignment dispatch) cannot be toggled off by the user via NotificationPreferences. The NotificationPreferencesService must reject preference updates that attempt to disable mandatory scenarios.
scenario_respects_user_preferences
Before dispatching, the NotificationScenarioEngine checks notification_preferences for the target user. If the user has opted out of a user-configurable scenario, the notification is suppressed.
channel_availability_check
A scenario's channels list may only include channels that are available for the organization's plan and the user's registered devices. Push requires a registered FCM/APNs token; SMS requires a phone number; email requires a verified email address.
repeat_requires_interval
If max_repeats > 1 then repeat_interval_hours must be set. A scenario cannot repeat without a defined interval.
disabled_module_suppresses_scenarios
If the area that owns the triggering event is toggled off for the organization (via module_toggles), scenarios belonging to that area must not fire even if is_enabled=true.
assignment_unread_reminder_auto_scenario
Blindeforbundet requires an automatic reminder after 10 days if an assignment has not been read. This must exist as a seeded scenario (scenario_key='assignment_unread_reminder', repeat_interval_hours=null after first fire, trigger_conditions={days_since_dispatch:10, read:false}) and cannot be deleted.