-- ========================================================================== -- Agência PSI — Migração: tabela `medicos` -- ========================================================================== -- Criado por: Leonardo Nohama -- Data: 2026 · São Carlos/SP — Brasil -- -- Propósito: -- Armazena médicos e profissionais de referência (psiquiatras, neurologistas, -- clínicos gerais, etc.) que encaminham pacientes ou fazem parte da rede de -- suporte clínico do terapeuta. -- -- Usado em: -- - PatientsCadastroPage: campo "Encaminhado por" (FK medico_id) -- - CadastroRapidoMedico.vue: cadastro rápido dentro do formulário -- - MedicosCadastroPage.vue: página completa de gestão de médicos -- -- Relacionamentos: -- medicos.owner_id → auth.users(id) -- medicos.tenant_id → tenants(id) -- patients.medico_encaminhador_id → medicos(id) (opcional, ver abaixo) -- -- RLS: owner_id = auth.uid() — cada profissional vê apenas seus médicos. -- ========================================================================== -- -------------------------------------------------------------------------- -- 1. Tabela principal -- -------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS public.medicos ( id uuid DEFAULT gen_random_uuid() NOT NULL, -- Contexto de acesso owner_id uuid NOT NULL, tenant_id uuid NOT NULL, -- Identidade profissional nome text NOT NULL, crm text, -- Ex: "123456/SP" especialidade text, -- Ex: "Psiquiatria" -- Contatos — telefone_pessoal é sensível (exibido com ícone de olho) telefone_profissional text, -- Consultório / clínica telefone_pessoal text, -- WhatsApp / pessoal email text, -- Local de atuação clinica text, -- Nome da clínica/hospital cidade text, estado text DEFAULT 'SP', -- Notas internas do terapeuta observacoes text, -- Controle ativo boolean DEFAULT true NOT NULL, created_at timestamptz DEFAULT now(), updated_at timestamptz DEFAULT now(), CONSTRAINT medicos_pkey PRIMARY KEY (id), -- CRM único por owner (mesmo terapeuta não cadastra o mesmo CRM duas vezes) CONSTRAINT medicos_crm_owner_unique UNIQUE NULLS NOT DISTINCT (owner_id, crm) ); -- -------------------------------------------------------------------------- -- 2. Índices de performance -- -------------------------------------------------------------------------- CREATE INDEX IF NOT EXISTS medicos_owner_idx ON public.medicos USING btree (owner_id); CREATE INDEX IF NOT EXISTS medicos_tenant_idx ON public.medicos USING btree (tenant_id); CREATE INDEX IF NOT EXISTS medicos_nome_idx ON public.medicos USING btree (nome); CREATE INDEX IF NOT EXISTS medicos_especialidade_idx ON public.medicos USING btree (especialidade); -- Busca textual por nome e especialidade CREATE INDEX IF NOT EXISTS medicos_nome_trgm_idx ON public.medicos USING gin (nome gin_trgm_ops); -- -------------------------------------------------------------------------- -- 3. Trigger de updated_at -- -------------------------------------------------------------------------- CREATE OR REPLACE FUNCTION public.set_medicos_updated_at() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $$; CREATE TRIGGER trg_medicos_updated_at BEFORE UPDATE ON public.medicos FOR EACH ROW EXECUTE FUNCTION public.set_medicos_updated_at(); -- -------------------------------------------------------------------------- -- 4. Row Level Security -- -------------------------------------------------------------------------- ALTER TABLE public.medicos ENABLE ROW LEVEL SECURITY; -- Owner tem acesso total aos seus próprios médicos CREATE POLICY "medicos: owner full access" ON public.medicos USING (owner_id = auth.uid()) WITH CHECK (owner_id = auth.uid()); -- -------------------------------------------------------------------------- -- 5. Comentários de documentação -- -------------------------------------------------------------------------- COMMENT ON TABLE public.medicos IS 'Médicos e profissionais de referência cadastrados pelo terapeuta.'; COMMENT ON COLUMN public.medicos.owner_id IS 'Terapeuta dono do cadastro (auth.uid()).'; COMMENT ON COLUMN public.medicos.tenant_id IS 'Tenant do terapeuta.'; COMMENT ON COLUMN public.medicos.nome IS 'Nome completo do médico/profissional.'; COMMENT ON COLUMN public.medicos.crm IS 'CRM com UF. Ex: 123456/SP. Único por owner_id.'; COMMENT ON COLUMN public.medicos.especialidade IS 'Especialidade médica. Ex: Psiquiatria, Neurologia.'; COMMENT ON COLUMN public.medicos.telefone_profissional IS 'Telefone do consultório ou clínica.'; COMMENT ON COLUMN public.medicos.telefone_pessoal IS 'Telefone pessoal / WhatsApp. Campo sensível.'; COMMENT ON COLUMN public.medicos.email IS 'E-mail profissional.'; COMMENT ON COLUMN public.medicos.clinica IS 'Nome da clínica ou hospital onde atua.'; COMMENT ON COLUMN public.medicos.cidade IS 'Cidade de atuação.'; COMMENT ON COLUMN public.medicos.estado IS 'UF de atuação. Default SP.'; COMMENT ON COLUMN public.medicos.observacoes IS 'Notas internas do terapeuta sobre o médico.'; COMMENT ON COLUMN public.medicos.ativo IS 'Soft delete: false oculta da listagem.'; -- -------------------------------------------------------------------------- -- 6. Coluna FK opcional em patients -- (Conecta "Encaminhado por" ao cadastro de médico) -- Execute apenas se quiser a FK estruturada; caso contrário, -- o campo encaminhado_por (text) no PatientsCadastroPage já funciona. -- -------------------------------------------------------------------------- -- ALTER TABLE public.patients -- ADD COLUMN IF NOT EXISTS medico_encaminhador_id uuid -- REFERENCES public.medicos(id) ON DELETE SET NULL; -- CREATE INDEX IF NOT EXISTS patients_medico_encaminhador_idx -- ON public.patients USING btree (medico_encaminhador_id); -- COMMENT ON COLUMN public.patients.medico_encaminhador_id -- IS 'FK para medicos.id — quem encaminhou o paciente.'; -- ========================================================================== -- FIM DA MIGRAÇÃO -- ==========================================================================