395 lines
13 KiB
Markdown
395 lines
13 KiB
Markdown
# Group Session Implementation Report
|
|
|
|
## Overview
|
|
This document details the implementation of group session support for the AgdarCentre appointment system, allowing multiple patients to be booked into the same appointment slot for group therapy sessions.
|
|
|
|
## Implementation Date
|
|
November 11, 2025
|
|
|
|
## Requirements Summary
|
|
Based on user requirements:
|
|
- **Capacity**: 1-20 patients per group session
|
|
- **Workflow**: Create empty group sessions, add patients later
|
|
- **Status Tracking**: Individual status per patient
|
|
- **Billing**: Per patient (separate invoices)
|
|
- **Documentation**: Both shared group notes AND individual patient notes
|
|
- **Architecture**: Session-based model (Option 1)
|
|
|
|
## What Was Implemented
|
|
|
|
### 1. Database Models (✅ COMPLETED)
|
|
|
|
#### New Model: `Session`
|
|
Located in: `appointments/models.py`
|
|
|
|
**Purpose**: Represents a scheduled session (individual or group) that can accommodate one or more patients.
|
|
|
|
**Key Fields**:
|
|
- `session_number`: Unique identifier (auto-generated)
|
|
- `session_type`: INDIVIDUAL or GROUP
|
|
- `max_capacity`: 1-20 patients (validated)
|
|
- `provider`, `clinic`, `room`: Core relationships
|
|
- `scheduled_date`, `scheduled_time`, `duration`: Scheduling
|
|
- `status`: SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLED
|
|
- `group_notes`: Shared notes for entire session
|
|
|
|
**Key Properties**:
|
|
- `current_capacity`: Number of enrolled patients
|
|
- `available_spots`: Remaining capacity
|
|
- `is_full`: Boolean check if at capacity
|
|
- `capacity_percentage`: Utilization percentage
|
|
- `get_participants_list()`: Get enrolled patients
|
|
|
|
#### New Model: `SessionParticipant`
|
|
Located in: `appointments/models.py`
|
|
|
|
**Purpose**: Represents individual patient participation in a session with unique tracking.
|
|
|
|
**Key Fields**:
|
|
- `session`: FK to Session
|
|
- `patient`: FK to Patient
|
|
- `appointment_number`: Unique per participant (for billing)
|
|
- `status`: BOOKED, CONFIRMED, CANCELLED, NO_SHOW, ARRIVED, ATTENDED
|
|
- `confirmation_sent_at`, `arrival_at`, `attended_at`: Individual timestamps
|
|
- `individual_notes`: Patient-specific notes
|
|
- `finance_cleared`, `consent_verified`: Per-patient prerequisites
|
|
- `no_show_reason`, `no_show_notes`: Individual tracking
|
|
|
|
**Key Properties**:
|
|
- `can_check_in`: Check if prerequisites met
|
|
- `get_status_color()`: UI color coding
|
|
|
|
#### Modified Model: `Appointment`
|
|
**Added Field**:
|
|
- `session`: FK to Session (nullable, for backward compatibility)
|
|
|
|
This allows existing appointments to be linked to sessions during migration.
|
|
|
|
### 2. Migration Files (✅ COMPLETED)
|
|
|
|
**Migration**: `appointments/migrations/0004_add_session_models.py`
|
|
|
|
**Creates**:
|
|
- Session model with all fields and indexes
|
|
- SessionParticipant model with all fields and indexes
|
|
- HistoricalSession (for audit trail)
|
|
- HistoricalSessionParticipant (for audit trail)
|
|
- Adds session FK to Appointment model
|
|
- Creates all necessary database indexes for performance
|
|
|
|
**Status**: Migration file created, ready to run with `python3 manage.py migrate`
|
|
|
|
## Architecture Design
|
|
|
|
### Data Flow for Group Sessions
|
|
|
|
```
|
|
1. CREATE GROUP SESSION
|
|
└─> Session (capacity=8, type=GROUP)
|
|
└─> session_number: "SES-AGDAR-2025-12345"
|
|
|
|
2. ADD PATIENTS TO SESSION
|
|
├─> SessionParticipant #1 (Patient A)
|
|
│ └─> appointment_number: "APT-AGDAR-2025-10001"
|
|
├─> SessionParticipant #2 (Patient B)
|
|
│ └─> appointment_number: "APT-AGDAR-2025-10002"
|
|
└─> SessionParticipant #3 (Patient C)
|
|
└─> appointment_number: "APT-AGDAR-2025-10003"
|
|
|
|
3. INDIVIDUAL TRACKING
|
|
├─> Patient A: CONFIRMED, finance_cleared=True
|
|
├─> Patient B: BOOKED, finance_cleared=False
|
|
└─> Patient C: NO_SHOW
|
|
|
|
4. BILLING
|
|
├─> Invoice for APT-AGDAR-2025-10001 (Patient A)
|
|
├─> Invoice for APT-AGDAR-2025-10002 (Patient B)
|
|
└─> Invoice for APT-AGDAR-2025-10003 (Patient C)
|
|
```
|
|
|
|
### Backward Compatibility
|
|
|
|
**Existing Appointments**:
|
|
- All existing appointments remain functional
|
|
- Can be migrated to individual sessions (capacity=1)
|
|
- Appointment model retained for legacy support
|
|
- New bookings can use either Appointment or Session models
|
|
|
|
## Next Steps (TODO)
|
|
|
|
### Phase 1: Service Layer (HIGH PRIORITY)
|
|
|
|
#### Create `SessionService` class
|
|
Location: `appointments/session_service.py`
|
|
|
|
**Methods to implement**:
|
|
```python
|
|
class SessionService:
|
|
@staticmethod
|
|
def create_group_session(provider, clinic, date, time, duration, service_type, max_capacity, **kwargs)
|
|
|
|
@staticmethod
|
|
def add_patient_to_session(session, patient, **kwargs)
|
|
|
|
@staticmethod
|
|
def remove_patient_from_session(participant, reason)
|
|
|
|
@staticmethod
|
|
def get_available_group_sessions(clinic, date_from, date_to, service_type=None)
|
|
|
|
@staticmethod
|
|
def check_session_capacity(session)
|
|
|
|
@staticmethod
|
|
def _generate_session_number(tenant)
|
|
|
|
@staticmethod
|
|
def _generate_appointment_number(tenant)
|
|
```
|
|
|
|
#### Update `AppointmentService`
|
|
Location: `appointments/services.py`
|
|
|
|
**Modifications needed**:
|
|
- Update `check_conflicts()` to handle group sessions
|
|
- Add session-aware booking logic
|
|
- Integrate with SessionService for group bookings
|
|
|
|
### Phase 2: Admin Interface (HIGH PRIORITY)
|
|
|
|
#### Create Django Admin
|
|
Location: `appointments/admin.py`
|
|
|
|
**Admin classes to add**:
|
|
```python
|
|
@admin.register(Session)
|
|
class SessionAdmin(admin.ModelAdmin):
|
|
list_display = ['session_number', 'session_type', 'provider', 'scheduled_date', 'current_capacity', 'max_capacity', 'status']
|
|
list_filter = ['session_type', 'status', 'clinic', 'scheduled_date']
|
|
search_fields = ['session_number', 'provider__user__first_name', 'provider__user__last_name']
|
|
readonly_fields = ['session_number', 'current_capacity', 'available_spots']
|
|
|
|
inlines = [SessionParticipantInline]
|
|
|
|
@admin.register(SessionParticipant)
|
|
class SessionParticipantAdmin(admin.ModelAdmin):
|
|
list_display = ['appointment_number', 'patient', 'session', 'status', 'finance_cleared', 'consent_verified']
|
|
list_filter = ['status', 'finance_cleared', 'consent_verified']
|
|
search_fields = ['appointment_number', 'patient__first_name_en', 'patient__last_name_en']
|
|
```
|
|
|
|
### Phase 3: Forms (MEDIUM PRIORITY)
|
|
|
|
#### Create Session Forms
|
|
Location: `appointments/forms.py`
|
|
|
|
**Forms to add**:
|
|
1. `GroupSessionCreateForm` - Create new group session
|
|
2. `AddPatientToSessionForm` - Add patient to existing session
|
|
3. `SessionParticipantStatusForm` - Update participant status
|
|
4. `GroupSessionNotesForm` - Edit group notes
|
|
|
|
### Phase 4: Views (MEDIUM PRIORITY)
|
|
|
|
#### Create Session Views
|
|
Location: `appointments/views.py` or `appointments/session_views.py`
|
|
|
|
**Views to implement**:
|
|
1. `GroupSessionListView` - List all group sessions
|
|
2. `GroupSessionDetailView` - View session with all participants
|
|
3. `GroupSessionCreateView` - Create new group session
|
|
4. `AddPatientToSessionView` - Add patient to session
|
|
5. `SessionParticipantCheckInView` - Check in individual participant
|
|
6. `GroupSessionCalendarView` - Calendar view with group sessions
|
|
|
|
### Phase 5: Templates (MEDIUM PRIORITY)
|
|
|
|
#### Create Templates
|
|
Location: `appointments/templates/appointments/`
|
|
|
|
**Templates needed**:
|
|
1. `group_session_list.html` - List of group sessions
|
|
2. `group_session_detail.html` - Session details with participants
|
|
3. `group_session_form.html` - Create/edit group session
|
|
4. `add_patient_to_session.html` - Add patient form
|
|
5. `session_participant_checkin.html` - Check-in interface
|
|
6. `partials/session_capacity_badge.html` - Capacity indicator
|
|
|
|
### Phase 6: API Endpoints (LOW PRIORITY)
|
|
|
|
#### REST API
|
|
Location: `appointments/api_views.py`
|
|
|
|
**Endpoints to add**:
|
|
- `GET /api/sessions/` - List sessions
|
|
- `POST /api/sessions/` - Create session
|
|
- `GET /api/sessions/{id}/` - Session detail
|
|
- `POST /api/sessions/{id}/add-patient/` - Add patient
|
|
- `GET /api/sessions/available/` - Available group sessions
|
|
- `PATCH /api/sessions/{id}/participants/{id}/` - Update participant
|
|
|
|
### Phase 7: Integration (LOW PRIORITY)
|
|
|
|
#### Billing Integration
|
|
- Link SessionParticipant.appointment_number to invoices
|
|
- Ensure per-patient billing works correctly
|
|
- Test invoice generation for group session participants
|
|
|
|
#### Clinical Documentation
|
|
- Link clinical forms to SessionParticipant.appointment_number
|
|
- Support both group_notes and individual_notes
|
|
- Update form templates to show session context
|
|
|
|
#### Notifications
|
|
- Send individual confirmations to each participant
|
|
- Group session reminders
|
|
- Capacity alerts (session full, spots available)
|
|
|
|
### Phase 8: Testing (CRITICAL)
|
|
|
|
#### Unit Tests
|
|
Location: `appointments/tests/`
|
|
|
|
**Test cases**:
|
|
1. Session creation with various capacities
|
|
2. Adding patients up to capacity
|
|
3. Capacity overflow prevention
|
|
4. Individual status tracking
|
|
5. Appointment number generation
|
|
6. Conflict checking for group sessions
|
|
|
|
#### Integration Tests
|
|
1. Full booking workflow
|
|
2. Check-in process for group sessions
|
|
3. Billing integration
|
|
4. Clinical documentation linking
|
|
|
|
## Migration Strategy
|
|
|
|
### Step 1: Run Migration
|
|
```bash
|
|
python3 manage.py migrate appointments
|
|
```
|
|
|
|
### Step 2: Data Migration (Optional)
|
|
Create a data migration to convert existing appointments to sessions:
|
|
|
|
```python
|
|
# appointments/migrations/0005_migrate_appointments_to_sessions.py
|
|
def migrate_appointments_to_sessions(apps, schema_editor):
|
|
Appointment = apps.get_model('appointments', 'Appointment')
|
|
Session = apps.get_model('appointments', 'Session')
|
|
SessionParticipant = apps.get_model('appointments', 'SessionParticipant')
|
|
|
|
for appointment in Appointment.objects.all():
|
|
# Create individual session
|
|
session = Session.objects.create(
|
|
tenant=appointment.tenant,
|
|
session_number=f"SES-{appointment.appointment_number}",
|
|
session_type='INDIVIDUAL',
|
|
max_capacity=1,
|
|
provider=appointment.provider,
|
|
clinic=appointment.clinic,
|
|
room=appointment.room,
|
|
service_type=appointment.service_type,
|
|
scheduled_date=appointment.scheduled_date,
|
|
scheduled_time=appointment.scheduled_time,
|
|
duration=appointment.duration,
|
|
status='SCHEDULED' if appointment.status in ['BOOKED', 'CONFIRMED'] else 'COMPLETED',
|
|
)
|
|
|
|
# Create participant
|
|
SessionParticipant.objects.create(
|
|
session=session,
|
|
patient=appointment.patient,
|
|
appointment_number=appointment.appointment_number,
|
|
status=appointment.status,
|
|
finance_cleared=appointment.finance_cleared,
|
|
consent_verified=appointment.consent_verified,
|
|
)
|
|
|
|
# Link appointment to session
|
|
appointment.session = session
|
|
appointment.save()
|
|
```
|
|
|
|
### Step 3: Update Existing Code
|
|
- Update views to handle both Appointment and Session models
|
|
- Update templates to show session information
|
|
- Update services to use SessionService for new bookings
|
|
|
|
## Benefits of This Implementation
|
|
|
|
### 1. Scalability
|
|
- Supports 1-20 patients per session
|
|
- Easy to adjust capacity limits
|
|
- Efficient database queries with proper indexing
|
|
|
|
### 2. Flexibility
|
|
- Create empty sessions and add patients later
|
|
- Individual status tracking per patient
|
|
- Support for both individual and group sessions
|
|
|
|
### 3. Data Integrity
|
|
- Unique appointment numbers for billing
|
|
- Proper foreign key relationships
|
|
- Audit trail with simple-history
|
|
|
|
### 4. User Experience
|
|
- Clear capacity indicators
|
|
- Individual patient management
|
|
- Separate notes for group and individual
|
|
|
|
### 5. Billing Accuracy
|
|
- Each participant gets unique appointment number
|
|
- Per-patient invoicing
|
|
- Clear audit trail
|
|
|
|
## Technical Considerations
|
|
|
|
### Performance
|
|
- Indexed fields for fast queries
|
|
- Efficient capacity calculations
|
|
- Optimized participant lookups
|
|
|
|
### Security
|
|
- Tenant isolation maintained
|
|
- Permission checks per participant
|
|
- Audit trail for all changes
|
|
|
|
### Maintainability
|
|
- Clean separation of concerns
|
|
- Well-documented code
|
|
- Backward compatible
|
|
|
|
## Conclusion
|
|
|
|
The foundation for group session support has been successfully implemented with:
|
|
- ✅ Database models (Session, SessionParticipant)
|
|
- ✅ Migration files
|
|
- ✅ Backward compatibility (session FK in Appointment)
|
|
- ✅ Comprehensive documentation
|
|
|
|
**Next immediate steps**:
|
|
1. Run the migration: `python3 manage.py migrate appointments`
|
|
2. Implement SessionService class
|
|
3. Create Django admin interface
|
|
4. Build forms and views
|
|
5. Test the complete workflow
|
|
|
|
The implementation follows Django best practices and maintains compatibility with the existing appointment system while adding powerful group session capabilities.
|
|
|
|
## Contact & Support
|
|
|
|
For questions or issues with this implementation:
|
|
- Review this document
|
|
- Check the inline code documentation
|
|
- Test in development environment first
|
|
- Create backup before running migrations in production
|
|
|
|
---
|
|
|
|
**Implementation Status**: Phase 1 Complete (Models & Migrations)
|
|
**Next Phase**: Service Layer & Admin Interface
|
|
**Estimated Completion**: 2-3 weeks for full implementation
|