""" Occupational Therapy (OT) models for the Tenhal Multidisciplinary Healthcare Platform. This module handles OT consultations and session notes based on OT-F-1 and OT-F-3 forms. """ from django.db import models from django.utils.translation import gettext_lazy as _ from simple_history.models import HistoricalRecords from core.models import ( UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin, ) class OTConsult(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin): """ OT consultation form (OT-F-1). Initial assessment and evaluation. """ class Recommendation(models.TextChoices): CONTINUE = 'CONTINUE', _('Continue Treatment') DISCHARGE = 'DISCHARGE', _('Discharge') REFER_TO_OTHER = 'REFER_TO_OTHER', _('Refer to Other Service') # Core Relationships patient = models.ForeignKey( 'core.Patient', on_delete=models.CASCADE, related_name='ot_consults', verbose_name=_("Patient") ) appointment = models.ForeignKey( 'appointments.Appointment', on_delete=models.SET_NULL, null=True, blank=True, related_name='ot_consults', verbose_name=_("Appointment") ) consultation_date = models.DateField( verbose_name=_("Consultation Date") ) provider = models.ForeignKey( 'core.User', on_delete=models.SET_NULL, null=True, related_name='ot_consults_provided', verbose_name=_("Provider") ) # Reasons for Referral (TextField for user-friendly input) reasons = models.TextField( blank=True, help_text=_("List of reasons for referral (e.g., motor skills, sensory processing, self-care)"), verbose_name=_("Reasons for Referral") ) # Top 3 Difficulty Areas top_difficulty_areas = models.TextField( blank=True, help_text=_("Three main areas of difficulty"), verbose_name=_("Top Difficulty Areas") ) # Developmental Motor Milestones (TextField for user-friendly input) developmental_motor_milestones = models.TextField( blank=True, help_text=_("Motor milestone achievements"), verbose_name=_("Developmental Motor Milestones") ) # Self-Help Skills (TextField for user-friendly input) self_help_skills = models.TextField( blank=True, help_text=_("Self-care and daily living skills assessment"), verbose_name=_("Self-Help Skills") ) # Feeding Participation feeding_participation = models.TextField( blank=True, verbose_name=_("Feeding Participation") ) # Behavior Descriptors infant_behavior_descriptors = models.TextField( blank=True, help_text=_("Behavior descriptors during infancy"), verbose_name=_("Infant Behavior Descriptors") ) current_behavior_descriptors = models.TextField( blank=True, help_text=_("Current behavior descriptors"), verbose_name=_("Current Behavior Descriptors") ) # Recommendation recommendation = models.CharField( max_length=20, choices=Recommendation.choices, blank=True, verbose_name=_("Recommendation") ) recommendation_notes = models.TextField( blank=True, verbose_name=_("Recommendation Notes") ) history = HistoricalRecords() class Meta: verbose_name = _("OT Consultation") verbose_name_plural = _("OT Consultations") ordering = ['-consultation_date', '-created_at'] indexes = [ models.Index(fields=['patient', 'consultation_date']), models.Index(fields=['provider', 'consultation_date']), models.Index(fields=['tenant', 'consultation_date']), ] def __str__(self): return f"OT Consultation - {self.patient} - {self.consultation_date}" class OTSession(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin): """ OT session notes form (OT-F-3). Progress tracking and session documentation. """ class SessionType(models.TextChoices): CONSULT = 'CONSULT', _('Consultation') INDIVIDUAL = 'INDIVIDUAL', _('Individual Session') GROUP = 'GROUP', _('Group Session') PARENT_TRAINING = 'PARENT_TRAINING', _('Parent Training') # Core Relationships patient = models.ForeignKey( 'core.Patient', on_delete=models.CASCADE, related_name='ot_sessions', verbose_name=_("Patient") ) appointment = models.ForeignKey( 'appointments.Appointment', on_delete=models.SET_NULL, null=True, blank=True, related_name='ot_sessions', verbose_name=_("Appointment") ) session_date = models.DateField( verbose_name=_("Session Date") ) provider = models.ForeignKey( 'core.User', on_delete=models.SET_NULL, null=True, related_name='ot_sessions_provided', verbose_name=_("Provider") ) # Session Details session_type = models.CharField( max_length=20, choices=SessionType.choices, verbose_name=_("Session Type") ) cooperative_level = models.PositiveSmallIntegerField( null=True, blank=True, help_text=_("Cooperative level (1-4 scale)"), verbose_name=_("Cooperative Level (1-4)") ) distraction_tolerance = models.PositiveSmallIntegerField( null=True, blank=True, help_text=_("Distraction tolerance (1-4 scale)"), verbose_name=_("Distraction Tolerance (1-4)") ) # Activities Checklist (TextField: "Today we work on...") activities_checklist = models.TextField( blank=True, help_text=_("List of activities worked on during session"), verbose_name=_("Activities Checklist") ) # Session Notes observations = models.TextField( blank=True, verbose_name=_("Observations") ) activities_performed = models.TextField( blank=True, verbose_name=_("Activities Performed") ) recommendations = models.TextField( blank=True, verbose_name=_("Recommendations") ) history = HistoricalRecords() class Meta: verbose_name = _("OT Session") verbose_name_plural = _("OT Sessions") ordering = ['-session_date', '-created_at'] indexes = [ models.Index(fields=['patient', 'session_date']), models.Index(fields=['provider', 'session_date']), models.Index(fields=['tenant', 'session_date']), ] def __str__(self): return f"OT Session - {self.patient} - {self.session_date}" @property def cooperative_level_display(self): """Return cooperative level with description.""" levels = { 1: _("Poor"), 2: _("Fair"), 3: _("Good"), 4: _("Excellent") } return levels.get(self.cooperative_level, "") @property def distraction_tolerance_display(self): """Return distraction tolerance with description.""" levels = { 1: _("Low"), 2: _("Moderate"), 3: _("Good"), 4: _("High") } return levels.get(self.distraction_tolerance, "") class OTTargetSkill(UUIDPrimaryKeyMixin): """ Target skills with 0-10 scoring for OT sessions. Tracks progress on specific therapeutic goals. """ session = models.ForeignKey( OTSession, on_delete=models.CASCADE, related_name='target_skills', verbose_name=_("Session") ) skill_name = models.CharField( max_length=200, verbose_name=_("Skill Name") ) score = models.PositiveSmallIntegerField( help_text=_("Score from 0 (not achieved) to 10 (fully achieved)"), verbose_name=_("Score (0-10)") ) notes = models.TextField( blank=True, verbose_name=_("Notes") ) order = models.PositiveIntegerField( default=0, help_text=_("Order of skills in the list"), verbose_name=_("Order") ) class Meta: verbose_name = _("OT Target Skill") verbose_name_plural = _("OT Target Skills") ordering = ['session', 'order'] def __str__(self): return f"{self.skill_name} - Score: {self.score}/10" @property def score_percentage(self): """Return score as percentage.""" return (self.score / 10) * 100 @property def achievement_level(self): """Return achievement level description.""" if self.score == 0: return _("Not Achieved") elif self.score <= 3: return _("Emerging") elif self.score <= 6: return _("Developing") elif self.score <= 9: return _("Proficient") else: return _("Mastered") class OTProgressReport(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin): """ OT progress report summarizing treatment outcomes. """ patient = models.ForeignKey( 'core.Patient', on_delete=models.CASCADE, related_name='ot_progress_reports', verbose_name=_("Patient") ) report_date = models.DateField( verbose_name=_("Report Date") ) provider = models.ForeignKey( 'core.User', on_delete=models.SET_NULL, null=True, related_name='ot_progress_reports_provided', verbose_name=_("Provider") ) # Session Summary sessions_scheduled = models.PositiveIntegerField( default=0, verbose_name=_("Sessions Scheduled") ) sessions_attended = models.PositiveIntegerField( default=0, verbose_name=_("Sessions Attended") ) # Progress Summary goals_progress = models.TextField( blank=True, help_text=_("Progress on each goal"), verbose_name=_("Goals Progress") ) overall_progress = models.TextField( blank=True, verbose_name=_("Overall Progress") ) # Recommendations recommendations = models.TextField( blank=True, verbose_name=_("Recommendations") ) continue_treatment = models.BooleanField( default=True, verbose_name=_("Continue Treatment") ) history = HistoricalRecords() class Meta: verbose_name = _("OT Progress Report") verbose_name_plural = _("OT Progress Reports") ordering = ['-report_date', '-created_at'] indexes = [ models.Index(fields=['patient', 'report_date']), models.Index(fields=['tenant', 'report_date']), ] def __str__(self): return f"OT Progress Report - {self.patient} - {self.report_date}" @property def attendance_rate(self): """Calculate attendance rate percentage.""" if self.sessions_scheduled > 0: return round((self.sessions_attended / self.sessions_scheduled) * 100, 2) return 0