234 lines
6.8 KiB
Markdown
234 lines
6.8 KiB
Markdown
# User-Specific Notifications Implementation
|
|
|
|
## Overview
|
|
|
|
The notifications system has been enhanced to support three types of notifications:
|
|
|
|
1. **Personal Notifications** - Targeted to a specific user
|
|
2. **General Notifications** - System-wide announcements visible to all users
|
|
3. **Role-Based Notifications** - Visible to all users with specific roles
|
|
|
|
## Changes Made
|
|
|
|
### 1. Model Updates (`notifications/models.py`)
|
|
|
|
#### New Fields Added to `Notification` Model:
|
|
- `user` - Made nullable (`null=True, blank=True`) to support general/role-based notifications
|
|
- `is_general` - Boolean field to mark system-wide announcements
|
|
- `target_roles` - JSONField containing list of role codes for role-based notifications
|
|
|
|
#### New Class Methods:
|
|
```python
|
|
# Get all notifications for a user (personal, general, and role-based)
|
|
Notification.get_for_user(user)
|
|
|
|
# Create a personal notification
|
|
Notification.create_personal(user, title, message, notification_type='INFO', ...)
|
|
|
|
# Create a general notification (visible to all users)
|
|
Notification.create_general(title, message, notification_type='INFO', ...)
|
|
|
|
# Create a role-based notification
|
|
Notification.create_role_based(roles, title, message, notification_type='INFO', ...)
|
|
```
|
|
|
|
### 2. Database Migration
|
|
|
|
Migration file: `notifications/migrations/0003_add_general_and_role_based_notifications.py`
|
|
|
|
Changes:
|
|
- Added `is_general` field (default=False)
|
|
- Added `target_roles` field (default=[])
|
|
- Modified `user` field to be nullable
|
|
|
|
### 3. Views Updates (`notifications/views.py`)
|
|
|
|
#### Updated Views:
|
|
- `NotificationListView` - Now uses `Notification.get_for_user()` to fetch all relevant notifications
|
|
- `NotificationDropdownView` - Updated to use `get_for_user()` method
|
|
- `get_unread_count()` and `mark_all_as_read()` - Updated to work with the new filtering
|
|
|
|
#### New View:
|
|
- `BroadcastNotificationCreateView` - Admin-only view to create general or role-based notifications
|
|
|
|
### 4. Forms (`notifications/forms.py`)
|
|
|
|
#### New Form:
|
|
`BroadcastNotificationForm` - Form for creating broadcast notifications with:
|
|
- Broadcast type selection (General or Role-Based)
|
|
- Target roles selection (for role-based notifications)
|
|
- Title, message, notification type, and action URL fields
|
|
- Validation to ensure roles are selected for role-based notifications
|
|
|
|
### 5. URLs (`notifications/urls.py`)
|
|
|
|
New route added:
|
|
```python
|
|
path('inbox/broadcast/create/', views.BroadcastNotificationCreateView.as_view(),
|
|
name='broadcast_notification_create')
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Creating Personal Notifications (Existing Code)
|
|
|
|
```python
|
|
from notifications.models import Notification
|
|
|
|
# Create a personal notification for a specific user
|
|
Notification.create_personal(
|
|
user=some_user,
|
|
title="Appointment Reminder",
|
|
message="You have an appointment tomorrow at 10:00 AM",
|
|
notification_type='INFO',
|
|
action_url='/appointments/123/'
|
|
)
|
|
```
|
|
|
|
### Creating General Notifications (New)
|
|
|
|
```python
|
|
from notifications.models import Notification
|
|
|
|
# Create a system-wide announcement
|
|
Notification.create_general(
|
|
title="System Maintenance",
|
|
message="The system will be under maintenance on Saturday from 2-4 AM",
|
|
notification_type='WARNING'
|
|
)
|
|
```
|
|
|
|
### Creating Role-Based Notifications (New)
|
|
|
|
```python
|
|
from notifications.models import Notification
|
|
from core.models import User
|
|
|
|
# Notify all admins and front desk staff
|
|
Notification.create_role_based(
|
|
roles=[User.Role.ADMIN, User.Role.FRONT_DESK],
|
|
title="New Patient Registration",
|
|
message="A new patient has been registered and requires file setup",
|
|
notification_type='INFO',
|
|
action_url='/patients/new/'
|
|
)
|
|
```
|
|
|
|
### Querying Notifications
|
|
|
|
```python
|
|
from notifications.models import Notification
|
|
|
|
# Get all notifications for a user (personal + general + role-based)
|
|
user_notifications = Notification.get_for_user(request.user)
|
|
|
|
# Get unread count
|
|
unread_count = Notification.get_unread_count(request.user)
|
|
|
|
# Mark all as read
|
|
Notification.mark_all_as_read(request.user)
|
|
```
|
|
|
|
## Admin Interface
|
|
|
|
Admins can create broadcast notifications through the web interface:
|
|
|
|
1. Navigate to `/notifications/inbox/broadcast/create/`
|
|
2. Select broadcast type:
|
|
- **General**: Visible to all users
|
|
- **Role-Based**: Select specific roles
|
|
3. Fill in title, message, type, and optional action URL
|
|
4. Submit to create the notification
|
|
|
|
## Backward Compatibility
|
|
|
|
✅ **Fully backward compatible** - All existing code that creates personal notifications continues to work without modification:
|
|
|
|
```python
|
|
# This still works exactly as before
|
|
Notification.objects.create(
|
|
user=some_user,
|
|
title="Test",
|
|
message="Test message",
|
|
notification_type='INFO'
|
|
)
|
|
```
|
|
|
|
## Database Query Optimization
|
|
|
|
The `get_for_user()` method uses a single optimized query with OR conditions:
|
|
|
|
```python
|
|
Q(user=user) | # Personal notifications
|
|
Q(is_general=True) | # General notifications
|
|
Q(target_roles__contains=[user.role]) # Role-based notifications
|
|
```
|
|
|
|
This ensures efficient retrieval of all relevant notifications in one database query.
|
|
|
|
## Notification Types
|
|
|
|
Each notification can be one of four types:
|
|
- `INFO` - Informational (blue)
|
|
- `SUCCESS` - Success message (green)
|
|
- `WARNING` - Warning (yellow/orange)
|
|
- `ERROR` - Error or critical alert (red)
|
|
|
|
## Security
|
|
|
|
- Only users with `ADMIN` role can create broadcast notifications
|
|
- Personal notifications are only visible to the targeted user
|
|
- General notifications are visible to all authenticated users
|
|
- Role-based notifications are only visible to users with matching roles
|
|
|
|
## Testing
|
|
|
|
To test the implementation:
|
|
|
|
1. **Test Personal Notifications:**
|
|
```python
|
|
# Create a notification for a specific user
|
|
Notification.create_personal(user, "Test", "Personal notification")
|
|
# Verify only that user sees it
|
|
```
|
|
|
|
2. **Test General Notifications:**
|
|
```python
|
|
# Create a general notification
|
|
Notification.create_general("Announcement", "System-wide message")
|
|
# Verify all users see it
|
|
```
|
|
|
|
3. **Test Role-Based Notifications:**
|
|
```python
|
|
# Create notification for admins only
|
|
Notification.create_role_based(['ADMIN'], "Admin Alert", "Admin-only message")
|
|
# Verify only admin users see it
|
|
```
|
|
|
|
## Migration Instructions
|
|
|
|
The migration has already been applied. If deploying to a new environment:
|
|
|
|
```bash
|
|
python3 manage.py migrate notifications
|
|
```
|
|
|
|
## Summary
|
|
|
|
The notification system now supports:
|
|
- ✅ User-specific (personal) notifications
|
|
- ✅ System-wide (general) notifications
|
|
- ✅ Role-based notifications
|
|
- ✅ Backward compatibility with existing code
|
|
- ✅ Efficient database queries
|
|
- ✅ Admin interface for creating broadcasts
|
|
- ✅ Proper filtering in all views
|
|
|
|
Users will now only see notifications that are:
|
|
1. Specifically addressed to them (personal)
|
|
2. Marked as general (system-wide)
|
|
3. Targeted to their role (role-based)
|
|
|
|
This solves the issue where users were seeing everyone's notifications.
|