# 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//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):** ```python # Only shows PackagePurchases for patient queryset = PackagePurchase.objects.filter( patient=patient, status='ACTIVE' ) ``` **Required:** ```python # 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:** ```python class AppointmentBookingForm: appointment_type = RadioField(['single', 'package']) package_purchase = ModelChoiceField(PackagePurchase) # Only purchases ``` **Required:** ```python 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:** ```html ``` ### **3. Package Assignment View** 🆕 NEW **Need to Create:** ```python @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:** ```python 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:** ```html ``` --- ## 🎨 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:** 1. ⚠️ Revert patient-only filtering 2. 🆕 Show ALL packages + existing PackagePurchases 3. 🆕 Create modal UI for package selection 4. 🆕 Implement package assignment (create PackagePurchase on-the-fly) 5. 🆕 Dynamic clinic filtering based on package services 6. 🆕 Multi-provider selection 7. 🔄 Enhanced auto-scheduling --- ## 🚀 READY TO PROCEED I now understand the complete workflow. Shall I proceed with implementing: 1. **First:** Revert the patient-only filtering 2. **Second:** Implement modal-based package selection 3. **Third:** Add package assignment logic 4. **Fourth:** Dynamic filtering and multi-provider support Please confirm and I'll start implementation! --- **Status:** READY TO IMPLEMENT CORRECT WORKFLOW