""" 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, 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=["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)