ALTER TYPE public.app_role ADD VALUE IF NOT EXISTS 'rv_boat_lot'; INSERT INTO public.role_permissions (role, feature_area, can_read, can_create, can_edit, can_delete) SELECT 'rv_boat_lot', feature_area, can_read, can_create, can_edit, can_delete FROM public.role_permissions WHERE role = 'homeowner' ON CONFLICT (role, feature_area) DO UPDATE SET can_read = EXCLUDED.can_read, can_create = EXCLUDED.can_create, can_edit = EXCLUDED.can_edit, can_delete = EXCLUDED.can_delete, updated_at = now(); ALTER TABLE public.portal_function_visibility DROP CONSTRAINT IF EXISTS portal_function_visibility_portal_check; ALTER TABLE public.portal_function_visibility ADD CONSTRAINT portal_function_visibility_portal_check CHECK (portal IN ('board', 'homeowner', 'rv_boat_lot')); ALTER TABLE public.portal_function_visibility DROP CONSTRAINT IF EXISTS portal_function_visibility_scope_check; ALTER TABLE public.portal_function_visibility ADD CONSTRAINT portal_function_visibility_scope_check CHECK (portal IN ('homeowner', 'rv_boat_lot') OR owner_user_id IS NULL); INSERT INTO public.portal_function_visibility (portal, function_key, enabled, owner_user_id, association_id) SELECT 'rv_boat_lot', function_key, enabled, owner_user_id, association_id FROM public.portal_function_visibility WHERE portal = 'homeowner' ON CONFLICT DO NOTHING; CREATE OR REPLACE FUNCTION public.can_view_portal_function( _portal text, _function_key text, _user_id uuid DEFAULT auth.uid(), _association_id uuid DEFAULT NULL ) RETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path TO 'public' AS $function$ SELECT COALESCE(( SELECT pfv.enabled FROM public.portal_function_visibility pfv WHERE pfv.portal = _portal AND pfv.function_key = _function_key AND (pfv.owner_user_id = _user_id OR pfv.owner_user_id IS NULL) AND (pfv.association_id = _association_id OR pfv.association_id IS NULL) ORDER BY (pfv.owner_user_id = _user_id) DESC, (pfv.association_id = _association_id) DESC LIMIT 1 ), true) $function$;