HH/apps/complaints/signals.py

183 lines
6.6 KiB
Python

"""
Complaint signals - Automatic SMS notifications on status changes
This module handles automatic SMS notifications to complainants when:
1. Complaint is created (confirmation)
2. Complaint status changes to resolved or closed
"""
import logging
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.sites.shortcuts import get_current_site
from .models import Complaint, ComplaintUpdate
logger = logging.getLogger(__name__)
@receiver(post_save, sender=Complaint)
def send_complaint_creation_sms(sender, instance, created, **kwargs):
"""
Send SMS notification when complaint is created.
Only sends for public complaints (those with contact_phone).
"""
if not created:
return
# Only send SMS if phone number is provided
if not instance.contact_phone:
logger.info(f"Complaint #{instance.id} created but no phone number provided. Skipping SMS.")
return
# Send SMS notification
try:
from apps.notifications.services import NotificationService
# Get tracking URL
tracking_url = instance.get_tracking_url()
# Bilingual SMS messages
messages = {
'en': f"PX360: Your complaint #{instance.reference_number} has been received. Track: {tracking_url}",
'ar': f"PX360: تم استلام شكوتك #{instance.reference_number}. تتبع الشكوى: {tracking_url}"
}
# Default to English (can be enhanced to detect language)
sms_message = messages['en']
# Send SMS
notification_log = NotificationService.send_sms(
phone=instance.contact_phone,
message=sms_message,
related_object=instance,
metadata={
'notification_type': 'complaint_created',
'reference_number': instance.reference_number,
'tracking_url': tracking_url,
'language': 'en' # Default to English
}
)
logger.info(f"Creation SMS sent to {instance.contact_phone} for complaint #{instance.id}")
# Create complaint update to track SMS
ComplaintUpdate.objects.create(
complaint=instance,
update_type='communication',
message=f"SMS notification sent to complainant: Your complaint has been received",
metadata={
'notification_type': 'complaint_created',
'notification_log_id': str(notification_log.id) if notification_log else None
}
)
except Exception as e:
# Log error but don't fail the complaint save
logger.error(f"Failed to send creation SMS for complaint #{instance.id}: {str(e)}")
@receiver(post_save, sender=Complaint)
def send_complaint_status_change_sms(sender, instance, created, **kwargs):
"""
Send SMS notification when complaint status changes to resolved or closed.
Uses update_fields to detect actual status changes (not just re-saves).
"""
# Skip on creation (handled by creation signal)
if created:
return
# Check if this is a status change to resolved or closed
# Use update_fields to detect actual status changes
if not hasattr(instance, '_status_was'):
return
old_status = instance._status_was
new_status = instance.status
# Only send SMS for resolved or closed status changes
if new_status not in ['resolved', 'closed']:
return
# Only send if status actually changed
if old_status == new_status:
return
# Only send SMS if phone number is provided
if not instance.contact_phone:
logger.info(f"Complaint #{instance.id} status changed to {new_status} but no phone number. Skipping SMS.")
return
# Send SMS notification
try:
from apps.notifications.services import NotificationService
# Bilingual SMS messages
messages_en = {
'resolved': f"PX360: Your complaint #{instance.reference_number} has been resolved. Thank you for your feedback.",
'closed': f"PX360: Your complaint #{instance.reference_number} has been closed. Thank you for your feedback."
}
messages_ar = {
'resolved': f"PX360: تم حل شكوتك #{instance.reference_number}. شكراً لتعاونكم.",
'closed': f"PX360: تم إغلاق شكوتك #{instance.reference_number}. شكراً لتعاونكم."
}
# Default to English (can be enhanced to detect language)
sms_message = messages_en.get(new_status, '')
# Send SMS
notification_log = NotificationService.send_sms(
phone=instance.contact_phone,
message=sms_message,
related_object=instance,
metadata={
'notification_type': 'complaint_status_change',
'reference_number': instance.reference_number,
'old_status': old_status,
'new_status': new_status,
'language': 'en' # Default to English
}
)
logger.info(f"Status change SMS sent to {instance.contact_phone} for complaint #{instance.id}: {old_status} -> {new_status}")
# Create complaint update to track SMS
ComplaintUpdate.objects.create(
complaint=instance,
update_type='communication',
message=f"SMS notification sent to complainant: Status changed to {new_status}",
metadata={
'notification_type': 'complaint_status_change',
'old_status': old_status,
'new_status': new_status,
'notification_log_id': str(notification_log.id) if notification_log else None
}
)
except Exception as e:
# Log error but don't fail the complaint save
logger.error(f"Failed to send status change SMS for complaint #{instance.id}: {str(e)}")
# Hook into ComplaintUpdate to track SMS sent manually via API
@receiver(post_save, sender=ComplaintUpdate)
def track_manual_sms(sender, instance, created, **kwargs):
"""
Track manually sent SMS notifications.
This ensures that SMS sent via API endpoints (like send_resolution_notification)
are also properly tracked.
"""
if not created:
return
# Check if this update was for a communication/notification
if instance.update_type == 'communication':
# Log tracking info
logger.info(
f"Manual communication update created for complaint #{instance.complaint.id}: "
f"{instance.message[:50]}..."
)