21 KiB
Internal Notifications Assessment Report
AgdarCentre Healthcare Platform
Date: November 2, 2025
Assessed By: Cline AI Assistant
📊 Executive Summary
The AgdarCentre project implements a dual-layer notification system:
- External Notifications (SMS/WhatsApp/Email) - For patient communications ✅ Fully Implemented
- Internal Notifications (In-app) - For staff communications ❌ Critical Gap Identified
Overall Status: 70% Complete
Critical Issue: In-app notification model is missing, causing all internal staff notifications to fail silently.
🏗️ System Architecture
Notification Flow
User Action (e.g., Book Appointment)
↓
Django Signal (post_save)
↓
Signal Handler (appointments/signals.py)
↓
Celery Task (core/tasks.py)
↓
┌─────────────────────────────────────┐
│ Multi-Channel Notification │
├─────────────────────────────────────┤
│ • In-App (❌ Model Missing) │
│ • Email (✅ Working) │
│ • SMS (✅ Working) │
│ • WhatsApp (✅ Working) │
└─────────────────────────────────────┘
↓
Message/Notification Record Created
↓
Provider Integration (Twilio/Unifonic)
↓
Delivery Status Tracking
✅ Implemented Components
1. External Notification System
Location: notifications/ app
Models (notifications/models.py)
-
MessageTemplate
- Reusable message templates
- Bilingual support (English/Arabic)
- Variable substitution system
- Channel-specific (SMS/WhatsApp/Email)
- Active/inactive status
-
Message
- Outbound message tracking
- Status lifecycle: QUEUED → SENT → DELIVERED → FAILED
- Provider integration (Twilio/Unifonic)
- Retry logic (max 3 attempts)
- Cost tracking
- Delivery timestamps
-
NotificationPreference
- Patient-specific preferences
- Channel preferences (SMS/WhatsApp/Email)
- Notification type preferences
- Language preference (EN/AR)
- Preferred channel priority
-
MessageLog
- Detailed audit trail
- Event tracking (Created, Queued, Sent, Delivered, Failed, Read, Retry)
- Provider response storage
- Error message capture
Messaging Service (integrations/messaging_service.py)
Key Features:
- Template-based messaging with variable substitution
- Multi-channel delivery (SMS, WhatsApp, Email)
- Automatic delivery tracking
- Patient preference checking
- Retry logic for failed messages
- Bulk messaging capabilities
- Status synchronization with providers
Main Methods:
MessagingService:
- send_from_template() # Send using template
- send_message() # Send direct message
- update_message_status() # Sync with provider
- retry_failed_message() # Retry failed sends
- send_bulk_messages() # Bulk sending
- get_message_statistics() # Analytics
Management Interface (notifications/views.py)
Dashboard Views:
MessageDashboardView- Statistics, charts, recent messagesMessageAnalyticsView- Detailed analytics and reports
Message Management:
MessageListView- List with filtering and searchMessageDetailView- Full message details and timelineMessageExportView- CSV exportMessageRetryView- Retry failed messages
Template Management:
TemplateListView- List all templatesTemplateDetailView- Template details and usage statsTemplateCreateView- Create new templateTemplateUpdateView- Edit templateTemplateDeleteView- Delete templateTemplateToggleView- Activate/deactivateTemplateTestView- Test with sample data
Bulk Messaging:
BulkMessageView- Send to multiple recipients
Status: Backend 100% complete, Frontend templates 10% complete
2. Celery Tasks (core/tasks.py)
Email Tasks:
send_email_task()- Send plain emailsend_template_email_task()- Send using Django template
SMS/WhatsApp Tasks:
send_sms_task()- Send SMS via Twiliosend_whatsapp_task()- Send WhatsApp via Twilio
In-App Notification Tasks:
create_notification_task()- ❌ BROKEN - References non-existent modelsend_multi_channel_notification_task()- Multi-channel delivery
Maintenance Tasks:
cleanup_old_notifications()- Clean up old read notifications
3. Appointment Lifecycle Notifications (appointments/signals.py)
Automatic Notifications Triggered:
| Event | Notification Type | Recipients | Channels |
|---|---|---|---|
| New Appointment | In-app + Email | Provider | In-app, Email |
| Confirmed | Multi-channel | Patient | SMS/WhatsApp, Email, In-app |
| Rescheduled | Multi-channel | Patient + Provider | SMS/WhatsApp, Email, In-app |
| Patient Arrived | In-app | Provider | In-app |
| In Progress | Log only | - | - |
| Completed | Patient | ||
| Cancelled | Multi-channel | Patient + Provider | SMS/WhatsApp, Email, In-app |
| No-Show | Email + In-app | Patient + Provider | Email, In-app |
Signal Handlers:
- appointment_pre_save() # Auto-generate appointment number
- appointment_post_save() # Trigger notifications
- create_subfile_if_needed() # Auto-create patient sub-file
- notify_provider_new_appointment()
- create_patient_confirmation_token()
- schedule_appointment_reminders()
- handle_appointment_confirmed()
- handle_appointment_rescheduled()
- handle_appointment_arrived()
- handle_appointment_in_progress()
- handle_appointment_completed()
- handle_appointment_cancelled()
- handle_appointment_no_show()
4. Appointment Reminder System (appointments/tasks.py)
Scheduled Reminders:
- 24-hour reminder before appointment
- 2-hour reminder before appointment
- Automatic cancellation on appointment changes
Reminder Channels:
- Determined by patient preferences
- Default: SMS
- Fallback: WhatsApp → Email
❌ Critical Gaps Identified
1. Missing In-App Notification Model
Problem:
The create_notification_task() function in core/tasks.py attempts to import:
from notifications.models import Notification # ❌ This model doesn't exist
Impact:
- All in-app notifications are failing silently
- Staff members receive no internal notifications
- System relies entirely on external channels (email/SMS)
- Provider alerts not working
- Patient arrival notifications not working
- Status change notifications not working
Evidence:
# core/tasks.py line 150
@shared_task(bind=True, max_retries=3)
def create_notification_task(
self,
user_id: str,
title: str,
message: str,
notification_type: str = 'INFO',
related_object_type: Optional[str] = None,
related_object_id: Optional[str] = None,
) -> bool:
try:
from notifications.models import Notification # ❌ FAILS HERE
from core.models import User
user = User.objects.get(id=user_id)
notification = Notification.objects.create( # ❌ NEVER EXECUTES
user=user,
title=title,
message=message,
notification_type=notification_type,
related_object_type=related_object_type,
related_object_id=related_object_id,
)
logger.info(f"Notification created for user {user_id}: {title}")
return True
except Exception as exc:
logger.error(f"Failed to create notification: {exc}")
raise self.retry(exc=exc, countdown=60)
Required Fix:
Create Notification model in notifications/models.py with fields:
user(ForeignKey to User)title(CharField)message(TextField)notification_type(CharField with choices: INFO, WARNING, ERROR, SUCCESS)is_read(BooleanField)read_at(DateTimeField, nullable)related_object_type(CharField, nullable)related_object_id(UUIDField, nullable)created_at(DateTimeField)updated_at(DateTimeField)
2. Missing Notification Center UI
Problem: No user interface for staff to view in-app notifications
Required Components:
- Bell icon in header with unread count badge
- Dropdown notification list
- Mark as read functionality
- Link to related objects (appointments, invoices, etc.)
- Notification preferences page
- Notification history page
3. Incomplete Frontend Templates
Status: 9 templates pending (only dashboard.html completed)
Missing Templates:
message_list.html- Message list viewmessage_detail.html- Message detail viewtemplate_list.html- Template list viewtemplate_detail.html- Template detail viewtemplate_form.html- Template create/edit formtemplate_confirm_delete.html- Template deletion confirmationtemplate_test.html- Template testing interfacebulk_message.html- Bulk messaging interfaceanalytics.html- Analytics dashboardpartials/message_list_partial.html- HTMX partial
📋 Notification Types
External (Patient-Facing)
-
Appointment Reminders
- Automated 24 hours before
- Automated 2 hours before
- Respects patient preferences
- Multi-channel delivery
-
Appointment Confirmations
- On booking
- On confirmation
- Includes appointment details
-
Rescheduling Notices
- New date/time
- Reason for change
- Confirmation request
-
Cancellation Notices
- Cancellation reason
- Rescheduling instructions
-
Completion Receipts
- Thank you message
- Next steps
-
Billing Notifications
- Invoice generation
- Payment reminders
- Payment confirmations
-
Marketing Communications
- Optional (preference-based)
- Promotional offers
- Health tips
Internal (Staff-Facing)
-
New Appointment Alerts
- Provider notifications
- Appointment details
- Patient information
-
Patient Arrival Alerts
- Front desk → Provider
- Financial clearance status
- Consent verification status
-
Status Change Alerts
- Appointment lifecycle updates
- Rescheduling notifications
- Cancellation notifications
-
System Alerts
- Errors
- Warnings
- Info messages
🔧 Technical Implementation Details
Message Template System
Variable Substitution:
# Template definition
template.body_en = "Hi {patient_name}, your appointment is on {date} at {time}"
template.variables = ['patient_name', 'date', 'time']
# Rendering
context = {
'patient_name': 'Ahmed Al-Saud',
'date': '2025-11-15',
'time': '10:00 AM'
}
rendered = template.render(language='en', **context)
# Result: "Hi Ahmed Al-Saud, your appointment is on 2025-11-15 at 10:00 AM"
Bilingual Support:
- English:
body_enfield - Arabic:
body_arfield with RTL support - Automatic language selection based on patient preference
Patient Notification Preferences
Controllable Settings:
-
Channel Preferences:
- SMS enabled/disabled
- WhatsApp enabled/disabled
- Email enabled/disabled
-
Notification Types:
- Appointment reminders
- Appointment confirmations
- Results notifications
- Billing notifications
- Marketing communications
-
Language & Channel:
- Preferred language (EN/AR)
- Preferred channel (SMS/WhatsApp/Email)
Preference Checking:
# In MessagingService
def _check_patient_preferences(patient_id, channel, notification_type):
prefs = NotificationPreference.objects.get(patient_id=patient_id)
return prefs.can_send(channel, notification_type)
Message Delivery Tracking
Status Lifecycle:
QUEUED → SENT → DELIVERED → READ
↓
FAILED (with retry logic, max 3 attempts)
↓
BOUNCED (permanent failure)
Audit Trail:
MessageLogrecords every state transition- Provider responses stored in JSON
- Error messages captured
- Retry attempts tracked
- Timestamps for each event
Example Timeline:
1. Created - 2025-11-02 10:00:00
2. Queued - 2025-11-02 10:00:01
3. Sending - 2025-11-02 10:00:02
4. Sent - 2025-11-02 10:00:03 (Provider: Twilio, SID: SM123...)
5. Delivered - 2025-11-02 10:00:15 (Confirmed by provider)
6. Read - 2025-11-02 10:05:30 (WhatsApp read receipt)
Retry Logic
Automatic Retries:
- Max 3 retry attempts
- Exponential backoff (60s, 120s, 240s)
- Only for FAILED status
- Manual retry available via UI
Retry Conditions:
def can_retry(self):
return self.status == Message.Status.FAILED and self.retry_count < 3
📈 Analytics & Reporting
Available Metrics
Dashboard Statistics:
- Total messages sent
- Success rate (%)
- Messages by status (Queued, Sent, Delivered, Failed)
- Messages by channel (SMS, WhatsApp, Email)
- Daily trend (last 7 days)
Analytics Dashboard:
- Delivery rate charts
- Channel comparison
- Daily/weekly/monthly trends
- Top templates by usage
- Cost analysis (per message, per channel)
- Failure analysis
Export Capabilities:
- CSV export of message history
- Filtered exports (date range, channel, status, template)
- Includes all message details and timestamps
Sample Analytics Query
# Get statistics for last 7 days
stats = MessagingService().get_message_statistics(
tenant_id=tenant_id,
days=7
)
# Returns:
{
'total': 1250,
'by_channel': {
'SMS': 800,
'WHATSAPP': 350,
'EMAIL': 100
},
'by_status': {
'DELIVERED': 1150,
'FAILED': 50,
'QUEUED': 50
},
'success_rate': 92.0
}
🔐 Security & Permissions
Role-Based Access Control
Notification Management:
- Admin: Full access (create, edit, delete templates, send bulk messages)
- Front Desk: View messages, send individual messages, retry failed
- Provider: View own notifications only
- Patient: View own messages only (future feature)
Tenant Isolation:
- All queries filtered by tenant
- Multi-tenancy enforced at model level
- No cross-tenant data access
Audit Logging:
- All administrative actions logged
- User, timestamp, action type recorded
- Changes tracked for compliance
📁 Key Files Reference
Models
notifications/models.py- External notification models (MessageTemplate, Message, NotificationPreference, MessageLog)- ❌ Missing: In-app Notification model
Services
integrations/messaging_service.py- Main messaging API (500+ lines)integrations/sms_providers.py- Provider abstraction layercore/tasks.py- Celery tasks for async notifications
Signal Handlers
appointments/signals.py- Appointment lifecycle notifications (600+ lines)finance/signals.py- Financial notifications (if exists)core/signals.py- Core model signals
Views
notifications/views.py- Notification management views (800+ lines)notifications/forms.py- Forms for templates and messagesnotifications/urls.py- URL routing
Templates
notifications/templates/notifications/dashboard.html- ✅ Completenotifications/templates/notifications/*.html- ❌ 9 templates pending
Tasks
appointments/tasks.py- Appointment-specific tasks (reminders, confirmations)integrations/tasks.py- Integration tasks (provider sync)
📊 Implementation Completeness Matrix
| Component | Status | Completion | Priority |
|---|---|---|---|
| External Notifications | |||
| - Message Models | ✅ Complete | 100% | - |
| - Message Templates | ✅ Complete | 100% | - |
| - Delivery Tracking | ✅ Complete | 100% | - |
| - Patient Preferences | ✅ Complete | 100% | - |
| - Messaging Service | ✅ Complete | 100% | - |
| - Provider Integration | ✅ Complete | 100% | - |
| - Retry Logic | ✅ Complete | 100% | - |
| - Bulk Messaging Backend | ✅ Complete | 100% | - |
| - Analytics Backend | ✅ Complete | 100% | - |
| Internal Notifications | |||
| - In-App Notification Model | ❌ Missing | 0% | 🔴 Critical |
| - Notification Tasks | ⚠️ Broken | 0% | 🔴 Critical |
| - Notification Center UI | ❌ Missing | 0% | 🟡 High |
| Frontend | |||
| - Dashboard Template | ✅ Complete | 100% | - |
| - Message Templates | ❌ Missing | 0% | 🟡 High |
| - Template Templates | ❌ Missing | 0% | 🟡 High |
| - Bulk Messaging Template | ❌ Missing | 0% | 🟡 High |
| - Analytics Template | ❌ Missing | 0% | 🟢 Medium |
| - HTMX Partials | ❌ Missing | 0% | 🟢 Medium |
| Integration | |||
| - Appointment Signals | ✅ Complete | 100% | - |
| - Celery Tasks | ✅ Complete | 100% | - |
| - URL Routing | ✅ Complete | 100% | - |
Overall Completion: 70%
🚨 Critical Issues Summary
Issue #1: Missing In-App Notification Model
- Severity: 🔴 Critical
- Impact: All internal staff notifications failing
- Affected Features:
- Provider appointment alerts
- Patient arrival notifications
- Status change notifications
- System alerts
- Fix Required: Create Notification model
- Estimated Effort: 1-2 hours
Issue #2: No Notification Center UI
- Severity: 🟡 High
- Impact: Staff cannot view notifications
- Affected Users: All staff members
- Fix Required: Build notification center interface
- Estimated Effort: 3-4 hours
Issue #3: Incomplete Frontend Templates
- Severity: 🟡 High
- Impact: Cannot manage messages/templates via UI
- Affected Features: Message management, template management, bulk messaging
- Fix Required: Create 9 missing templates
- Estimated Effort: 2-3 hours
💡 Recommendations
Immediate Actions (Priority 1)
-
Create In-App Notification Model
- Add to
notifications/models.py - Create migration
- Update admin interface
- Test with existing signal handlers
- Add to
-
Build Notification Center UI
- Bell icon in header with badge
- Dropdown notification list
- Mark as read functionality
- Link to related objects
-
Complete Frontend Templates
- Message list and detail views
- Template management views
- Bulk messaging interface
Short-Term Improvements (Priority 2)
-
Real-Time Notifications
- Implement WebSockets (Django Channels)
- Or use HTMX polling for updates
- Push notifications to browser
-
Enhanced Analytics
- Engagement metrics (open rates, click rates)
- Cost analysis by department
- Provider performance metrics
-
Notification Preferences UI
- Staff notification preferences
- Quiet hours configuration
- Notification grouping
Long-Term Enhancements (Priority 3)
-
Advanced Features
- Message scheduling
- Template versioning
- A/B testing for templates
- Rich media support (images, attachments)
-
Integration Expansion
- Additional SMS providers
- Push notifications (mobile app)
- Slack/Teams integration
-
AI/ML Features
- Smart send time optimization
- Predictive delivery success
- Automated template suggestions
🎯 Conclusion
The AgdarCentre notification system has a solid foundation with:
✅ Strengths:
- Comprehensive external messaging (SMS/WhatsApp/Email)
- Robust template system with bilingual support
- Detailed delivery tracking and analytics
- Patient preference management
- Automated appointment lifecycle notifications
- Multi-channel delivery with fallback
- Retry logic and error handling
❌ Critical Gaps:
- In-app notification model missing
- Staff cannot receive internal notifications
- Notification center UI not implemented
- Frontend templates incomplete
Overall Assessment: The external notification system is production-ready and well-implemented. However, the internal notification system has a critical flaw that prevents staff from receiving in-app notifications. This should be addressed immediately to ensure proper staff communication.
Recommended Next Steps:
- Create the missing Notification model (1-2 hours)
- Build notification center UI (3-4 hours)
- Complete frontend templates (2-3 hours)
- Add real-time notification delivery (4-6 hours)
Total Estimated Effort: 10-15 hours to reach 100% completion
📞 Support & Documentation
Related Documentation:
NOTIFICATIONS_IMPLEMENTATION_SUMMARY.md- Implementation detailsPHASE6_SMS_WHATSAPP_INTEGRATION_COMPLETE.md- SMS/WhatsApp integrationPHASE4_STATE_MACHINE_NOTIFICATIONS_COMPLETE.md- State machine notifications
Key Contacts:
- Backend:
integrations/messaging_service.py - Frontend:
notifications/views.py - Signals:
appointments/signals.py - Tasks:
core/tasks.py
Report Generated: November 2, 2025
Version: 1.0
Status: Complete