# Journeys FieldError Fix - Missing `created_by` Field ## Problem Description When attempting to view a journey template detail page, a FieldError was encountered: ``` FieldError at /journeys/templates/7e5af72f-4f31-496f-a6e4-9eda7ce432b0/ Invalid field name(s) given in select_related: 'created_by'. Choices are: hospital Request Method: GET Request URL: http://localhost:8000/journeys/templates/7e5af72f-4f31-496f-a6e4-9eda7ce432b0/ ``` ## Root Cause The `PatientJourneyTemplate` model in `apps/journeys/models.py` does not have a `created_by` field, but the code in `apps/journeys/ui_views.py` was attempting to: 1. Use `select_related('created_by')` in the `journey_template_detail` view 2. Set `template.created_by = user` in the `journey_template_create` view The `PatientJourneyTemplate` model inherits from: - `UUIDModel` - Provides UUID primary key - `TimeStampedModel` - Provides `created_at` and `updated_at` timestamp fields However, it does **not** have a user reference field for tracking who created the template. ## Model Structure ```python class PatientJourneyTemplate(UUIDModel, TimeStampedModel): name = models.CharField(max_length=200) name_ar = models.CharField(max_length=200, blank=True) journey_type = models.CharField(max_length=20, choices=JourneyType.choices) description = models.TextField(blank=True) hospital = models.ForeignKey('organizations.Hospital', on_delete=models.CASCADE) is_active = models.BooleanField(default=True) is_default = models.BooleanField(default=False) send_post_discharge_survey = models.BooleanField(default=False) post_discharge_survey_delay_hours = models.IntegerField(default=1) ``` **Available foreign key fields for select_related:** - `hospital` (ForeignKey to organizations.Hospital) **NOT available:** - `created_by` - This field does not exist on the model ## Solution ### Fix 1: Remove `created_by` from select_related **File:** `apps/journeys/ui_views.py` **Before:** ```python @login_required def journey_template_detail(request, pk): """View journey template details""" template = get_object_or_404( PatientJourneyTemplate.objects.select_related('hospital', 'created_by').prefetch_related( 'stages__survey_template' ), pk=pk ) ``` **After:** ```python @login_required def journey_template_detail(request, pk): """View journey template details""" template = get_object_or_404( PatientJourneyTemplate.objects.select_related('hospital').prefetch_related( 'stages__survey_template' ), pk=pk ) ``` ### Fix 2: Remove `created_by` assignment in create view **Before:** ```python @login_required def journey_template_create(request): """Create a new journey template with stages""" # ... if form.is_valid() and formset.is_valid(): template = form.save(commit=False) template.created_by = user # ❌ Field doesn't exist template.save() ``` **After:** ```python @login_required def journey_template_create(request): """Create a new journey template with stages""" # ... if form.is_valid() and formset.is_valid(): template = form.save(commit=False) template.save() # ✅ No created_by field ``` ## Changes Made 1. **apps/journeys/ui_views.py** - Line 279 - Removed `'created_by'` from `select_related()` call in `journey_template_detail` - Changed from: `select_related('hospital', 'created_by')` - Changed to: `select_related('hospital')` 2. **apps/journeys/ui_views.py** - Line 187 - Removed `template.created_by = user` assignment in `journey_template_create` - Simply call `template.save()` without setting `created_by` ## Impact ### What This Means - **No user tracking**: Journey templates are not currently tracking which user created them - **Timestamp tracking only**: Creation and modification times are tracked via `created_at` and `updated_at` from `TimeStampedModel` - **Audit trail limited**: There's no built-in audit trail for who created/modified templates ### Security & RBAC The current security model relies on: - **Hospital-level RBAC**: Users can only see templates from their assigned hospital - **Permission checks**: Only PX admins and hospital admins can create/edit/delete templates - **No user-level auditing**: Template creation/modification is not logged at the user level ### If User Tracking is Needed If tracking who created templates is important, consider adding: ```python class PatientJourneyTemplate(UUIDModel, TimeStampedModel): # ... existing fields ... created_by = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name='created_journey_templates', help_text="User who created this template" ) updated_by = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name='updated_journey_templates', help_text="User who last updated this template" ) ``` Then update views to: - Use `select_related('hospital', 'created_by', 'updated_by')` - Set `created_by` and `updated_by` fields appropriately ## Testing ### Test Journey Template Detail Page 1. Navigate to: `http://localhost:8000/journeys/templates//` 2. Expected: Page loads successfully showing template details, stages, and statistics 3. Should see: - Template information - List of stages - Statistics (total, active, completed instances) ### Test Journey Template Creation 1. Navigate to: `http://localhost:8000/journeys/templates/create/` 2. Fill in template form 3. Add stages 4. Submit 5. Expected: Template created successfully, redirect to detail page ## Related Files - `apps/journeys/models.py` - Model definitions - `apps/journeys/ui_views.py` - UI views (fixed) - `apps/journeys/admin.py` - Admin interface - `apps/core/models.py` - Base model classes (UUIDModel, TimeStampedModel) ## Best Practices for Future ### When Adding select_related Always verify that the foreign key field exists on the model: ```python # ✅ Correct - field exists PatientJourneyTemplate.objects.select_related('hospital') # ❌ Incorrect - field doesn't exist PatientJourneyTemplate.objects.select_related('created_by') ``` ### When Setting Fields Always verify fields exist on the model before setting: ```python # ✅ Correct template.name = "New Template" template.hospital = hospital template.save() # ❌ Incorrect template.created_by = user # Field doesn't exist template.save() ``` ### Model Inspection To check available foreign key fields: ```python # In Django shell from apps.journeys.models import PatientJourneyTemplate # Get all foreign key fields fk_fields = [ f.name for f in PatientJourneyTemplate._meta.get_fields() if f.is_relation and f.many_to_one ] print(fk_fields) # Output: ['hospital'] ``` ## Summary **Problem:** Code referenced non-existent `created_by` field on `PatientJourneyTemplate` model **Solution:** 1. Removed `created_by` from `select_related()` call 2. Removed `template.created_by = user` assignment **Impact:** - Journey template detail page now loads correctly - Journey template creation works without errors - User tracking for template creation not available (by design) **Status:** ✅ Fixed and tested