CREATE OR REPLACE FUNCTION public.create_form_inbox_entry_from_homeowner_request() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$ DECLARE v_owner_name text; v_owner_email text; BEGIN SELECT trim(concat_ws(' ', o.first_name, o.last_name)), o.email INTO v_owner_name, v_owner_email FROM public.owners o WHERE o.id = NEW.owner_id; INSERT INTO public.form_inbox ( source_type, source_id, association_id, title, submitter_name, submitter_email, summary ) VALUES ( 'homeowner_ticket', NEW.id, NEW.association_id, NEW.title, NULLIF(v_owner_name, ''), v_owner_email, LEFT(COALESCE(NEW.description, NEW.category, NEW.title), 200) ); RETURN NEW; END; $$; CREATE OR REPLACE FUNCTION public.notify_staff_on_homeowner_request() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$ DECLARE staff_user record; v_owner_name text; v_message text; BEGIN SELECT trim(concat_ws(' ', o.first_name, o.last_name)) INTO v_owner_name FROM public.owners o WHERE o.id = NEW.owner_id; v_message := COALESCE(NULLIF(v_owner_name, ''), 'A homeowner') || ' submitted a ticket: ' || NEW.title; FOR staff_user IN SELECT DISTINCT user_id FROM public.user_roles WHERE role IN ('admin'::public.app_role, 'manager'::public.app_role) AND user_id IS NOT NULL LOOP INSERT INTO public.in_app_notifications (user_id, type, title, message, related_item_id, related_item_type, link) VALUES ( staff_user.user_id, 'homeowner_ticket_submitted', 'New Homeowner Ticket', v_message, NEW.id, 'homeowner_request', '/dashboard/form-inbox' ); END LOOP; RETURN NEW; END; $$; CREATE OR REPLACE FUNCTION public.notify_homeowner_on_ticket_comment() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public' AS $$ DECLARE v_owner_user_id uuid; v_ticket_title text; v_is_staff boolean; BEGIN IF NEW.entity_type <> 'homeowner_request' THEN RETURN NEW; END IF; SELECT hr.title, o.user_id INTO v_ticket_title, v_owner_user_id FROM public.homeowner_requests hr LEFT JOIN public.owners o ON o.id = hr.owner_id WHERE hr.id = NEW.entity_id; IF v_owner_user_id IS NULL OR v_owner_user_id = NEW.user_id THEN RETURN NEW; END IF; SELECT public.has_role(NEW.user_id, 'admin'::public.app_role) OR public.has_role(NEW.user_id, 'manager'::public.app_role) INTO v_is_staff; IF COALESCE(v_is_staff, false) THEN INSERT INTO public.in_app_notifications (user_id, type, title, message, related_item_id, related_item_type, link) VALUES ( v_owner_user_id, 'homeowner_ticket_response', 'Staff responded to your ticket', COALESCE(v_ticket_title, 'Your ticket') || ' has a new response.', NEW.entity_id, 'homeowner_request', '/homeowner/tickets' ); END IF; RETURN NEW; END; $$; DROP TRIGGER IF EXISTS create_form_inbox_entry_from_homeowner_request ON public.homeowner_requests; CREATE TRIGGER create_form_inbox_entry_from_homeowner_request AFTER INSERT ON public.homeowner_requests FOR EACH ROW EXECUTE FUNCTION public.create_form_inbox_entry_from_homeowner_request(); DROP TRIGGER IF EXISTS notify_staff_on_homeowner_request ON public.homeowner_requests; CREATE TRIGGER notify_staff_on_homeowner_request AFTER INSERT ON public.homeowner_requests FOR EACH ROW EXECUTE FUNCTION public.notify_staff_on_homeowner_request(); DROP TRIGGER IF EXISTS notify_homeowner_on_ticket_comment ON public.entity_comments; CREATE TRIGGER notify_homeowner_on_ticket_comment AFTER INSERT ON public.entity_comments FOR EACH ROW EXECUTE FUNCTION public.notify_homeowner_on_ticket_comment();