640 lines
23 KiB
Python
640 lines
23 KiB
Python
"""
|
|
Appointments forms for the Tenhal Multidisciplinary Healthcare Platform.
|
|
|
|
This module contains forms for appointment booking, confirmation, rescheduling, etc.
|
|
"""
|
|
|
|
from django import forms
|
|
from django.utils.translation import gettext_lazy as _
|
|
from crispy_forms.helper import FormHelper
|
|
from crispy_forms.layout import Layout, Fieldset, Row, Column, Submit, HTML
|
|
|
|
from .models import Appointment, Provider, Room, Schedule
|
|
|
|
|
|
class AppointmentBookingForm(forms.ModelForm):
|
|
"""
|
|
Form for booking new appointments.
|
|
"""
|
|
|
|
# Define common service types
|
|
SERVICE_TYPE_CHOICES = [
|
|
('', _('Select a service type')),
|
|
('consultation', _('Consultation')),
|
|
('follow_up', _('Follow-up Visit')),
|
|
('assessment', _('Assessment')),
|
|
('therapy_session', _('Therapy Session')),
|
|
('evaluation', _('Evaluation')),
|
|
('intervention', _('Intervention')),
|
|
('screening', _('Screening')),
|
|
('parent_training', _('Parent Training')),
|
|
('group_session', _('Group Session')),
|
|
('other', _('Other')),
|
|
]
|
|
|
|
# Appointment type selection
|
|
APPOINTMENT_TYPE_CHOICES = [
|
|
('single', _('Single Session')),
|
|
('package', _('Use Package')),
|
|
]
|
|
|
|
appointment_type = forms.ChoiceField(
|
|
choices=APPOINTMENT_TYPE_CHOICES,
|
|
widget=forms.RadioSelect(attrs={'class': 'form-check-input'}),
|
|
label=_('Appointment Type'),
|
|
initial='single',
|
|
required=False
|
|
)
|
|
|
|
# Package selection (shown when appointment_type = 'package')
|
|
package_purchase = forms.ModelChoiceField(
|
|
queryset=None, # Will be set in __init__
|
|
required=False,
|
|
label=_('Select Package'),
|
|
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select a package'}),
|
|
help_text=_('Select an active package with remaining sessions')
|
|
)
|
|
|
|
service_type = forms.ChoiceField(
|
|
choices=SERVICE_TYPE_CHOICES,
|
|
widget=forms.Select(attrs={'class': 'form-control'}),
|
|
label=_('Service Type')
|
|
)
|
|
|
|
class Meta:
|
|
model = Appointment
|
|
fields = [
|
|
'patient', 'clinic', 'provider', 'room',
|
|
'service_type', 'scheduled_date', 'scheduled_time', 'duration',
|
|
'finance_cleared', 'consent_verified',
|
|
'notes',
|
|
]
|
|
widgets = {
|
|
'patient': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select patient'}),
|
|
'clinic': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'}),
|
|
'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}),
|
|
'room': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select room'}),
|
|
'scheduled_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
|
'scheduled_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),
|
|
'duration': forms.NumberInput(attrs={'class': 'form-control', 'min': '15', 'step': '15'}),
|
|
'finance_cleared': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
|
'consent_verified': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
|
'notes': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
patient = kwargs.pop('patient', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Initialize package_purchase queryset (empty by default)
|
|
from finance.models import PackagePurchase
|
|
self.fields['package_purchase'].queryset = PackagePurchase.objects.none()
|
|
|
|
# Load available packages for patient if provided
|
|
if patient:
|
|
from .package_integration_service import PackageIntegrationService
|
|
self.fields['package_purchase'].queryset = \
|
|
PackageIntegrationService.get_available_packages_for_patient(patient)
|
|
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
Fieldset(
|
|
_('Appointment Type'),
|
|
'appointment_type',
|
|
),
|
|
Fieldset(
|
|
_('Package Selection'),
|
|
'package_purchase',
|
|
css_id='packageSection',
|
|
css_class='d-none'
|
|
),
|
|
Fieldset(
|
|
_('Appointment Details'),
|
|
'patient',
|
|
Row(
|
|
Column('clinic', css_class='form-group col-md-6 mb-0'),
|
|
Column('provider', css_class='form-group col-md-6 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
Row(
|
|
Column('service_type', css_class='form-group col-md-6 mb-0'),
|
|
Column('room', css_class='form-group col-md-6 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
Row(
|
|
Column('scheduled_date', css_class='form-group col-md-4 mb-0'),
|
|
Column('scheduled_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'
|
|
),
|
|
'notes',
|
|
),
|
|
Submit('submit', _('Book Appointment'), css_class='btn btn-primary')
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
provider = cleaned_data.get('provider')
|
|
clinic = cleaned_data.get('clinic')
|
|
|
|
# Validate provider belongs to clinic
|
|
if provider and clinic:
|
|
if not provider.specialties.filter(id=clinic.id).exists():
|
|
raise forms.ValidationError(
|
|
_('Selected provider does not work in this clinic.')
|
|
)
|
|
|
|
return cleaned_data
|
|
|
|
|
|
class AppointmentConfirmForm(forms.Form):
|
|
"""
|
|
Form for confirming appointments.
|
|
"""
|
|
|
|
confirmation_method = forms.ChoiceField(
|
|
label=_('Confirmation Method'),
|
|
choices=Appointment.ConfirmationMethod.choices,
|
|
widget=forms.RadioSelect(attrs={'class': 'form-check-input'})
|
|
)
|
|
notes = forms.CharField(
|
|
required=False,
|
|
label=_('Notes'),
|
|
widget=forms.Textarea(attrs={'rows': 2, 'class': 'form-control'})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
'confirmation_method',
|
|
'notes',
|
|
Submit('submit', _('Confirm Appointment'), css_class='btn btn-success')
|
|
)
|
|
|
|
|
|
class AppointmentRescheduleForm(forms.ModelForm):
|
|
"""
|
|
Form for rescheduling appointments.
|
|
"""
|
|
|
|
reschedule_reason = forms.CharField(
|
|
label=_('Reason for Rescheduling'),
|
|
widget=forms.Textarea(attrs={'rows': 3, 'class': 'form-control'})
|
|
)
|
|
|
|
class Meta:
|
|
model = Appointment
|
|
fields = ['scheduled_date', 'scheduled_time', 'reschedule_reason']
|
|
widgets = {
|
|
'scheduled_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
|
'scheduled_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),
|
|
}
|
|
labels = {
|
|
'scheduled_date': _('New Date'),
|
|
'scheduled_time': _('New Time'),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
Row(
|
|
Column('scheduled_date', css_class='form-group col-md-6 mb-0'),
|
|
Column('scheduled_time', css_class='form-group col-md-6 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
'reschedule_reason',
|
|
Submit('submit', _('Reschedule'), css_class='btn btn-warning')
|
|
)
|
|
|
|
|
|
class AppointmentCancelForm(forms.Form):
|
|
"""
|
|
Form for cancelling appointments.
|
|
"""
|
|
|
|
cancel_reason = forms.CharField(
|
|
label=_('Reason for Cancellation'),
|
|
widget=forms.Textarea(attrs={'rows': 3, 'class': 'form-control'})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
'cancel_reason',
|
|
Submit('submit', _('Cancel Appointment'), css_class='btn btn-danger')
|
|
)
|
|
|
|
|
|
class AppointmentArrivalForm(forms.Form):
|
|
"""
|
|
Form for marking patient arrival.
|
|
"""
|
|
|
|
notes = forms.CharField(
|
|
required=False,
|
|
label=_('Notes'),
|
|
widget=forms.Textarea(attrs={'rows': 2, 'class': 'form-control'})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
'notes',
|
|
Submit('submit', _('Mark as Arrived'), css_class='btn btn-info')
|
|
)
|
|
|
|
|
|
class AppointmentSearchForm(forms.Form):
|
|
"""
|
|
Form for searching appointments.
|
|
"""
|
|
|
|
search_query = forms.CharField(
|
|
required=False,
|
|
label=_('Search'),
|
|
widget=forms.TextInput(attrs={
|
|
'placeholder': _('Patient name, MRN, Appointment #...'),
|
|
'class': 'form-control'
|
|
})
|
|
)
|
|
clinic = forms.ModelChoiceField(
|
|
required=False,
|
|
label=_('Clinic'),
|
|
queryset=None, # Will be set in __init__
|
|
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'})
|
|
)
|
|
provider = forms.ModelChoiceField(
|
|
required=False,
|
|
label=_('Provider'),
|
|
queryset=None, # Will be set in __init__
|
|
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'})
|
|
)
|
|
status = forms.ChoiceField(
|
|
required=False,
|
|
label=_('Status'),
|
|
choices=[('', _('All'))] + list(Appointment.Status.choices),
|
|
widget=forms.Select(attrs={'class': 'form-control'})
|
|
)
|
|
date_from = forms.DateField(
|
|
required=False,
|
|
label=_('From Date'),
|
|
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'})
|
|
)
|
|
date_to = forms.DateField(
|
|
required=False,
|
|
label=_('To Date'),
|
|
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
tenant = kwargs.pop('tenant', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if tenant:
|
|
from core.models import Clinic
|
|
self.fields['clinic'].queryset = Clinic.objects.filter(tenant=tenant, is_active=True)
|
|
self.fields['provider'].queryset = Provider.objects.filter(tenant=tenant, is_available=True)
|
|
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'get'
|
|
self.helper.layout = Layout(
|
|
Row(
|
|
Column('search_query', css_class='form-group col-md-3 mb-0'),
|
|
Column('clinic', css_class='form-group col-md-2 mb-0'),
|
|
Column('provider', css_class='form-group col-md-2 mb-0'),
|
|
Column('status', css_class='form-group col-md-2 mb-0'),
|
|
Column('date_from', css_class='form-group col-md-1.5 mb-0'),
|
|
Column('date_to', css_class='form-group col-md-1.5 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
Submit('search', _('Search'), css_class='btn btn-primary')
|
|
)
|
|
|
|
|
|
class ProviderScheduleForm(forms.ModelForm):
|
|
"""
|
|
Form for managing provider schedules.
|
|
"""
|
|
|
|
class Meta:
|
|
model = Schedule
|
|
fields = ['provider', 'day_of_week', 'start_time', 'end_time', 'slot_duration', 'is_active']
|
|
widgets = {
|
|
'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}),
|
|
'day_of_week': forms.Select(attrs={'class': 'form-control'}),
|
|
'start_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),
|
|
'end_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),
|
|
'slot_duration': forms.NumberInput(attrs={'class': 'form-control', 'min': '15', 'step': '15'}),
|
|
'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
'provider',
|
|
Row(
|
|
Column('day_of_week', css_class='form-group col-md-4 mb-0'),
|
|
Column('start_time', css_class='form-group col-md-3 mb-0'),
|
|
Column('end_time', css_class='form-group col-md-3 mb-0'),
|
|
Column('slot_duration', css_class='form-group col-md-2 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
'is_active',
|
|
Submit('submit', _('Save Schedule'), css_class='btn btn-primary')
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
start_time = cleaned_data.get('start_time')
|
|
end_time = cleaned_data.get('end_time')
|
|
|
|
if start_time and end_time and start_time >= end_time:
|
|
raise forms.ValidationError(_('End time must be after start time.'))
|
|
|
|
return cleaned_data
|
|
|
|
|
|
# Alias for backward compatibility with views
|
|
AppointmentForm = AppointmentBookingForm
|
|
RescheduleForm = AppointmentRescheduleForm
|
|
|
|
|
|
# ============================================================================
|
|
# Session Forms (Group Session Support)
|
|
# ============================================================================
|
|
|
|
|
|
class GroupSessionCreateForm(forms.ModelForm):
|
|
"""
|
|
Form for creating a new group session.
|
|
"""
|
|
|
|
SERVICE_TYPE_CHOICES = [
|
|
('', _('Select a service type')),
|
|
('group_therapy', _('Group Therapy')),
|
|
('group_assessment', _('Group Assessment')),
|
|
('parent_training', _('Parent Training Group')),
|
|
('social_skills', _('Social Skills Group')),
|
|
('behavior_management', _('Behavior Management Group')),
|
|
('other', _('Other')),
|
|
]
|
|
|
|
service_type = forms.ChoiceField(
|
|
choices=SERVICE_TYPE_CHOICES,
|
|
widget=forms.Select(attrs={'class': 'form-control'}),
|
|
label=_('Service Type')
|
|
)
|
|
|
|
class Meta:
|
|
from .models import Session
|
|
model = Session
|
|
fields = [
|
|
'provider', 'clinic', 'room', 'service_type',
|
|
'scheduled_date', 'scheduled_time', 'duration',
|
|
'max_capacity', 'group_notes'
|
|
]
|
|
widgets = {
|
|
'provider': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'}),
|
|
'clinic': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'}),
|
|
'room': forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select room'}),
|
|
'scheduled_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
|
'scheduled_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),
|
|
'duration': forms.NumberInput(attrs={'class': 'form-control', 'min': '15', 'step': '15', 'value': '60'}),
|
|
'max_capacity': forms.NumberInput(attrs={'class': 'form-control', 'min': '1', 'max': '20', 'value': '8'}),
|
|
'group_notes': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': 'Shared notes for the entire group session'}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
Fieldset(
|
|
_('Group Session Details'),
|
|
Row(
|
|
Column('provider', css_class='form-group col-md-6 mb-0'),
|
|
Column('clinic', css_class='form-group col-md-6 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
Row(
|
|
Column('service_type', css_class='form-group col-md-6 mb-0'),
|
|
Column('room', css_class='form-group col-md-6 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
Row(
|
|
Column('scheduled_date', css_class='form-group col-md-4 mb-0'),
|
|
Column('scheduled_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'
|
|
),
|
|
Row(
|
|
Column('max_capacity', css_class='form-group col-md-12 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
'group_notes',
|
|
),
|
|
Submit('submit', _('Create Group Session'), css_class='btn btn-primary')
|
|
)
|
|
|
|
def clean_max_capacity(self):
|
|
"""Validate capacity is between 1 and 20."""
|
|
capacity = self.cleaned_data.get('max_capacity')
|
|
if capacity and (capacity < 1 or capacity > 20):
|
|
raise forms.ValidationError(_('Capacity must be between 1 and 20 patients'))
|
|
return capacity
|
|
|
|
|
|
class AddPatientToSessionForm(forms.Form):
|
|
"""
|
|
Form for adding a patient to an existing session.
|
|
"""
|
|
|
|
patient = forms.ModelChoiceField(
|
|
queryset=None, # Will be set in __init__
|
|
label=_('Patient'),
|
|
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select patient'})
|
|
)
|
|
|
|
individual_notes = forms.CharField(
|
|
required=False,
|
|
label=_('Individual Notes'),
|
|
widget=forms.Textarea(attrs={'rows': 2, 'class': 'form-control', 'placeholder': 'Notes specific to this patient'})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
tenant = kwargs.pop('tenant', None)
|
|
session = kwargs.pop('session', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if tenant:
|
|
from core.models import Patient
|
|
# Get patients not already in this session
|
|
queryset = Patient.objects.filter(tenant=tenant, is_active=True)
|
|
if session:
|
|
# Exclude patients already enrolled
|
|
enrolled_patient_ids = session.participants.filter(
|
|
status__in=['BOOKED', 'CONFIRMED', 'ARRIVED', 'ATTENDED']
|
|
).values_list('patient_id', flat=True)
|
|
queryset = queryset.exclude(id__in=enrolled_patient_ids)
|
|
|
|
self.fields['patient'].queryset = queryset
|
|
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
'patient',
|
|
'individual_notes',
|
|
Submit('submit', _('Add Patient to Session'), css_class='btn btn-success')
|
|
)
|
|
|
|
|
|
class SessionParticipantStatusForm(forms.Form):
|
|
"""
|
|
Form for updating participant status.
|
|
"""
|
|
|
|
STATUS_CHOICES = [
|
|
('CONFIRMED', _('Confirm')),
|
|
('ARRIVED', _('Mark as Arrived')),
|
|
('ATTENDED', _('Mark as Attended')),
|
|
('NO_SHOW', _('Mark as No-Show')),
|
|
('CANCELLED', _('Cancel')),
|
|
]
|
|
|
|
status = forms.ChoiceField(
|
|
choices=STATUS_CHOICES,
|
|
label=_('Action'),
|
|
widget=forms.Select(attrs={'class': 'form-control'})
|
|
)
|
|
|
|
notes = forms.CharField(
|
|
required=False,
|
|
label=_('Notes'),
|
|
widget=forms.Textarea(attrs={'rows': 2, 'class': 'form-control'})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
'status',
|
|
'notes',
|
|
Submit('submit', _('Update Status'), css_class='btn btn-primary')
|
|
)
|
|
|
|
|
|
class SessionSearchForm(forms.Form):
|
|
"""
|
|
Form for searching sessions.
|
|
"""
|
|
|
|
search_query = forms.CharField(
|
|
required=False,
|
|
label=_('Search'),
|
|
widget=forms.TextInput(attrs={
|
|
'placeholder': _('Session number, provider name...'),
|
|
'class': 'form-control'
|
|
})
|
|
)
|
|
|
|
session_type = forms.ChoiceField(
|
|
required=False,
|
|
label=_('Session Type'),
|
|
choices=[('', _('All'))] + [('INDIVIDUAL', _('Individual')), ('GROUP', _('Group'))],
|
|
widget=forms.Select(attrs={'class': 'form-control'})
|
|
)
|
|
|
|
clinic = forms.ModelChoiceField(
|
|
required=False,
|
|
label=_('Clinic'),
|
|
queryset=None, # Will be set in __init__
|
|
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select clinic'})
|
|
)
|
|
|
|
provider = forms.ModelChoiceField(
|
|
required=False,
|
|
label=_('Provider'),
|
|
queryset=None, # Will be set in __init__
|
|
widget=forms.Select(attrs={'class': 'form-select select2', 'data-placeholder': 'Select provider'})
|
|
)
|
|
|
|
status = forms.ChoiceField(
|
|
required=False,
|
|
label=_('Status'),
|
|
choices=[('', _('All')), ('SCHEDULED', _('Scheduled')), ('IN_PROGRESS', _('In Progress')),
|
|
('COMPLETED', _('Completed')), ('CANCELLED', _('Cancelled'))],
|
|
widget=forms.Select(attrs={'class': 'form-control'})
|
|
)
|
|
|
|
date_from = forms.DateField(
|
|
required=False,
|
|
label=_('From Date'),
|
|
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'})
|
|
)
|
|
|
|
date_to = forms.DateField(
|
|
required=False,
|
|
label=_('To Date'),
|
|
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
tenant = kwargs.pop('tenant', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if tenant:
|
|
from core.models import Clinic
|
|
self.fields['clinic'].queryset = Clinic.objects.filter(tenant=tenant, is_active=True)
|
|
self.fields['provider'].queryset = Provider.objects.filter(tenant=tenant, is_available=True)
|
|
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'get'
|
|
self.helper.layout = Layout(
|
|
Row(
|
|
Column('search_query', css_class='form-group col-md-3 mb-0'),
|
|
Column('session_type', css_class='form-group col-md-2 mb-0'),
|
|
Column('clinic', css_class='form-group col-md-2 mb-0'),
|
|
Column('provider', css_class='form-group col-md-2 mb-0'),
|
|
Column('status', css_class='form-group col-md-1 mb-0'),
|
|
Column('date_from', css_class='form-group col-md-1 mb-0'),
|
|
Column('date_to', css_class='form-group col-md-1 mb-0'),
|
|
css_class='form-row'
|
|
),
|
|
Submit('search', _('Search'), css_class='btn btn-primary')
|
|
)
|
|
|
|
|
|
class GroupSessionNotesForm(forms.ModelForm):
|
|
"""
|
|
Form for editing group session notes.
|
|
"""
|
|
|
|
class Meta:
|
|
from .models import Session
|
|
model = Session
|
|
fields = ['group_notes']
|
|
widgets = {
|
|
'group_notes': forms.Textarea(attrs={'rows': 5, 'class': 'form-control'}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.form_method = 'post'
|
|
self.helper.layout = Layout(
|
|
'group_notes',
|
|
Submit('submit', _('Save Notes'), css_class='btn btn-primary')
|
|
)
|