""" Call Center models - Call center interaction tracking and ratings This module implements call center tracking that: - Records call center interactions - Tracks agent performance - Monitors wait times and satisfaction - Creates PX actions for low ratings """ from django.db import models from apps.core.models import TimeStampedModel, UUIDModel class CallCenterInteraction(UUIDModel, TimeStampedModel): """ Call center interaction - tracks calls with patients. Low ratings trigger PX action creation. """ # Patient information patient = models.ForeignKey( 'organizations.Patient', on_delete=models.CASCADE, null=True, blank=True, related_name='call_center_interactions' ) # Caller information (if not a patient) caller_name = models.CharField(max_length=200, blank=True) caller_phone = models.CharField(max_length=20, blank=True) caller_relationship = models.CharField( max_length=50, choices=[ ('patient', 'Patient'), ('family', 'Family Member'), ('other', 'Other'), ], default='patient' ) # Organization hospital = models.ForeignKey( 'organizations.Hospital', on_delete=models.CASCADE, related_name='call_center_interactions' ) department = models.ForeignKey( 'organizations.Department', on_delete=models.SET_NULL, null=True, blank=True, related_name='call_center_interactions' ) # Agent information agent = models.ForeignKey( 'accounts.User', on_delete=models.SET_NULL, null=True, blank=True, related_name='call_center_interactions' ) # Call details call_type = models.CharField( max_length=50, choices=[ ('inquiry', 'Inquiry'), ('complaint', 'Complaint'), ('appointment', 'Appointment'), ('follow_up', 'Follow-up'), ('feedback', 'Feedback'), ('other', 'Other'), ], db_index=True ) subject = models.CharField(max_length=500) notes = models.TextField(blank=True) # Metrics wait_time_seconds = models.IntegerField( null=True, blank=True, help_text="Time caller waited before agent answered" ) call_duration_seconds = models.IntegerField( null=True, blank=True, help_text="Total call duration" ) # Rating (1-5 scale) satisfaction_rating = models.IntegerField( null=True, blank=True, help_text="Caller satisfaction rating (1-5)" ) is_low_rating = models.BooleanField( default=False, db_index=True, help_text="True if rating below threshold (< 3)" ) # Resolution resolved = models.BooleanField(default=False) resolution_notes = models.TextField(blank=True) # Timestamps call_started_at = models.DateTimeField(auto_now_add=True) call_ended_at = models.DateTimeField(null=True, blank=True) # Metadata metadata = models.JSONField(default=dict, blank=True) class Meta: ordering = ['-call_started_at'] indexes = [ models.Index(fields=['hospital', '-call_started_at']), models.Index(fields=['agent', '-call_started_at']), models.Index(fields=['is_low_rating', '-call_started_at']), ] def __str__(self): caller = self.patient.get_full_name() if self.patient else self.caller_name return f"{caller} - {self.call_type} ({self.call_started_at.strftime('%Y-%m-%d %H:%M')})" def save(self, *args, **kwargs): """Check if rating is low""" if self.satisfaction_rating and self.satisfaction_rating < 3: self.is_low_rating = True super().save(*args, **kwargs) class CallRecord(UUIDModel, TimeStampedModel): """ Call Record - Tracks call center recordings imported from CSV. Stores all call metadata from the call recording system including: - Call details (start, end, duration) - Caller information - Department and extension - Recording file information - Inbound/Outbound call details """ # Core identifiers media_id = models.UUIDField(unique=True, db_index=True, help_text="Unique media ID from recording system") media_type = models.CharField(max_length=50, default="Calls", help_text="Type of media (e.g., Calls)") chain = models.CharField(max_length=255, blank=True, help_text="Chain identifier") evaluated = models.BooleanField(default=False, help_text="Whether the call has been evaluated") # Call timing call_start = models.DateTimeField(help_text="Call start time") call_end = models.DateTimeField(null=True, blank=True, help_text="Call end time") call_length = models.CharField(max_length=20, blank=True, help_text="Call length as HH:MM:SS") call_duration_seconds = models.IntegerField(null=True, blank=True, help_text="Call duration in seconds") # Caller information first_name = models.CharField(max_length=100, blank=True, help_text="Caller first name") last_name = models.CharField(max_length=100, blank=True, help_text="Caller last name") # Department information extension = models.CharField(max_length=20, blank=True, help_text="Extension number") department = models.CharField(max_length=255, blank=True, help_text="Department name") location = models.CharField(max_length=255, blank=True, help_text="Location") # Inbound call details inbound_id = models.CharField(max_length=50, blank=True, help_text="Inbound call ID") inbound_name = models.CharField(max_length=255, blank=True, help_text="Inbound caller name/number") dnis = models.CharField(max_length=50, blank=True, help_text="Dialed Number Identification Service") # Outbound call details outbound_id = models.CharField(max_length=50, blank=True, help_text="Outbound call ID") outbound_name = models.CharField(max_length=255, blank=True, help_text="Outbound caller name/number") # Flag information flag_name = models.CharField(max_length=100, blank=True, help_text="Flag name") flag_value = models.CharField(max_length=100, blank=True, help_text="Flag value") # Recording file information file_location = models.CharField(max_length=500, blank=True, help_text="File system location") file_name = models.CharField(max_length=500, blank=True, help_text="Recording file name") file_hash = models.CharField(max_length=64, blank=True, help_text="File hash for integrity") # Additional metadata external_ref = models.CharField(max_length=100, blank=True, help_text="External reference number") transfer_from = models.CharField(max_length=255, blank=True, help_text="Transfer source") recorded_by = models.CharField(max_length=255, blank=True, help_text="Recording system/user") time_zone = models.CharField(max_length=50, default="03:00:00", help_text="Time zone offset") recording_server_name = models.CharField(max_length=100, blank=True, help_text="Recording server name") # Hospital link (for multi-hospital systems) hospital = models.ForeignKey( 'organizations.Hospital', on_delete=models.CASCADE, null=True, blank=True, related_name='call_records' ) class Meta: ordering = ['-call_start'] indexes = [ models.Index(fields=['-call_start']), models.Index(fields=['media_id']), models.Index(fields=['department']), models.Index(fields=['evaluated']), models.Index(fields=['hospital', '-call_start']), ] def __str__(self): return f"{self.first_name} {self.last_name} - {self.call_start.strftime('%Y-%m-%d %H:%M')}" @property def caller_full_name(self): """Get full caller name""" return f"{self.first_name} {self.last_name}".strip() @property def is_inbound(self): """Check if call is inbound""" return bool(self.inbound_id or self.inbound_name) @property def is_outbound(self): """Check if call is outbound""" return bool(self.outbound_id or self.outbound_name)