-- ============================================================================ -- Trigger de versionamento automático de clinical_notes -- ---------------------------------------------------------------------------- -- A cada INSERT ou UPDATE relevante em clinical_notes, cria snapshot completo -- em clinical_note_versions. Função é SECURITY DEFINER pra bypassar a RLS -- (que bloqueia INSERT direto em clinical_note_versions). -- -- Versionamento dispara em: -- • INSERT — registra criação (version_number = 1) -- • UPDATE em content_text, content_structured ou title — registra edição -- -- Mudanças em pinned/is_draft NÃO disparam versionamento (mudança de UI/state, -- não de conteúdo). -- ============================================================================ BEGIN; CREATE OR REPLACE FUNCTION public.fn_clinical_note_version() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ DECLARE next_version integer; reason text; BEGIN SELECT COALESCE(MAX(version_number), 0) + 1 INTO next_version FROM public.clinical_note_versions WHERE note_id = NEW.id; IF TG_OP = 'INSERT' THEN reason := 'criacao'; ELSIF TG_OP = 'UPDATE' THEN IF NEW.deleted_at IS NOT NULL AND OLD.deleted_at IS NULL THEN reason := 'soft_delete'; ELSIF NEW.deleted_at IS NULL AND OLD.deleted_at IS NOT NULL THEN reason := 'restore'; ELSE reason := 'edicao'; END IF; ELSE reason := 'desconhecido'; END IF; INSERT INTO public.clinical_note_versions ( note_id, tenant_id, version_number, title, content_text, content_structured, change_reason, created_at, created_by ) VALUES ( NEW.id, NEW.tenant_id, next_version, NEW.title, NEW.content_text, NEW.content_structured, reason, now(), COALESCE(NEW.updated_by, NEW.created_by) ); RETURN NEW; END; $$; COMMENT ON FUNCTION public.fn_clinical_note_version() IS 'Snapshot completo de clinical_notes a cada INSERT/UPDATE relevante. SECURITY DEFINER bypassa RLS pra escrever em clinical_note_versions (que bloqueia INSERT direto).'; CREATE TRIGGER trg_clinical_notes_version_insert AFTER INSERT ON public.clinical_notes FOR EACH ROW EXECUTE FUNCTION public.fn_clinical_note_version(); CREATE TRIGGER trg_clinical_notes_version_update AFTER UPDATE OF content_text, content_structured, title, deleted_at ON public.clinical_notes FOR EACH ROW WHEN ( OLD.content_text IS DISTINCT FROM NEW.content_text OR OLD.content_structured IS DISTINCT FROM NEW.content_structured OR OLD.title IS DISTINCT FROM NEW.title OR OLD.deleted_at IS DISTINCT FROM NEW.deleted_at ) EXECUTE FUNCTION public.fn_clinical_note_version(); -- ────────────────────────────────────────────────────────────────────────── -- Trigger para updated_at automático -- ────────────────────────────────────────────────────────────────────────── CREATE OR REPLACE FUNCTION public.fn_clinical_notes_updated_at() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN NEW.updated_at := now(); RETURN NEW; END; $$; CREATE TRIGGER trg_clinical_notes_updated_at BEFORE UPDATE ON public.clinical_notes FOR EACH ROW EXECUTE FUNCTION public.fn_clinical_notes_updated_at(); CREATE TRIGGER trg_clinical_note_templates_updated_at BEFORE UPDATE ON public.clinical_note_templates FOR EACH ROW EXECUTE FUNCTION public.fn_clinical_notes_updated_at(); COMMIT;