13 KiB
13 KiB
Package Appointments - Current vs Required Workflow Explanation
Date: November 18, 2025
🔍 HOW IT WORKS NOW (After My Fixes)
Current Workflow:
Step 1: Package Purchase (Finance Module)
1. Patient goes to Finance module
2. Staff creates an Invoice with a Package
3. Patient pays the invoice
4. System creates PackagePurchase record:
- patient = Patient A
- package = "10 SLP Sessions"
- total_sessions = 10
- sessions_used = 0
- status = ACTIVE
- expiry_date = purchase_date + 90 days
Step 2: Booking Appointment (Appointments Module)
1. Staff goes to Appointments → Create Appointment
2. Selects Patient A
3. Form loads with:
- Patient: Patient A (selected)
- Appointment Type: Radio buttons
○ Single Session (default)
○ Use Package
4. If "Use Package" selected:
- Package dropdown shows ONLY PackagePurchases for Patient A
- Shows: "10 SLP Sessions (5/10 used, 5 remaining)"
5. Staff selects package
6. Manually enters:
- Clinic
- Provider
- Service Type
- Date
- Time
7. Clicks "Book Appointment"
8. System creates Appointment:
- Links to PackagePurchase
- Sets session_number_in_package = 6 (next available)
Step 3: Auto-Schedule (Optional)
1. Staff goes to /appointments/packages/<package_purchase_id>/schedule/
2. Selects:
- Provider (single)
- Start date
- End date
- Preferred days
3. Clicks "Auto-Schedule All Sessions"
4. System creates all remaining appointments automatically
🎯 HOW IT SHOULD WORK (Your Requirements)
Required Workflow:
Step 1: Package Creation (Admin Panel) ✅ Same
Admin creates Package templates:
- "10 SLP Sessions Package"
- "5 OT Assessment Package"
- "20 ABA Therapy Package"
Step 2: Booking Appointment with Package 🆕 DIFFERENT
1. Staff clicks "Book Appointment"
2. Selects "Use Package" option
3. MODAL OPENS showing:
┌─────────────────────────────────────────┐
│ Select Package for Patient │
├─────────────────────────────────────────┤
│ Patient: [Dropdown - Select Patient] │
│ │
│ 📦 ASSIGNED PACKAGES (for this patient)│
│ ✓ 10 SLP Sessions (5/10 used) │
│ ✓ 5 OT Assessment (2/5 used) │
│ │
│ 📦 AVAILABLE PACKAGES (not assigned) │
│ ○ 10 SLP Sessions Package │
│ ○ 20 ABA Therapy Package │
│ ○ 5 OT Assessment Package │
│ │
│ [Select Package] [Cancel] │
└─────────────────────────────────────────┘
4. User selects a package:
Option A: Selects ASSIGNED package
- Uses existing PackagePurchase
- Continues to appointment booking
Option B: Selects AVAILABLE package
- System creates NEW PackagePurchase
- Assigns package to patient
- Sets purchase_date = today
- Sets expiry_date = today + validity_days
- Continues to appointment booking
5. After package selected, system:
- Extracts services from package
- Filters clinics by these services
- Auto-populates clinic dropdown
6. User selects clinic(s)
7. System filters providers by clinic + services
8. User selects provider(s) - MULTI-SELECT
9. User clicks "Auto Schedule"
10. System creates all appointments
🔄 KEY DIFFERENCES
Package Selection:
Current (My Fix):
# Only shows PackagePurchases for patient
queryset = PackagePurchase.objects.filter(
patient=patient,
status='ACTIVE'
)
Required:
# Should show BOTH:
# 1. Existing PackagePurchases for patient
existing_purchases = PackagePurchase.objects.filter(
patient=patient,
status='ACTIVE'
)
# 2. ALL available Packages
available_packages = Package.objects.filter(
is_active=True
)
# Combine and show in modal with visual distinction
Package Assignment:
Current:
- Packages must be purchased in Finance module first
- Creates invoice, payment, then PackagePurchase
Required:
- Packages can be assigned during appointment booking
- No invoice/payment required upfront
- PackagePurchase created on-the-fly
Clinic Filtering:
Current:
- User manually selects clinic
- No filtering based on package
Required:
- System auto-filters clinics based on package services
- Only shows clinics that can perform package services
Provider Selection:
Current:
- Single provider dropdown
- One provider for all sessions
Required:
- Multi-select dropdown
- Can assign different providers to different sessions
📋 WHAT NEEDS TO CHANGE
1. Form Structure 🔄
Current:
class AppointmentBookingForm:
appointment_type = RadioField(['single', 'package'])
package_purchase = ModelChoiceField(PackagePurchase) # Only purchases
Required:
class AppointmentBookingForm:
appointment_type = RadioField(['single', 'package'])
# Remove package_purchase field - will use modal instead
class PackageSelectionForm: # NEW FORM
patient = ModelChoiceField(Patient)
package_type = RadioField(['existing', 'new'])
existing_package = ModelChoiceField(PackagePurchase) # For patient
new_package = ModelChoiceField(Package) # All packages
2. Modal UI 🆕 NEW
Need to Create:
<!-- package_selection_modal.html -->
<div class="modal">
<h5>Select Package for Patient</h5>
<!-- Patient Selection -->
<select id="patient">...</select>
<!-- Assigned Packages Section -->
<h6>Assigned Packages</h6>
<div id="assignedPackages">
<!-- List of PackagePurchases for patient -->
</div>
<!-- Available Packages Section -->
<h6>Available Packages</h6>
<div id="availablePackages">
<!-- List of all Packages -->
</div>
<button>Select Package</button>
</div>
3. Package Assignment View 🆕 NEW
Need to Create:
@login_required
def assign_package_to_patient(request):
"""
Assign a package to a patient (create PackagePurchase).
Called when user selects an unassigned package.
"""
if request.method == 'POST':
package_id = request.POST.get('package_id')
patient_id = request.POST.get('patient_id')
package = Package.objects.get(id=package_id)
patient = Patient.objects.get(id=patient_id)
# Create PackagePurchase
package_purchase = PackagePurchase.objects.create(
tenant=request.user.tenant,
patient=patient,
package=package,
purchase_date=date.today(),
expiry_date=date.today() + timedelta(days=package.validity_days),
total_sessions=package.total_sessions,
sessions_used=0,
status='ACTIVE',
invoice=None # No invoice for now
)
return JsonResponse({
'success': True,
'package_purchase_id': str(package_purchase.id),
'message': 'Package assigned successfully'
})
4. Dynamic Clinic Filtering 🆕 NEW
Need to Add:
def get_clinics_for_package(request):
"""
Get clinics that can perform services in the package.
"""
package_id = request.GET.get('package_id')
package = Package.objects.get(id=package_id)
# Get all services in package
services = package.services.all()
# Get clinics for these services
clinic_ids = services.values_list('clinic_id', flat=True).distinct()
clinics = Clinic.objects.filter(id__in=clinic_ids)
return JsonResponse({
'clinics': [{'id': c.id, 'name': c.name_en} for c in clinics]
})
5. Multi-Provider Selection 🆕 NEW
Need to Add:
<!-- Multi-select for providers -->
<select id="providers" multiple class="form-select">
<option value="provider1">Dr. Smith</option>
<option value="provider2">Dr. Jones</option>
</select>
🎨 UI MOCKUP
Package Selection Modal:
┌──────────────────────────────────────────────────────┐
│ 📦 Select Package [X] │
├──────────────────────────────────────────────────────┤
│ │
│ Patient: [Ahmed Al-Rashid ▼] │
│ │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ │
│ ✅ ASSIGNED PACKAGES (2) │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ ✓ 10 SLP Sessions Package │ │
│ │ Sessions: 5/10 used (5 remaining) │ │
│ │ Expires: 2025-12-31 │ │
│ │ [Select This Package] │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ ✓ 5 OT Assessment Package │ │
│ │ Sessions: 2/5 used (3 remaining) │ │
│ │ Expires: 2026-01-15 │ │
│ │ [Select This Package] │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ │
│ 📦 AVAILABLE PACKAGES (3) │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ ○ 20 ABA Therapy Package │ │
│ │ Total Sessions: 20 │ │
│ │ Price: 5,000 SAR │ │
│ │ Validity: 90 days │ │
│ │ [Assign & Use] │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ ○ 10 SLP Sessions Package │ │
│ │ Total Sessions: 10 │ │
│ │ Price: 3,000 SAR │ │
│ │ [Assign & Use] │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ [Cancel] │
└──────────────────────────────────────────────────────┘
💡 SUMMARY
What I Fixed (Was Partially Correct):
✅ Fixed form field name mismatch ✅ Added atomic transactions for session numbers ✅ Improved security with validation
What I Got Wrong:
❌ Filtered packages by patient only ❌ Assumed packages are pre-purchased ❌ Didn't implement modal UI ❌ Didn't implement package assignment logic
What Needs to Be Done:
- ⚠️ Revert patient-only filtering
- 🆕 Show ALL packages + existing PackagePurchases
- 🆕 Create modal UI for package selection
- 🆕 Implement package assignment (create PackagePurchase on-the-fly)
- 🆕 Dynamic clinic filtering based on package services
- 🆕 Multi-provider selection
- 🔄 Enhanced auto-scheduling
🚀 READY TO PROCEED
I now understand the complete workflow. Shall I proceed with implementing:
- First: Revert the patient-only filtering
- Second: Implement modal-based package selection
- Third: Add package assignment logic
- Fourth: Dynamic filtering and multi-provider support
Please confirm and I'll start implementation!
Status: READY TO IMPLEMENT CORRECT WORKFLOW