""" Forms for Appointments app CRUD operations. """ from django import forms from django.core.exceptions import ValidationError from django.utils import timezone from datetime import datetime, time, timedelta from .models import ( AppointmentRequest, SlotAvailability, WaitingQueue, QueueEntry, TelemedicineSession, AppointmentTemplate ) from patients.models import PatientProfile from accounts.models import User class AppointmentRequestForm(forms.ModelForm): """ Form for appointment request management. """ class Meta: model = AppointmentRequest fields = [ 'patient', 'provider', 'appointment_type', 'specialty', 'preferred_date', 'preferred_time', 'duration_minutes', 'priority', 'chief_complaint', 'clinical_notes', 'status', 'is_telemedicine', 'location', 'room_number' ] widgets = { 'patient': forms.Select(attrs={'class': 'form-select'}), 'provider': forms.Select(attrs={'class': 'form-select'}), 'appointment_type': forms.Select(attrs={'class': 'form-select'}), 'specialty': forms.Select(attrs={'class': 'form-select'}), 'preferred_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), 'preferred_time': forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}), 'duration_minutes': forms.NumberInput(attrs={'class': 'form-control', 'min': '15', 'step': '15'}), 'priority': forms.Select(attrs={'class': 'form-select'}), 'chief_complaint': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), 'clinical_notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), 'status': forms.Select(attrs={'class': 'form-select'}), 'is_telemedicine': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 'location': forms.TextInput(attrs={'class': 'form-control'}), 'room_number': forms.TextInput(attrs={'class': 'form-control'}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['patient'].queryset = PatientProfile.objects.filter( tenant=user.tenant, is_active=True ).order_by('last_name', 'first_name') self.fields['provider'].queryset = User.objects.filter( tenant=user.tenant, is_active=True, role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT'] ).order_by('last_name', 'first_name') def clean_preferred_date(self): preferred_date = self.cleaned_data.get('preferred_date') if preferred_date and preferred_date < timezone.now().date(): raise ValidationError('Appointment cannot be scheduled in the past.') return preferred_date def clean_duration_minutes(self): duration = self.cleaned_data.get('duration_minutes') if duration and duration < 15: raise ValidationError('Appointment duration must be at least 15 minutes.') if duration and duration > 480: # 8 hours raise ValidationError('Appointment duration cannot exceed 8 hours.') return duration class SlotAvailabilityForm(forms.ModelForm): """ Form for slot availability management. """ class Meta: model = SlotAvailability fields = [ 'provider', 'date', 'start_time', 'end_time', 'duration_minutes', 'max_appointments', 'location', 'room_number', 'specialty', 'availability_type', 'is_active', 'supports_telemedicine' ] widgets = { 'provider': forms.Select(attrs={'class': 'form-select'}), 'date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), 'start_time': forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}), 'end_time': forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}), 'duration_minutes': forms.NumberInput(attrs={'class': 'form-control', 'min': '15', 'step': '15'}), 'max_appointments': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), 'location': forms.TextInput(attrs={'class': 'form-control'}), 'room_number': forms.TextInput(attrs={'class': 'form-control'}), 'specialty': forms.TextInput(attrs={'class': 'form-control'}), 'availability_type': forms.Select(attrs={'class': 'form-select'}), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 'supports_telemedicine': forms.CheckboxInput(attrs={'class': 'form-check-input'}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['provider'].queryset = User.objects.filter( tenant=user.tenant, is_active=True, role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT'] ).order_by('last_name', 'first_name') def clean(self): cleaned_data = super().clean() date = cleaned_data.get('date') start_time = cleaned_data.get('start_time') end_time = cleaned_data.get('end_time') if date and date < timezone.now().date(): raise ValidationError('Availability date cannot be in the past.') if start_time and end_time and start_time >= end_time: raise ValidationError('Start time must be before end time.') return cleaned_data class WaitingQueueForm(forms.ModelForm): """ Form for waiting queue management. """ class Meta: model = WaitingQueue fields = [ 'name', 'description', 'queue_type', 'location', 'specialty', 'max_queue_size', 'average_service_time_minutes', 'is_active' ] widgets = { 'name': forms.TextInput(attrs={'class': 'form-control'}), 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), 'queue_type': forms.Select(attrs={'class': 'form-select'}), 'location': forms.TextInput(attrs={'class': 'form-control'}), 'specialty': forms.TextInput(attrs={'class': 'form-control'}), 'max_queue_size': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), 'average_service_time_minutes': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['provider'].queryset = User.objects.filter( tenant=user.tenant, is_active=True, role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT'] ).order_by('last_name', 'first_name') class QueueEntryForm(forms.ModelForm): """ Form for queue entry management. """ class Meta: model = QueueEntry fields = [ 'queue', 'patient', 'appointment', 'priority_score', 'assigned_provider', 'status', 'notes' ] widgets = { 'queue': forms.Select(attrs={'class': 'form-select'}), 'patient': forms.Select(attrs={'class': 'form-select'}), 'appointment': forms.Select(attrs={'class': 'form-select'}), 'priority_score': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.1', 'min': '0'}), 'assigned_provider': forms.Select(attrs={'class': 'form-select'}), 'status': forms.Select(attrs={'class': 'form-select'}), 'notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['queue'].queryset = WaitingQueue.objects.filter( tenant=user.tenant, is_active=True ).order_by('name') self.fields['patient'].queryset = PatientProfile.objects.filter( tenant=user.tenant, is_active=True ).order_by('last_name', 'first_name') self.fields['appointment'].queryset = AppointmentRequest.objects.filter( tenant=user.tenant, status__in=['SCHEDULED', 'CONFIRMED'] ).order_by('-preferred_date') class TelemedicineSessionForm(forms.ModelForm): """ Form for telemedicine session management. """ class Meta: model = TelemedicineSession fields = [ 'appointment', 'platform', 'meeting_url', 'meeting_id', 'meeting_password', 'scheduled_start', 'scheduled_end', 'status', 'waiting_room_enabled', 'recording_enabled', 'recording_consent' ] widgets = { 'appointment': forms.Select(attrs={'class': 'form-select'}), 'platform': forms.Select(attrs={'class': 'form-select'}), 'meeting_url': forms.URLInput(attrs={'class': 'form-control'}), 'meeting_id': forms.TextInput(attrs={'class': 'form-control'}), 'meeting_password': forms.PasswordInput(attrs={'class': 'form-control'}), 'scheduled_start': forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}), 'scheduled_end': forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}), 'status': forms.Select(attrs={'class': 'form-select'}), 'waiting_room_enabled': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 'recording_enabled': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 'recording_consent': forms.CheckboxInput(attrs={'class': 'form-check-input'}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['appointment'].queryset = AppointmentRequest.objects.filter( tenant=user.tenant, is_telemedicine=True, status__in=['SCHEDULED', 'CONFIRMED', 'IN_PROGRESS'] ).order_by('-preferred_date') def clean(self): cleaned_data = super().clean() start_time = cleaned_data.get('session_start_time') end_time = cleaned_data.get('session_end_time') if start_time and end_time and start_time >= end_time: raise ValidationError('Start time must be before end time.') return cleaned_data class AppointmentTemplateForm(forms.ModelForm): """ Form for appointment template management. """ class Meta: model = AppointmentTemplate fields = [ 'name', 'description', 'appointment_type', 'duration_minutes', 'specialty', 'advance_booking_days', 'minimum_notice_hours', 'pre_appointment_instructions', 'post_appointment_instructions', 'is_active' ] widgets = { 'name': forms.TextInput(attrs={'class': 'form-control'}), 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), 'appointment_type': forms.TextInput(attrs={'class': 'form-control'}), 'duration_minutes': forms.NumberInput(attrs={'class': 'form-control', 'min': '15', 'step': '15'}), 'specialty': forms.TextInput(attrs={'class': 'form-control'}), 'advance_booking_days': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), 'minimum_notice_hours': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), 'pre_appointment_instructions': forms.Textarea(attrs={'class': 'form-control', 'rows': 4}), 'post_appointment_instructions': forms.Textarea(attrs={'class': 'form-control', 'rows': 4}), 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['provider'].queryset = User.objects.filter( tenant=user.tenant, is_active=True, role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT'] ).order_by('last_name', 'first_name') class AppointmentSearchForm(forms.Form): """ Form for searching appointment data. """ search = forms.CharField( max_length=255, required=False, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Search appointments, patients, providers...' }) ) appointment_type = forms.ChoiceField( choices=[('', 'All Types')] + list(AppointmentRequest._meta.get_field('appointment_type').choices), required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) status = forms.ChoiceField( choices=[('', 'All Status')] + list(AppointmentRequest._meta.get_field('status').choices), required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) priority = forms.ChoiceField( choices=[('', 'All Priorities')] + list(AppointmentRequest._meta.get_field('priority').choices), required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) provider = forms.ModelChoiceField( queryset=User.objects.none(), required=False, empty_label='All Providers', widget=forms.Select(attrs={'class': 'form-select'}) ) specialty = forms.CharField( max_length=100, required=False, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Specialty' }) ) date_from = forms.DateField( required=False, widget=forms.DateInput(attrs={ 'class': 'form-control', 'type': 'date' }) ) date_to = forms.DateField( required=False, widget=forms.DateInput(attrs={ 'class': 'form-control', 'type': 'date' }) ) is_telemedicine = forms.ChoiceField( choices=[ ('', 'All Appointments'), ('true', 'Telemedicine Only'), ('false', 'In-Person Only') ], required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['provider'].queryset = User.objects.filter( tenant=user.tenant, is_active=True, role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT'] ).order_by('last_name', 'first_name') class QueueSearchForm(forms.Form): """ Form for searching queues. """ search = forms.CharField( max_length=200, required=False, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Search queues...' }) ) queue_type = forms.ChoiceField( choices=[('', 'All Types')] + [ ('PROVIDER', 'Provider Queue'), ('SPECIALTY', 'Specialty Queue'), ('LOCATION', 'Location Queue'), ('PROCEDURE', 'Procedure Queue'), ('EMERGENCY', 'Emergency Queue'), ], required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) is_active = forms.ChoiceField( choices=[('', 'All'), ('true', 'Active'), ('false', 'Inactive')], required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) class SlotSearchForm(forms.Form): """ Form for searching appointment slots. """ search = forms.CharField( max_length=200, required=False, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Search slots...' }) ) provider = forms.ModelChoiceField( queryset=User.objects.none(), required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) date_from = forms.DateField( required=False, widget=forms.DateInput(attrs={ 'class': 'form-control', 'type': 'date' }) ) date_to = forms.DateField( required=False, widget=forms.DateInput(attrs={ 'class': 'form-control', 'type': 'date' }) ) is_available = forms.ChoiceField( choices=[('', 'All'), ('true', 'Available'), ('false', 'Booked')], required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user: self.fields['provider'].queryset = User.objects.filter( tenant=user.tenant, role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT'] ).order_by('last_name', 'first_name') # from django import forms # from django.core.exceptions import ValidationError # from django.utils import timezone # from django.contrib.auth.models import User # from crispy_forms.helper import FormHelper # from crispy_forms.layout import Layout, Fieldset, Submit, Row, Column, HTML, Div # from crispy_forms.bootstrap import FormActions # from datetime import datetime, timedelta # # from .models import Appointment, AppointmentConfirmation, Queue, TelemedicineSession # from patients.models import Patient # from core.models import Department # # # class AppointmentSchedulingForm(forms.ModelForm): # """ # Form for appointment scheduling # """ # patient_search = forms.CharField( # required=False, # widget=forms.TextInput(attrs={ # 'class': 'form-control', # 'placeholder': 'Search patient by name, ID, or phone...', # 'data-toggle': 'patient-search' # }) # ) # preferred_time_1 = forms.TimeField( # required=False, # widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) # ) # preferred_time_2 = forms.TimeField( # required=False, # widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) # ) # preferred_time_3 = forms.TimeField( # required=False, # widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) # ) # special_instructions = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # ) # send_confirmation = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # send_reminder = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # class Meta: # model = Appointment # fields = [ # 'patient', 'provider', 'department', 'appointment_type', # 'appointment_date', 'appointment_time', 'duration', # 'urgency', 'reason', 'notes', 'special_instructions', # 'send_confirmation', 'send_reminder' # ] # widgets = { # 'patient': forms.Select(attrs={'class': 'form-control'}), # 'provider': forms.Select(attrs={'class': 'form-control'}), # 'department': forms.Select(attrs={'class': 'form-control'}), # 'appointment_type': forms.Select(attrs={'class': 'form-control'}), # 'appointment_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), # 'appointment_time': forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}), # 'duration': forms.NumberInput(attrs={'class': 'form-control'}), # 'urgency': forms.Select(attrs={'class': 'form-control'}), # 'reason': forms.TextInput(attrs={'class': 'form-control'}), # 'notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # } # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # if tenant: # self.fields['patient'].queryset = Patient.objects.filter(tenant=tenant) # self.fields['provider'].queryset = User.objects.filter( # tenant=tenant, # groups__name__in=['Doctors', 'Nurses', 'Specialists'] # ) # self.fields['department'].queryset = Department.objects.filter(tenant=tenant) # # # Set minimum date to today # self.fields['appointment_date'].widget.attrs['min'] = timezone.now().date().isoformat() # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Patient Information', # 'patient_search', # 'patient' # ), # Fieldset( # 'Appointment Details', # Row( # Column('provider', css_class='form-group col-md-6 mb-0'), # Column('department', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # Row( # Column('appointment_type', css_class='form-group col-md-6 mb-0'), # Column('urgency', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # Row( # Column('appointment_date', css_class='form-group col-md-4 mb-0'), # Column('appointment_time', css_class='form-group col-md-4 mb-0'), # Column('duration', css_class='form-group col-md-4 mb-0'), # css_class='form-row' # ), # 'reason', # 'notes', # 'special_instructions' # ), # Fieldset( # 'Preferred Times (Alternative Options)', # Row( # Column('preferred_time_1', css_class='form-group col-md-4 mb-0'), # Column('preferred_time_2', css_class='form-group col-md-4 mb-0'), # Column('preferred_time_3', css_class='form-group col-md-4 mb-0'), # css_class='form-row' # ) # ), # Fieldset( # 'Notifications', # HTML('
'), # 'send_confirmation', # HTML( # ''), # HTML('
'), # HTML('
'), # 'send_reminder', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Schedule Appointment', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # def clean(self): # cleaned_data = super().clean() # appointment_date = cleaned_data.get('appointment_date') # appointment_time = cleaned_data.get('appointment_time') # provider = cleaned_data.get('provider') # # if appointment_date and appointment_time: # appointment_datetime = datetime.combine(appointment_date, appointment_time) # # # Check if appointment is in the past # if appointment_datetime < timezone.now(): # raise ValidationError('Appointment cannot be scheduled in the past.') # # # Check provider availability # if provider and self.check_provider_conflict(provider, appointment_datetime): # raise ValidationError('Provider is not available at the selected time.') # # return cleaned_data # # def check_provider_conflict(self, provider, appointment_datetime): # """Check if provider has conflicting appointments""" # duration = self.cleaned_data.get('duration', 30) # end_time = appointment_datetime + timedelta(minutes=duration) # # conflicts = Appointment.objects.filter( # provider=provider, # appointment_date=appointment_datetime.date(), # status__in=['scheduled', 'confirmed', 'in_progress'] # ).exclude(id=self.instance.id if self.instance else None) # # for conflict in conflicts: # conflict_start = datetime.combine(conflict.appointment_date, conflict.appointment_time) # conflict_end = conflict_start + timedelta(minutes=conflict.duration) # # if (appointment_datetime < conflict_end and end_time > conflict_start): # return True # # return False # # # class AppointmentConfirmationForm(forms.ModelForm): # """ # Form for appointment confirmation # """ # confirmation_method = forms.ChoiceField( # choices=[ # ('phone', 'Phone Call'), # ('email', 'Email'), # ('sms', 'SMS'), # ('in_person', 'In Person'), # ('online', 'Online Portal') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # contact_attempts = forms.IntegerField( # initial=1, # min_value=1, # max_value=5, # widget=forms.NumberInput(attrs={'class': 'form-control'}) # ) # confirmation_notes = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # ) # reschedule_requested = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # new_preferred_date = forms.DateField( # required=False, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # new_preferred_time = forms.TimeField( # required=False, # widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) # ) # # class Meta: # model = AppointmentConfirmation # fields = [ # 'confirmation_method', 'contact_attempts', 'confirmation_notes', # 'reschedule_requested', 'new_preferred_date', 'new_preferred_time' # ] # # def __init__(self, *args, **kwargs): # appointment = kwargs.pop('appointment', None) # super().__init__(*args, **kwargs) # # self.appointment = appointment # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Confirmation Details', # Row( # Column('confirmation_method', css_class='form-group col-md-6 mb-0'), # Column('contact_attempts', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'confirmation_notes' # ), # Fieldset( # 'Reschedule Request', # HTML('
'), # 'reschedule_requested', # HTML( # ''), # HTML('
'), # Row( # Column('new_preferred_date', css_class='form-group col-md-6 mb-0'), # Column('new_preferred_time', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # FormActions( # Submit('submit', 'Confirm Appointment', css_class='btn btn-primary'), # HTML( # 'Cancel') # ) # ) # # def clean(self): # cleaned_data = super().clean() # reschedule_requested = cleaned_data.get('reschedule_requested') # new_preferred_date = cleaned_data.get('new_preferred_date') # new_preferred_time = cleaned_data.get('new_preferred_time') # # if reschedule_requested: # if not new_preferred_date: # raise ValidationError('New preferred date is required when reschedule is requested.') # if not new_preferred_time: # raise ValidationError('New preferred time is required when reschedule is requested.') # # return cleaned_data # # # class QueueManagementForm(forms.ModelForm): # """ # Form for queue management # """ # estimated_wait_time = forms.IntegerField( # required=False, # widget=forms.NumberInput(attrs={'class': 'form-control'}) # ) # priority_adjustment = forms.ChoiceField( # choices=[ # ('none', 'No Change'), # ('increase', 'Increase Priority'), # ('decrease', 'Decrease Priority') # ], # required=False, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # queue_notes = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # ) # notify_patient = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # class Meta: # model = Queue # fields = [ # 'queue_type', 'priority', 'estimated_wait_time', # 'priority_adjustment', 'queue_notes', 'notify_patient' # ] # widgets = { # 'queue_type': forms.Select(attrs={'class': 'form-control'}), # 'priority': forms.Select(attrs={'class': 'form-control'}) # } # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Queue Configuration', # Row( # Column('queue_type', css_class='form-group col-md-6 mb-0'), # Column('priority', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # Row( # Column('estimated_wait_time', css_class='form-group col-md-6 mb-0'), # Column('priority_adjustment', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'queue_notes' # ), # Fieldset( # 'Notifications', # HTML('
'), # 'notify_patient', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Update Queue', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class TelemedicineSetupForm(forms.ModelForm): # """ # Form for telemedicine session setup # """ # platform = forms.ChoiceField( # choices=[ # ('zoom', 'Zoom'), # ('teams', 'Microsoft Teams'), # ('webex', 'Cisco Webex'), # ('meet', 'Google Meet'), # ('custom', 'Custom Platform') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # test_connection = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # send_instructions = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # backup_phone = forms.CharField( # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # technical_support_contact = forms.CharField( # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # session_recording = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # class Meta: # model = TelemedicineSession # fields = [ # 'platform', 'meeting_url', 'meeting_id', 'meeting_password', # 'test_connection', 'send_instructions', 'backup_phone', # 'technical_support_contact', 'session_recording' # ] # widgets = { # 'meeting_url': forms.URLInput(attrs={'class': 'form-control'}), # 'meeting_id': forms.TextInput(attrs={'class': 'form-control'}), # 'meeting_password': forms.TextInput(attrs={'class': 'form-control'}) # } # # def __init__(self, *args, **kwargs): # appointment = kwargs.pop('appointment', None) # super().__init__(*args, **kwargs) # # self.appointment = appointment # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Platform Configuration', # 'platform', # 'meeting_url', # Row( # Column('meeting_id', css_class='form-group col-md-6 mb-0'), # Column('meeting_password', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # Fieldset( # 'Support Information', # Row( # Column('backup_phone', css_class='form-group col-md-6 mb-0'), # Column('technical_support_contact', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # Fieldset( # 'Session Options', # HTML('
'), # 'test_connection', # HTML( # ''), # HTML('
'), # HTML('
'), # 'send_instructions', # HTML( # ''), # HTML('
'), # HTML('
'), # 'session_recording', # HTML( # ''), # HTML('
') # ), # FormActions( # Submit('submit', 'Setup Telemedicine', css_class='btn btn-primary'), # HTML( # 'Cancel') # ) # ) # # def clean_meeting_url(self): # meeting_url = self.cleaned_data.get('meeting_url') # platform = self.cleaned_data.get('platform') # # if platform and meeting_url: # # Validate URL format based on platform # if platform == 'zoom' and 'zoom.us' not in meeting_url: # raise ValidationError('Invalid Zoom meeting URL format.') # elif platform == 'teams' and 'teams.microsoft.com' not in meeting_url: # raise ValidationError('Invalid Microsoft Teams meeting URL format.') # elif platform == 'webex' and 'webex.com' not in meeting_url: # raise ValidationError('Invalid Webex meeting URL format.') # elif platform == 'meet' and 'meet.google.com' not in meeting_url: # raise ValidationError('Invalid Google Meet URL format.') # # return meeting_url # # # class AppointmentRescheduleForm(forms.Form): # """ # Form for appointment rescheduling # """ # new_date = forms.DateField( # required=True, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # new_time = forms.TimeField( # required=True, # widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) # ) # new_provider = forms.ModelChoiceField( # queryset=None, # required=False, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # reschedule_reason = forms.ChoiceField( # choices=[ # ('patient_request', 'Patient Request'), # ('provider_unavailable', 'Provider Unavailable'), # ('emergency', 'Emergency'), # ('equipment_issue', 'Equipment Issue'), # ('other', 'Other') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # notes = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # ) # notify_patient = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # appointment = kwargs.pop('appointment', None) # super().__init__(*args, **kwargs) # # if tenant: # self.fields['new_provider'].queryset = User.objects.filter( # tenant=tenant, # groups__name__in=['Doctors', 'Nurses', 'Specialists'] # ) # # # Set minimum date to today # self.fields['new_date'].widget.attrs['min'] = timezone.now().date().isoformat() # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'New Appointment Details', # Row( # Column('new_date', css_class='form-group col-md-6 mb-0'), # Column('new_time', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'new_provider' # ), # Fieldset( # 'Reschedule Information', # 'reschedule_reason', # 'notes' # ), # Fieldset( # 'Notifications', # HTML('
'), # 'notify_patient', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Reschedule Appointment', css_class='btn btn-primary'), # HTML( # 'Cancel') # ) # ) # # # class AppointmentCancellationForm(forms.Form): # """ # Form for appointment cancellation # """ # cancellation_reason = forms.ChoiceField( # choices=[ # ('patient_request', 'Patient Request'), # ('provider_unavailable', 'Provider Unavailable'), # ('patient_no_show', 'Patient No Show'), # ('emergency', 'Emergency'), # ('equipment_failure', 'Equipment Failure'), # ('other', 'Other') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # cancellation_notes = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # ) # offer_reschedule = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # notify_patient = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # refund_required = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Cancellation Details', # 'cancellation_reason', # 'cancellation_notes' # ), # Fieldset( # 'Follow-up Actions', # HTML('
'), # 'offer_reschedule', # HTML( # ''), # HTML('
'), # HTML('
'), # 'notify_patient', # HTML(''), # HTML('
'), # HTML('
'), # 'refund_required', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Cancel Appointment', css_class='btn btn-danger'), # HTML( # 'Back') # ) # ) # # # class AppointmentCheckInForm(forms.Form): # """ # Form for appointment check-in # """ # arrival_time = forms.TimeField( # initial=timezone.now().time(), # widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) # ) # insurance_verified = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # copay_collected = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # forms_completed = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # vitals_required = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # special_needs = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 2}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Check-in Information', # 'arrival_time', # 'special_needs' # ), # Fieldset( # 'Pre-visit Tasks', # HTML('
'), # 'insurance_verified', # HTML(''), # HTML('
'), # HTML('
'), # 'copay_collected', # HTML(''), # HTML('
'), # HTML('
'), # 'forms_completed', # HTML(''), # HTML('
'), # HTML('
'), # 'vitals_required', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Check In Patient', css_class='btn btn-primary'), # HTML( # 'Cancel') # ) # ) # # # class BulkAppointmentForm(forms.Form): # """ # Form for bulk appointment operations # """ # action = forms.ChoiceField( # choices=[ # ('confirm', 'Confirm Appointments'), # ('reschedule', 'Reschedule Appointments'), # ('cancel', 'Cancel Appointments'), # ('send_reminders', 'Send Reminders') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # appointment_ids = forms.CharField( # widget=forms.HiddenInput() # ) # bulk_date = forms.DateField( # required=False, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # bulk_reason = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) # ) # notify_patients = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # 'appointment_ids', # Fieldset( # 'Bulk Operation', # 'action', # 'bulk_date', # 'bulk_reason' # ), # Fieldset( # 'Notifications', # HTML('
'), # 'notify_patients', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Execute Bulk Operation', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) #