Announcement
Announcement is a system-wide messaging feature that allows administrators to broadcast important information to targeted user groups. Announcements support priority levels, user targeting, and pinning capabilities to ensure critical messages reach the right users.
Core Concept
An Announcement represents a broadcast message with:
- Title and Content: Message headline and body text
- Priority Level: Visual importance indicator (Journal, Info, Warning, Urgent)
- User Targeting: Specify which user groups should see the announcement
- Pinning: Pin important announcements to the top of the list
- Persistence: All announcements are stored permanently for historical reference
Data Model
pub struct Announcement {
pub id: i64,
pub title: String,
pub content: String,
pub user_group: Vec<i32>, // Target user groups
pub user_extra_groups: Vec<i32>, // Target extra user groups
pub is_pinned: bool, // Whether pinned to top
pub priority: AnnouncementPriority, // Visual importance
pub created_at: PrimitiveDateTime,
pub updated_at: PrimitiveDateTime,
}
Priority Levels
Announcements have four priority levels that indicate message importance:
- Journal: Routine informational messages (default priority)
- Info: General information that users should be aware of
- Warning: Important messages requiring user attention
- Urgent: Critical messages that need immediate attention
Priority levels are purely visual indicators—they don’t affect targeting or delivery. Frontend implementations should style these differently to draw appropriate attention.
User Targeting
Announcements use a flexible targeting system based on user groups:
Targeting Logic
An announcement is visible to a user if either condition is true:
- User’s primary
user_groupmatches any group in announcement’suser_grouparray - User’s
user_extra_groupshas any overlap with announcement’suser_extra_groupsarray
This OR-based logic allows administrators to target announcements broadly or narrowly:
- Broadcast to all: Include all possible user groups
- Target specific roles: Specify only relevant user groups
- Mixed targeting: Combine primary and extra groups for fine-grained control
Empty Targeting
If both user_group and user_extra_groups are empty arrays, the announcement won’t be visible to any users. This can be useful for drafting announcements before activating them.
Announcement Lifecycle
1. Creation
Administrators create announcements through AdminCreateAnnouncement:
Process:
- Admin specifies title, content, targeting, priority, and pin status
- Announcement is inserted into database
AnnouncementCreatedEventis published to RabbitMQ- Event hook can trigger side effects (cache invalidation, push notifications)
Permissions: SuperAdmin, Moderator
Event System: Creation triggers an internal event for extensibility. Currently, the event hook is a placeholder for future features like real-time push notifications or cache updates.
2. Display
Users retrieve announcements through NotificationService::ListAnnouncements:
Behavior:
- Returns announcements targeted to the requesting user
- Sorted by pinned status first (pinned on top), then by creation date (newest first)
- Limited to 20 announcements per request
- No pagination—shows the 20 most relevant announcements
Targeting Query: Uses PostgreSQL array operators (= ANY() for primary group, && for array overlap) with GIN indexes for performance.
Single Announcement: Users can also fetch a specific announcement by ID via GetAnnouncement, useful for detail pages or deep links.
3. Updates
Administrators can edit existing announcements through AdminEditAnnouncement:
Editable Fields: All fields (title, content, targeting, priority, pinning) can be modified
Effect: Changes are immediate—users will see updated content on next fetch
No History: The system doesn’t track edit history. If audit trail is needed, it’s handled through the admin operation logging system.
4. Deletion
Administrators can permanently remove announcements through AdminDeleteAnnouncement:
Permissions: SuperAdmin, Moderator
Effect: Hard delete from database—no soft delete or archiving
Use Cases:
- Removing outdated announcements
- Cleaning up test announcements
- Deleting announcements posted in error
User Operations
List Announcements
Service: NotificationService::ListAnnouncements
Retrieves all announcements targeted to the current user, ordered by relevance (pinned first, then newest).
Response: Returns up to 20 announcements. No pagination—users see the most important/recent messages.
Targeting: Automatically filtered based on user’s group membership—no need to specify groups in request.
Get Single Announcement
Service: NotificationService::GetAnnouncement
Fetches a specific announcement by ID.
Use Case: Detail pages, direct links, or refreshing a single announcement without fetching the entire list.
Access Control: No additional access control beyond targeting—if an announcement exists and targets the user, they can retrieve it by ID.
Admin Operations
All admin operations require SuperAdmin or Moderator roles and are exposed through NotificationManageService.
Create Announcement
Operation: AdminCreateAnnouncement
Broadcasts a new message to users.
Parameters:
title: Message headlinecontent: Full message body (supports long text, formatting handled by frontend)user_group: Array of primary user group IDs to targetuser_extra_groups: Array of extra user group IDs to targetis_pinned: Whether to pin to top of listpriority: Visual importance indicator
Returns: New announcement ID
Event: Triggers AnnouncementCreatedEvent for extensibility (future push notifications, cache invalidation)
List Announcements
Operation: AdminListAnnouncements
Retrieves all announcements (not filtered by user targeting) for management purposes.
Pagination: Uses limit and offset for pagination
Sorting: Returns announcements in creation order (newest first)
Use Case: Admin dashboard showing all system announcements regardless of targeting
Edit Announcement
Operation: AdminEditAnnouncement
Updates an existing announcement.
Parameters: All fields can be modified (same as creation)
Returns: Updated announcement object
Effect: Changes are immediate—users see updated content on next fetch
Delete Announcement
Operation: AdminDeleteAnnouncement
Permanently removes an announcement from the database.
Parameters: Announcement ID
Returns: Empty response on success
Warning: Hard delete with no recovery mechanism. Ensure announcement should be permanently removed.
Pinning Behavior
Pinned announcements always appear at the top of the list, regardless of creation date:
Sorting Order:
- Pinned announcements (ordered by creation date, newest first)
- Unpinned announcements (ordered by creation date, newest first)
Use Cases:
- Pin urgent system maintenance notices
- Keep important policy changes visible
- Highlight time-sensitive information
Frontend Consideration: Pinned announcements should be visually distinct (e.g., pin icon, different background) to indicate their importance.
Database Schema
Key schema details (from 20250814171450_create_entities_for_notification_module.sql):
Table: notification.announcement
id BIGSERIAL PRIMARY KEY
title TEXT NOT NULL
content TEXT NOT NULL
user_group INTEGER[] NOT NULL
user_extra_groups INTEGER[] NOT NULL
is_pinned BOOLEAN NOT NULL DEFAULT FALSE
priority announcement_priority NOT NULL DEFAULT 'journal'
created_at TIMESTAMP NOT NULL DEFAULT NOW()
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
Indexes:
- GIN index on
user_group: Fast targeting queries - GIN index on
user_extra_groups: Fast targeting queries - B-tree index on
is_pinned: Efficient pinned-first sorting - B-tree index on
priority: Potential future priority-based queries
No Foreign Key: User groups are stored as integer arrays with no foreign key constraint, providing flexibility for group management.
Event System
The announcement system uses internal events for lifecycle hooks:
Event: AnnouncementCreatedEvent
- Published by:
ManageService::AdminCreateAnnouncement - Consumed by: Internal
AnnouncementEventHook(extensibility placeholder) - Route:
notification.announcement_createdonnotificationexchange - Payload:
announcement_id,created_attimestamp
Current Implementation: The event hook is a placeholder. Future implementations might:
- Invalidate frontend caches
- Send push notifications to targeted users
- Trigger webhooks for external integrations
- Log analytics events
Frontend Integration Points
User Announcement Display
List View:
- Call
ListAnnouncementson page load - Display announcements with priority-based styling:
- Urgent: Red/high-contrast styling
- Warning: Yellow/amber styling
- Info: Blue/neutral styling
- Journal: Default/subtle styling
- Show pinned announcements with visual indicator (pin icon)
- Limit display to 20 announcements (no pagination needed)
Detail View:
- Provide “Read More” links using announcement ID
- Call
GetAnnouncementto fetch full content - Display full message with timestamp and priority indicator
Real-time Updates: Consider polling ListAnnouncements periodically (e.g., every 5 minutes) or implementing WebSocket for real-time announcement delivery.
Admin Management UI
Create Form:
- Title input (required)
- Content textarea (supports long text)
- User group multi-select (checkboxes or dropdown)
- Extra user groups multi-select
- Priority dropdown (Journal, Info, Warning, Urgent)
- Pin checkbox
List View:
- Table showing all announcements
- Columns: ID, Title, Priority, Pinned, Target Groups, Created, Updated
- Edit and delete actions
- Pagination controls (limit/offset)
Edit Form:
- Pre-populate with existing values
- Allow modification of all fields
- Show last updated timestamp
Design Decisions
Why No Read Tracking?
Announcements don’t track which users have read them:
- Simplicity: Avoids per-user state management
- Broadcast Nature: Announcements are informational, not actionable
- Scalability: No need to store read state for thousands of users
- Use Case: For messages requiring acknowledgment, use notification systems with explicit confirmation flows
Why Hard Delete Instead of Soft Delete?
Announcements are permanently deleted rather than archived:
- Clean Data: Old announcements clutter management UI
- No Recovery Need: If an announcement needs to persist, don’t delete it
- Admin Control: Admins have full control over lifecycle
- Audit Trail: Admin operation logging provides deletion records if needed
Why Limit to 20 Announcements?
User-facing list is capped at 20 without pagination:
- Relevance: Users don’t need to see dozens of old announcements
- Performance: Keeps queries fast with simple sorting
- UX: Encourages admins to keep announcements current
- Workaround: For historical access, provide search/filter in admin panel
Why OR-Based Targeting?
Users see announcements if they match either primary group or extra groups:
- Flexibility: Allows broad or narrow targeting
- Ease of Use: Simpler than complex boolean logic
- Common Use Case: “Show to all premium users OR all beta testers”
- Empty Arrays: Provide draft mode (not visible to anyone)
See Also:
- Notification Module Introduction - Module overview and architecture
- Auth Module - User group management (user_group and user_extra_groups)