# Location Handling Fix - Complete Summary ## Problem Identified Parks were being created without location data due to a critical bug in the approval pipeline. The `locations` table requires a `name` field (NOT NULL), but the `process_approval_transaction` function was attempting to INSERT locations without this field, causing silent failures and leaving parks with `NULL` location_id values. ## Root Cause The function was: 1. ✅ Correctly JOINing `park_submission_locations` table 2. ✅ Fetching location fields like `country`, `city`, `latitude`, etc. 3. ❌ **NOT** fetching the `name` or `display_name` fields 4. ❌ **NOT** including `name` field in the INSERT statement This caused PostgreSQL to reject the INSERT (violating NOT NULL constraint), but since there was no explicit error handling for this specific failure, the park was still created with `location_id = NULL`. ## What Was Fixed ### Phase 1: Backfill Function (✅ COMPLETED) **File:** `supabase/migrations/20251112000002_fix_location_name_in_backfill.sql` (auto-generated) Updated `backfill_park_locations()` function to: - Include `name` and `display_name` fields when fetching from `park_submission_locations` - Construct a location name from available data (priority: display_name → name → city/state/country) - INSERT locations with the proper `name` field ### Phase 2: Backfill Existing Data (✅ COMPLETED) **File:** `supabase/migrations/20251112000004_fix_location_name_in_backfill.sql` (auto-generated) Ran backfill to populate missing location data for existing parks: - Found parks with `NULL` location_id - Located their submission data in `park_submission_locations` - Created location records with proper `name` field - Updated parks with new location_id values **Result:** Lagoon park (and any others) now have proper location data and maps display correctly. ### Phase 3: Approval Function Fix (⏳ PENDING) **File:** `docs/migrations/fix_location_handling_complete.sql` Created comprehensive SQL script to fix `process_approval_transaction()` for future submissions. **Key Changes:** 1. Added to SELECT clause (line ~108): ```sql psl.name as park_location_name, psl.display_name as park_location_display_name, ``` 2. Updated CREATE action location INSERT (line ~204): ```sql v_location_name := COALESCE( v_item.park_location_display_name, v_item.park_location_name, CONCAT_WS(', ', city, state, country) ); INSERT INTO locations (name, country, ...) VALUES (v_location_name, v_item.park_location_country, ...) ``` 3. Updated UPDATE action location INSERT (line ~454): ```sql -- Same logic as CREATE action ``` ## How to Apply the Approval Function Fix The complete SQL script is ready in `docs/migrations/fix_location_handling_complete.sql`. ### Option 1: Via Supabase SQL Editor (Recommended) 1. Go to [Supabase SQL Editor](https://supabase.com/dashboard/project/ydvtmnrszybqnbcqbdcy/sql/new) 2. Copy the contents of `docs/migrations/fix_location_handling_complete.sql` 3. Paste and execute the SQL 4. Verify success by checking the function exists ### Option 2: Via Migration Tool (Later) The migration can be split into smaller chunks if needed, but the complete file is ready for manual application. ## Verification Steps ### 1. Verify Existing Parks Have Locations ```sql SELECT p.name, p.slug, p.location_id, l.name as location_name FROM parks p LEFT JOIN locations l ON p.location_id = l.id WHERE p.slug = 'lagoon'; ``` **Expected Result:** Location data should be populated ✅ ### 2. Test New Park Submission (After Applying Fix) 1. Create a new park submission with location data 2. Submit for moderation 3. Approve the submission 4. Verify the park has a non-NULL location_id 5. Check the locations table has the proper name field 6. Verify the map displays on the park detail page ### 3. Test Park Update with Location Change 1. Edit an existing park and change its location 2. Submit for moderation 3. Approve the update 4. Verify a new location record was created with proper name 5. Verify the park's location_id was updated ## Database Schema Context ### locations Table Structure ```sql - id: uuid (PK) - name: text (NOT NULL) ← This was the missing field - country: text - state_province: text - city: text - street_address: text - postal_code: text - latitude: numeric - longitude: numeric - timezone: text - created_at: timestamp with time zone ``` ### park_submission_locations Table Structure ```sql - id: uuid (PK) - park_submission_id: uuid (FK) - name: text ← We weren't fetching this - display_name: text ← We weren't fetching this - country: text - state_province: text - city: text - street_address: text - postal_code: text - latitude: numeric - longitude: numeric - timezone: text - created_at: timestamp with time zone ``` ## Impact Assessment ### Before Fix - ❌ Parks created without location data (location_id = NULL) - ❌ Maps not displaying on park detail pages - ❌ Location-based features not working - ❌ Silent failures in approval pipeline ### After Complete Fix - ✅ All existing parks have location data (backfilled) - ✅ Maps display correctly on park detail pages - ✅ Future park submissions will have locations created properly - ✅ Park updates with location changes work correctly - ✅ No more silent failures in the pipeline ## Files Created 1. `docs/migrations/fix_location_handling_complete.sql` - Complete SQL script for approval function fix 2. `docs/LOCATION_FIX_SUMMARY.md` - This document ## Next Steps 1. **Immediate:** Apply the fix from `docs/migrations/fix_location_handling_complete.sql` 2. **Testing:** Run verification steps above 3. **Monitoring:** Watch for any location-related errors in production 4. **Documentation:** Update team on the fix and new behavior ## Related Issues This fix ensures compliance with the "Sacred Pipeline" architecture documented in `docs/SUBMISSION_FLOW.md`. All location data flows through: 1. User form input 2. Submission to `park_submission_locations` table 3. Moderation queue review 4. Approval via `process_approval_transaction` function 5. Location creation in `locations` table 6. Park creation/update with proper location_id reference ## Additional Notes - The `display_name` field in `park_submission_locations` is used for human-readable location labels (e.g., "375, Lagoon Drive, Farmington, Davis County, Utah, 84025, United States") - The `name` field in `locations` must be populated for the INSERT to succeed - If neither display_name nor name is provided, we construct it from city/state/country as a fallback - This pattern should be applied to any other entities that use location data in the future