Files
thrilltrack-explorer/supabase/migrations/20251110201312_df5a3cc0-baac-40da-a74f-d43110b9ba2b.sql
gpt-engineer-app[bot] 95c352af48 Connect to Lovable Cloud
Approve and apply migration to fix RPC for park location data
- Update TypeScript types to remove temp_location_data
- Create migration to fix create_submission_with_items by using relational park_submission_locations
- Ensure _temp_location is extracted and stored properly
2025-11-10 20:13:27 +00:00

336 lines
12 KiB
PL/PgSQL

-- Fix create_submission_with_items to use relational park_submission_locations
-- Removes temp_location_data column reference and properly stores location data
DROP FUNCTION IF EXISTS public.create_submission_with_items(uuid, text, jsonb, jsonb[]);
CREATE FUNCTION public.create_submission_with_items(
p_user_id uuid,
p_submission_type text,
p_content jsonb,
p_items jsonb[]
)
RETURNS uuid
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path TO 'public'
AS $$
DECLARE
v_submission_id UUID;
v_item JSONB;
v_item_data JSONB;
v_item_type TEXT;
v_action_type TEXT;
v_park_submission_id UUID;
v_company_submission_id UUID;
v_ride_submission_id UUID;
v_ride_model_submission_id UUID;
v_photo_submission_id UUID;
v_timeline_event_submission_id UUID;
v_submission_item_id UUID;
v_temp_ref_key TEXT;
v_temp_ref_value TEXT;
v_ref_type TEXT;
v_ref_order_index INTEGER;
v_existing_user_id TEXT;
v_existing_submission_id TEXT;
v_temp_location JSONB;
BEGIN
-- DEFENSIVE CHECK: Warn if variables are already set
BEGIN
v_existing_user_id := current_setting('app.current_user_id', true);
v_existing_submission_id := current_setting('app.submission_id', true);
IF v_existing_user_id IS NOT NULL AND v_existing_user_id != '' THEN
RAISE WARNING 'Session variable app.current_user_id already set to: % (expected clean state)', v_existing_user_id;
END IF;
IF v_existing_submission_id IS NOT NULL AND v_existing_submission_id != '' THEN
RAISE WARNING 'Session variable app.submission_id already set to: % (expected clean state)', v_existing_submission_id;
END IF;
EXCEPTION WHEN OTHERS THEN
NULL;
END;
PERFORM set_config('app.current_user_id', p_user_id::text, true);
PERFORM set_config('app.submission_id', '', true);
INSERT INTO content_submissions (user_id, submission_type, status, approval_mode)
VALUES (p_user_id, p_submission_type, 'pending', 'full')
RETURNING id INTO v_submission_id;
PERFORM set_config('app.submission_id', v_submission_id::text, true);
IF array_length(p_items, 1) IS NULL OR array_length(p_items, 1) = 0 THEN
RAISE EXCEPTION 'Cannot create submission without items';
END IF;
FOREACH v_item IN ARRAY p_items
LOOP
v_item_type := (v_item->>'item_type')::TEXT;
v_action_type := (v_item->>'action_type')::TEXT;
v_item_data := v_item->'item_data';
v_park_submission_id := NULL;
v_company_submission_id := NULL;
v_ride_submission_id := NULL;
v_ride_model_submission_id := NULL;
v_photo_submission_id := NULL;
v_timeline_event_submission_id := NULL;
v_temp_location := NULL;
IF v_item_type = 'park' THEN
v_temp_location := v_item_data->'_temp_location';
INSERT INTO park_submissions (
submission_id, name, slug, description, park_type, status,
opening_date, opening_date_precision, closing_date, closing_date_precision,
location_id, operator_id, property_owner_id,
website_url, phone, email,
banner_image_url, banner_image_id, card_image_url, card_image_id
) VALUES (
v_submission_id,
v_item_data->>'name',
v_item_data->>'slug',
v_item_data->>'description',
v_item_data->>'park_type',
v_item_data->>'status',
(v_item_data->>'opening_date')::DATE,
v_item_data->>'opening_date_precision',
(v_item_data->>'closing_date')::DATE,
v_item_data->>'closing_date_precision',
(v_item_data->>'location_id')::UUID,
(v_item_data->>'operator_id')::UUID,
(v_item_data->>'property_owner_id')::UUID,
v_item_data->>'website_url',
v_item_data->>'phone',
v_item_data->>'email',
v_item_data->>'banner_image_url',
v_item_data->>'banner_image_id',
v_item_data->>'card_image_url',
v_item_data->>'card_image_id'
) RETURNING id INTO v_park_submission_id;
IF v_temp_location IS NOT NULL AND jsonb_typeof(v_temp_location) = 'object' THEN
INSERT INTO park_submission_locations (
park_submission_id,
name,
street_address,
city,
state_province,
country,
postal_code,
latitude,
longitude,
timezone,
display_name
) VALUES (
v_park_submission_id,
v_temp_location->>'name',
v_temp_location->>'street_address',
v_temp_location->>'city',
v_temp_location->>'state_province',
v_temp_location->>'country',
v_temp_location->>'postal_code',
(v_temp_location->>'latitude')::NUMERIC,
(v_temp_location->>'longitude')::NUMERIC,
v_temp_location->>'timezone',
v_temp_location->>'display_name'
);
RAISE NOTICE 'Inserted location for park_submission_id=%: %',
v_park_submission_id, v_temp_location->>'name';
END IF;
ELSIF v_item_type IN ('manufacturer', 'operator', 'property_owner', 'designer') THEN
INSERT INTO company_submissions (
submission_id, name, slug, description, company_type, person_type,
founded_year, founded_date, founded_date_precision,
headquarters_location, website_url, logo_url,
banner_image_url, banner_image_id, card_image_url, card_image_id
) VALUES (
v_submission_id,
v_item_data->>'name',
v_item_data->>'slug',
v_item_data->>'description',
v_item_type,
COALESCE(v_item_data->>'person_type', 'company'),
(v_item_data->>'founded_year')::INTEGER,
(v_item_data->>'founded_date')::DATE,
v_item_data->>'founded_date_precision',
v_item_data->>'headquarters_location',
v_item_data->>'website_url',
v_item_data->>'logo_url',
v_item_data->>'banner_image_url',
v_item_data->>'banner_image_id',
v_item_data->>'card_image_url',
v_item_data->>'card_image_id'
) RETURNING id INTO v_company_submission_id;
ELSIF v_item_type = 'ride' THEN
INSERT INTO ride_submissions (
submission_id, name, slug, description, category, status,
park_id, manufacturer_id, designer_id, ride_model_id,
opening_date, opening_date_precision, closing_date, closing_date_precision,
height_requirement_cm, age_requirement, max_speed_kmh, duration_seconds,
capacity_per_hour, gforce_max, inversions_count, length_meters,
height_meters, drop_meters,
banner_image_url, banner_image_id, card_image_url, card_image_id, image_url,
ride_sub_type, coaster_type, seating_type, intensity_level
) VALUES (
v_submission_id,
v_item_data->>'name',
v_item_data->>'slug',
v_item_data->>'description',
v_item_data->>'category',
v_item_data->>'status',
(v_item_data->>'park_id')::UUID,
(v_item_data->>'manufacturer_id')::UUID,
(v_item_data->>'designer_id')::UUID,
(v_item_data->>'ride_model_id')::UUID,
(v_item_data->>'opening_date')::DATE,
v_item_data->>'opening_date_precision',
(v_item_data->>'closing_date')::DATE,
v_item_data->>'closing_date_precision',
(v_item_data->>'height_requirement_cm')::NUMERIC,
(v_item_data->>'age_requirement')::INTEGER,
(v_item_data->>'max_speed_kmh')::NUMERIC,
(v_item_data->>'duration_seconds')::INTEGER,
(v_item_data->>'capacity_per_hour')::INTEGER,
(v_item_data->>'gforce_max')::NUMERIC,
(v_item_data->>'inversions_count')::INTEGER,
(v_item_data->>'length_meters')::NUMERIC,
(v_item_data->>'height_meters')::NUMERIC,
(v_item_data->>'drop_meters')::NUMERIC,
v_item_data->>'banner_image_url',
v_item_data->>'banner_image_id',
v_item_data->>'card_image_url',
v_item_data->>'card_image_id',
v_item_data->>'image_url',
v_item_data->>'ride_sub_type',
v_item_data->>'coaster_type',
v_item_data->>'seating_type',
v_item_data->>'intensity_level'
) RETURNING id INTO v_ride_submission_id;
ELSIF v_item_type = 'ride_model' THEN
INSERT INTO ride_model_submissions (
submission_id, name, slug, manufacturer_id, category, ride_type, description,
banner_image_url, banner_image_id, card_image_url, card_image_id
) VALUES (
v_submission_id,
v_item_data->>'name',
v_item_data->>'slug',
(v_item_data->>'manufacturer_id')::UUID,
v_item_data->>'category',
v_item_data->>'ride_type',
v_item_data->>'description',
v_item_data->>'banner_image_url',
v_item_data->>'banner_image_id',
v_item_data->>'card_image_url',
v_item_data->>'card_image_id'
) RETURNING id INTO v_ride_model_submission_id;
ELSIF v_item_type = 'photo' THEN
INSERT INTO photo_submissions (
submission_id, entity_type, entity_id, title
) VALUES (
v_submission_id,
v_item_data->>'entity_type',
(v_item_data->>'entity_id')::UUID,
v_item_data->>'title'
) RETURNING id INTO v_photo_submission_id;
ELSIF v_item_type IN ('timeline_event', 'milestone') THEN
INSERT INTO timeline_event_submissions (
submission_id, entity_type, entity_id, event_type, event_date,
event_date_precision, title, description
) VALUES (
v_submission_id,
v_item_data->>'entity_type',
(v_item_data->>'entity_id')::UUID,
v_item_data->>'event_type',
(v_item_data->>'event_date')::DATE,
v_item_data->>'event_date_precision',
v_item_data->>'title',
v_item_data->>'description'
) RETURNING id INTO v_timeline_event_submission_id;
END IF;
INSERT INTO submission_items (
submission_id,
item_type,
action_type,
park_submission_id,
company_submission_id,
ride_submission_id,
ride_model_submission_id,
photo_submission_id,
timeline_event_submission_id,
status,
order_index,
depends_on
) VALUES (
v_submission_id,
v_item_type,
v_action_type,
v_park_submission_id,
v_company_submission_id,
v_ride_submission_id,
v_ride_model_submission_id,
v_photo_submission_id,
v_timeline_event_submission_id,
'pending',
COALESCE((v_item->>'order_index')::INTEGER, 0),
(v_item->>'depends_on')::UUID
) RETURNING id INTO v_submission_item_id;
IF v_item_data IS NOT NULL AND jsonb_typeof(v_item_data) = 'object' THEN
FOR v_temp_ref_key, v_temp_ref_value IN
SELECT key, value::text
FROM jsonb_each_text(v_item_data)
WHERE key LIKE '_temp_%_ref'
AND value ~ '^\d+$'
LOOP
BEGIN
v_ref_type := substring(v_temp_ref_key from '_temp_(.+)_ref');
v_ref_order_index := v_temp_ref_value::INTEGER;
INSERT INTO submission_item_temp_refs (
submission_item_id,
ref_type,
ref_order_index
) VALUES (
v_submission_item_id,
v_ref_type,
v_ref_order_index
);
RAISE NOTICE 'Stored temp ref: item_id=%, ref_type=%, order_index=%',
v_submission_item_id, v_ref_type, v_ref_order_index;
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'Failed to store temp ref % for item %: %',
v_temp_ref_key, v_submission_item_id, SQLERRM;
END;
END LOOP;
END IF;
END LOOP;
PERFORM set_config('app.current_user_id', '', true);
PERFORM set_config('app.submission_id', '', true);
RETURN v_submission_id;
EXCEPTION
WHEN OTHERS THEN
PERFORM set_config('app.current_user_id', '', true);
PERFORM set_config('app.submission_id', '', true);
RAISE NOTICE 'Submission creation failed for user % (type=%): %', p_user_id, p_submission_type, SQLERRM;
RAISE;
END;
$$;
COMMENT ON FUNCTION public.create_submission_with_items(uuid, text, jsonb, jsonb[]) IS
'Creates submission with items. Uses relational park_submission_locations table instead of temp_location_data JSONB column.';