diff --git a/supabase/migrations/20251012183350_c3ce8e74-d50f-4e38-95f1-8a4b458eb394.sql b/supabase/migrations/20251012183350_c3ce8e74-d50f-4e38-95f1-8a4b458eb394.sql new file mode 100644 index 00000000..fb3f201b --- /dev/null +++ b/supabase/migrations/20251012183350_c3ce8e74-d50f-4e38-95f1-8a4b458eb394.sql @@ -0,0 +1,104 @@ +-- Fix notification payload data types for Novu validation +CREATE OR REPLACE FUNCTION public.notify_moderators_on_new_submission() + RETURNS trigger + LANGUAGE plpgsql + SECURITY DEFINER + SET search_path TO 'public' +AS $function$ +DECLARE + submitter_profile record; + function_url text; + anon_key text; + content_preview text; + has_photos boolean := false; + item_count integer := 0; +BEGIN + -- Get submitter's username or display name + SELECT username, display_name INTO submitter_profile + FROM public.profiles + WHERE user_id = NEW.user_id; + + -- Build content preview based on submission type + content_preview := CASE NEW.submission_type + WHEN 'park' THEN + COALESCE(NEW.content->>'name', 'Unnamed') || ' - ' || + COALESCE(NEW.content->>'park_type', 'Park') || + CASE + WHEN NEW.content->>'location' IS NOT NULL + THEN ' in ' || (NEW.content->>'location') + ELSE '' + END + WHEN 'ride' THEN + COALESCE(NEW.content->>'name', 'Unnamed') || ' - ' || + COALESCE(NEW.content->>'category', 'Ride') || + CASE + WHEN NEW.content->>'park_name' IS NOT NULL + THEN ' at ' || (NEW.content->>'park_name') + ELSE '' + END + WHEN 'company' THEN + COALESCE(NEW.content->>'name', 'Unnamed') || ' - ' || + COALESCE(NEW.content->>'company_type', 'Company') + WHEN 'ride_model' THEN + COALESCE(NEW.content->>'name', 'Unnamed') || ' - ' || + 'Ride Model' || + CASE + WHEN NEW.content->>'manufacturer_name' IS NOT NULL + THEN ' by ' || (NEW.content->>'manufacturer_name') + ELSE '' + END + WHEN 'photo' THEN + 'Photo submission for ' || COALESCE(NEW.content->>'entity_type', 'entity') + ELSE + 'Submission' + END; + + -- Truncate preview to 200 characters + content_preview := LEFT(content_preview, 200); + + -- Check if this submission has photos + has_photos := EXISTS ( + SELECT 1 FROM photo_submissions ps + WHERE ps.submission_id = NEW.id + ); + + -- Count submission items and ensure it's an integer + SELECT COALESCE(COUNT(*), 0)::integer INTO item_count + FROM submission_items + WHERE submission_id = NEW.id; + + -- Build the function URL + function_url := 'https://ydvtmnrszybqnbcqbdcy.supabase.co/functions/v1/notify-moderators-submission'; + + -- Use the public anon key + anon_key := 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlkdnRtbnJzenlicW5iY3FiZGN5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTgzMjYzNTYsImV4cCI6MjA3MzkwMjM1Nn0.DM3oyapd_omP5ZzIlrT0H9qBsiQBxBRgw2tYuqgXKX4'; + + -- Call edge function asynchronously with enhanced data + PERFORM net.http_post( + url := function_url, + headers := jsonb_build_object( + 'Content-Type', 'application/json', + 'Authorization', 'Bearer ' || anon_key, + 'apikey', anon_key + ), + body := jsonb_build_object( + 'submission_id', NEW.id, + 'submission_type', NEW.submission_type, + 'submitter_name', COALESCE(submitter_profile.display_name, submitter_profile.username, 'Anonymous'), + 'action', COALESCE((NEW.content->>'action')::text, 'create'), + 'content_preview', content_preview, + 'submitted_at', to_char(NEW.submitted_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'), + 'has_photos', has_photos, + 'item_count', item_count, + 'is_escalated', COALESCE(NEW.escalated, false) + ) + ); + + RETURN NEW; +EXCEPTION + WHEN OTHERS THEN + -- Log error but don't fail the submission + RAISE WARNING 'Failed to notify moderators: %', SQLERRM; + RETURN NEW; +END; +$function$; \ No newline at end of file