""" 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]}..." )