287 lines
10 KiB
Markdown
287 lines
10 KiB
Markdown
# Appointments, Queuing, and waiting list
|
|
1. Detailed Feature Specifications
|
|
|
|
1.1. Appointment Management System
|
|
|
|
1.1.1 Core Scheduling Logic
|
|
|
|
```python
|
|
# appointments/models.py (simplified)
|
|
class Appointment(models.Model):
|
|
APPOINTMENT_STATUS = (
|
|
('scheduled', 'Scheduled'),
|
|
('confirmed', 'Confirmed'),
|
|
('checked_in', 'Checked In'),
|
|
('in_progress', 'In Progress'),
|
|
('completed', 'Completed'),
|
|
('cancelled', 'Cancelled'),
|
|
('no_show', 'No Show'),
|
|
)
|
|
|
|
patient = models.ForeignKey('accounts.Patient', on_delete=models.CASCADE)
|
|
provider = models.ForeignKey('accounts.HealthcareProvider', on_delete=models.CASCADE)
|
|
appointment_type = models.ForeignKey('AppointmentType', on_delete=models.PROTECT)
|
|
scheduled_time = models.DateTimeField()
|
|
duration = models.DurationField(default=timedelta(minutes=30))
|
|
status = models.CharField(max_length=20, choices=APPOINTMENT_STATUS, default='scheduled')
|
|
reason_for_visit = models.TextField()
|
|
|
|
# Smart scheduling fields
|
|
priority_score = models.IntegerField(default=0) # For triage logic
|
|
is_waitlist_conversion = models.BooleanField(default=False)
|
|
```
|
|
|
|
1.1.2 Scheduling Algorithms
|
|
|
|
```python
|
|
# appointments/logic/scheduling.py
|
|
class SmartScheduler:
|
|
def find_optimal_slot(self, patient, provider, appointment_type, preferred_dates):
|
|
"""Implements multi-factor slot finding"""
|
|
|
|
# Factor 1: Provider availability with buffer time
|
|
base_slots = self.get_available_slots(provider, preferred_dates)
|
|
|
|
# Factor 2: Patient priority (urgent cases get priority)
|
|
prioritized_slots = self.apply_priority_routing(base_slots, patient)
|
|
|
|
# Factor 3: Historical no-show prediction
|
|
optimized_slots = self.apply_no_show_mitigation(prioritized_slots, patient)
|
|
|
|
# Factor 4: Travel time consideration for follow-ups
|
|
final_slots = self.apply_geographic_optimization(optimized_slots, patient)
|
|
|
|
return final_slots
|
|
|
|
def apply_priority_routing(self, slots, patient):
|
|
"""Route high-priority patients to sooner available slots"""
|
|
if self.is_high_priority(patient):
|
|
return sorted(slots, key=lambda x: x['datetime'])
|
|
return slots
|
|
```
|
|
|
|
1.2 Intelligent Queue Management
|
|
|
|
1.2.1 Real-time Queue System
|
|
|
|
```python
|
|
# queue/models.py
|
|
class PatientQueue(models.Model):
|
|
clinic = models.ForeignKey('accounts.Clinic', on_delete=models.CASCADE)
|
|
name = models.CharField(max_length=100) # e.g., "Triage", "Consultation"
|
|
capacity = models.IntegerField(default=10)
|
|
current_wait_time = models.DurationField(null=True, blank=True)
|
|
is_active = models.BooleanField(default=True)
|
|
|
|
class QueueEntry(models.Model):
|
|
queue = models.ForeignKey(PatientQueue, on_delete=models.CASCADE)
|
|
patient = models.ForeignKey('accounts.Patient', on_delete=models.CASCADE)
|
|
appointment = models.OneToOneField('appointments.Appointment', on_delete=models.CASCADE)
|
|
position = models.IntegerField()
|
|
check_in_time = models.DateTimeField(auto_now_add=True)
|
|
estimated_wait_time = models.DurationField()
|
|
actual_wait_time = models.DurationField(null=True, blank=True)
|
|
status = models.CharField(max_length=20, choices=QUEUE_STATUS)
|
|
|
|
class Meta:
|
|
ordering = ['position']
|
|
```
|
|
|
|
1.2.2 Queue Logic Engine
|
|
|
|
```python
|
|
# queue/logic/queue_engine.py
|
|
class QueueEngine:
|
|
def add_to_queue(self, appointment, queue_name="Main"):
|
|
"""Add patient to queue with intelligent positioning"""
|
|
queue = PatientQueue.objects.get(name=queue_name, clinic=appointment.clinic)
|
|
|
|
# Calculate position based on multiple factors
|
|
position = self.calculate_queue_position(appointment, queue)
|
|
|
|
# Estimate wait time based on historical data
|
|
wait_time = self.calculate_estimated_wait(queue, position)
|
|
|
|
queue_entry = QueueEntry.objects.create(
|
|
queue=queue,
|
|
patient=appointment.patient,
|
|
appointment=appointment,
|
|
position=position,
|
|
estimated_wait_time=wait_time
|
|
)
|
|
|
|
# Real-time update via WebSocket
|
|
self.broadcast_queue_update(queue)
|
|
|
|
return queue_entry
|
|
|
|
def calculate_estimated_wait(self, queue, position):
|
|
"""Dynamic wait time calculation"""
|
|
avg_appointment_time = timedelta(minutes=20)
|
|
current_load = queue.queueentry_set.filter(status='waiting').count()
|
|
|
|
# Factor in provider availability and current load
|
|
base_wait = avg_appointment_time * position
|
|
|
|
# Adjust based on real-time factors
|
|
adjustment_factor = self.calculate_load_factor(current_load)
|
|
|
|
return base_wait * adjustment_factor
|
|
```
|
|
|
|
1.3 Smart Waitlist Management
|
|
|
|
1.3.1 Waitlist Logic
|
|
|
|
```python
|
|
# waitlist/models.py
|
|
class WaitlistEntry(models.Model):
|
|
patient = models.ForeignKey('accounts.Patient', on_delete=models.CASCADE)
|
|
preferred_provider = models.ForeignKey('accounts.HealthcareProvider', null=True, blank=True)
|
|
appointment_type = models.ForeignKey('AppointmentType', on_delete=models.PROTECT)
|
|
desired_date_range_start = models.DateField()
|
|
desired_date_range_end = models.DateField()
|
|
flexibility_score = models.IntegerField(default=0) # How flexible is patient on timing
|
|
priority = models.IntegerField(default=0) # Clinical priority
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
is_active = models.BooleanField(default=True)
|
|
|
|
# Notification preferences
|
|
notify_by_sms = models.BooleanField(default=True)
|
|
notify_by_email = models.BooleanField(default=False)
|
|
notify_by_phone = models.BooleanField(default=False)
|
|
|
|
class SlotCancellation(models.Model):
|
|
"""Track cancelled slots for waitlist fulfillment"""
|
|
provider = models.ForeignKey('accounts.HealthcareProvider', on_delete=models.CASCADE)
|
|
original_appointment = models.ForeignKey('appointments.Appointment', on_delete=models.SET_NULL, null=True)
|
|
cancelled_slot_start = models.DateTimeField()
|
|
cancelled_slot_end = models.DateTimeField()
|
|
cancellation_time = models.DateTimeField(auto_now_add=True)
|
|
filled_by_waitlist = models.BooleanField(default=False)
|
|
```
|
|
|
|
1.3.2 Automated Waitlist Fulfillment
|
|
|
|
```python
|
|
# waitlist/logic/waitlist_engine.py
|
|
class WaitlistEngine:
|
|
def check_and_fulfill_waitlist(self, cancellation):
|
|
"""Automatically fill cancelled slots from waitlist"""
|
|
suitable_waitlist_entries = self.find_matching_waitlist_entries(cancellation)
|
|
|
|
for waitlist_entry in suitable_waitlist_entries:
|
|
if self.attempt_waitlist_fulfillment(waitlist_entry, cancellation):
|
|
break # Stop after first successful fulfillment
|
|
|
|
def find_matching_waitlist_entries(self, cancellation):
|
|
"""Find the best waitlist matches for a cancelled slot"""
|
|
return WaitlistEntry.objects.filter(
|
|
is_active=True,
|
|
appointment_type__in=cancellation.provider.supported_appointment_types,
|
|
desired_date_range_start__lte=cancellation.cancelled_slot_start.date(),
|
|
desired_date_range_end__gte=cancellation.cancelled_slot_start.date()
|
|
).order_by('-priority', 'created_at')
|
|
```
|
|
|
|
1.4 Multi-channel Notification System
|
|
|
|
1.4.1 Notification Engine
|
|
|
|
```python
|
|
# notifications/engine.py
|
|
class NotificationEngine:
|
|
CHANNELS = ['sms', 'email', 'push', 'voice']
|
|
|
|
def send_appointment_reminder(self, appointment):
|
|
"""Send smart reminders based on patient preference"""
|
|
patient_prefs = appointment.patient.notification_preferences
|
|
|
|
# Base reminder (48 hours before)
|
|
self._send_reminder(appointment, hours_before=48)
|
|
|
|
# Same-day confirmation (4 hours before)
|
|
self._send_reminder(appointment, hours_before=4)
|
|
|
|
def send_waitlist_opportunity(self, waitlist_entry, available_slot):
|
|
"""Notify patient of waitlist opportunity"""
|
|
context = {
|
|
'patient': waitlist_entry.patient,
|
|
'available_slot': available_slot,
|
|
'expiration_minutes': 30 # Quick response required
|
|
}
|
|
|
|
# Use preferred notification channel
|
|
if waitlist_entry.notify_by_sms:
|
|
self.send_sms(waitlist_entry.patient.phone, 'waitlist_opportunity', context)
|
|
```
|
|
|
|
2. User Workflows
|
|
|
|
2.1 Patient Self-Scheduling Workflow
|
|
|
|
```
|
|
1. Patient accesses portal → Authenticates (OAuth2/OIDC)
|
|
2. Selects appointment type and preferred provider/dates
|
|
3. System shows available slots with intelligent recommendations
|
|
4. Patient selects slot → System checks insurance eligibility
|
|
5. Patient completes booking → Automated reminders scheduled
|
|
6. System suggests waitlist option if no preferred slots available
|
|
```
|
|
|
|
2.2 Clinic Queue Management Workflow
|
|
|
|
```
|
|
1. Patient checks in at kiosk/mobile → Appointment status updates
|
|
2. System automatically places patient in appropriate queue
|
|
3. Real-time wait time estimates calculated and displayed
|
|
4. Staff dashboard shows queue status with patient priorities
|
|
5. Provider marks patient as "in progress" → Next patient alerted
|
|
6. Completion triggers automated follow-up tasks
|
|
```
|
|
|
|
2.3 Waitlist Automation Workflow
|
|
|
|
```
|
|
1. Cancellation occurs → System immediately scans waitlist
|
|
2. Matching algorithm finds suitable waitlist patients
|
|
3. Automated notifications sent via preferred channels
|
|
4. First patient to respond gets the slot
|
|
5. System updates all related records automatically
|
|
6. Unfilled slots trigger secondary notification rounds
|
|
```
|
|
|
|
3. Integration Specifications
|
|
|
|
3.1 EHR Integration Layer
|
|
|
|
```python
|
|
# integrations/ehr/base.py
|
|
class EHRIntegrationBase:
|
|
def sync_patient_data(self, patient_id):
|
|
"""Two-way sync with EHR system"""
|
|
pass
|
|
|
|
def push_appointment_to_ehr(self, appointment):
|
|
"""Ensure EHR system has latest appointment data"""
|
|
pass
|
|
|
|
def pull_schedule_changes(self, provider, date_range):
|
|
"""Sync schedule changes from EHR"""
|
|
pass
|
|
```
|
|
|
|
3.2 Insurance Verification Integration
|
|
|
|
```python
|
|
# integrations/insurance/verification.py
|
|
class InsuranceVerification:
|
|
def verify_eligibility(self, patient, appointment_type):
|
|
"""Real-time insurance eligibility check"""
|
|
# Integration with insurance clearinghouses
|
|
pass
|
|
|
|
def estimate_co-pay(self, patient, services):
|
|
"""Provide cost estimates to patients"""
|
|
pass
|
|
``` |