Central do Médico (Cockpit) — Mapeamento de Banco de Dados (v6.0)
Documentos desta funcionalidade: 01 - Definição (v6.0) · 02 - Especificação (v6.0) · 03 - Protótipo (v6.0, código executável em 03 - Protótipo v6.0.html) · 04 - Mapeamento de Banco de Dados (v6.0) · 05 - Registro de Decisões (v1.20)
SEÇÃO 4 — MAPEAMENTO DE BANCO DE DADOS
Exclusão lógica: um registro excluído tem RemovidoEm preenchido; as consultas deste documento ignoram esses registros nas tabelas que têm o campo (em GescomClienteAlfa, segundo a Biblioteca de Schema (DDL): Agenda, Paciente, PEP, PEPDiagnostico, ProgramaApoio e ProgramaApoioPaciente). O campo Status com A/I do legado está sendo descontinuado e não é usado como critério de “ativo” (Log de Mudanças Estruturais do Banco de Dados, 07/10/2026). Tabelas sem RemovidoEm (ex.: Prescricao, PacienteFoto, PEPProgramaApoioPaciente) não recebem esse filtro.
Ligação entre a clínica do login e a base do cliente (D-CM-065). O login é autorizado para um Cliente; as clínicas dele são linhas de ClienteEmpresa (IpSeguranca) e os dados delas ficam no banco do cliente. A cadeia, de ponta a ponta: ClienteEmpresa.Id (guid; IpSeguranca) = SegEmpresa.SegurancaClienteEmpresaId (banco do cliente) → SegEmpresa.IdEmpresa → Clinica.IdEmpresa (chave estrangeira real) → Clinica.IdChClinica. É esse IdChClinica que aparece em Agenda.IdChClinica e em IpParametroChave.IdChave. Por isso {IdClinica} nas consultas deste documento é o Clinica.IdChClinica da clínica em que o usuário está logado, obtido por essa cadeia a partir do ClienteEmpresa.Id da sessão; o fuso (FusoHorarioOficial) e o idioma saem da mesma linha de ClienteEmpresa. O nome do campo é o da Biblioteca de Schema (DDL), SegurancaClienteEmpresaId (D-CM-071). A coluna Clinica.FusoHorario, que a DDL ainda traz, está descontinuada e nenhuma consulta deste documento a lê (D-CM-072; Log de Mudanças Estruturais, 26/10/2026). Padrões dos parâmetros por clínica: NumeroDiasRevisaoPrescricoes = 1 e PrescricaoTempoAssinatura = 7 (D-CM-006, D-CM-037).
Clínicas em que o médico atende (D-CM-066, D-CM-067). O médico vê só as clínicas do cliente em que atende, e atender, para o sistema, é ter acesso à clínica (D-CM-067): são as clínicas do cliente da sessão a que o usuário tem acesso, o mesmo critério que o Mapeamento da Agenda do Médico já usa em ClinicVisible() (RN-CIU-009), com a ligação de D-CM-065 para chegar ao IdChClinica. A aplicação monta a tabela {ClinicasDoMedico} (colunas IdEmpresa e IdChClinica) uma vez por sessão (pode ficar em cache) e a usa nos filtros de 4.1 a 4.8:
-- 1) IpSeguranca: clínicas (ClienteEmpresa) do cliente da sessão a que o usuário tem acesso
SELECT DISTINCT cpau.ClienteEmpresaId
FROM IpSeguranca.dbo.ClientePerfilAcessoUsuario cpau
JOIN IpSeguranca.dbo.UsuarioCliente uc ON uc.Id = cpau.UsuarioClienteId
JOIN IpSeguranca.dbo.ClienteEmpresa ce ON ce.Id = cpau.ClienteEmpresaId
WHERE uc.UsuarioId = @UsuarioId -- usuário autenticado
AND ce.ClienteBDId = @ClienteBDId -- banco do cliente da sessão
AND uc.RemovidoEm IS NULL
AND cpau.RemovidoEm IS NULL
AND ce.RemovidoEm IS NULL;
-- 2) Banco do cliente: de cada ClienteEmpresa para a clínica do banco => {ClinicasDoMedico}
SELECT se.IdEmpresa, c.IdChClinica
FROM SegEmpresa se
JOIN Clinica c ON c.IdEmpresa = se.IdEmpresa
WHERE se.SegurancaClienteEmpresaId IN (/* ClienteEmpresaId do passo 1 */);Onde {ClinicasDoMedico} entra: consultas e procedimentos, Agenda.IdChClinica IN (SELECT IdChClinica FROM {ClinicasDoMedico}); prescrições, pela tabela {LimitesPorClinica}, que passa a ter uma linha por clínica de {ClinicasDoMedico} (4.6); conversas, Conversa.IdEmpresa IN (SELECT IdEmpresa FROM {ClinicasDoMedico}) (4.8; Conversa.IdEmpresa = SegEmpresa.IdEmpresa, confirmado em D-CM-069; o uso de IdChClinica segue em avaliação, P-CM-052); a regra de exibir o nome da clínica é COUNT({ClinicasDoMedico}) > 1. A clínica em que o usuário está logado sempre está na lista. Fora desta regra (D-CM-067): Recurso.IdChClinica e RecursoHorario ligam-se à marcação de agendas, tarefa da recepção (só quem é recurso na clínica pode ter horário), e não influenciam quais clínicas o médico vê. Perda de acesso (D-CM-068, D-CM-070): quem perde o acesso a uma clínica deixa de ver as agendas e as prescrições dela; para consultas, prescrições, procedimentos e mensagens isso é o filtro acima. O médico não perde o acesso ao paciente (D-CM-070): “Em Tratamento”, adesão ao protocolo e busca de pacientes não têm filtro por clínica, e Paciente.IdChClinica (smallint NULL, GescomClienteAlfa) não entra em nenhuma consulta da Central; ele será filtro para o administrativo e outras funções, ainda sem especificação. A expectativa é que as agendas e prescrições da clínica sem acesso sejam redirecionadas ou canceladas; isso não está especificado.
4.1 Endpoint: GET /api/v1/cockpit/doctor/appointments
Retorna a lista de consultas do médico logado para o dia atual.
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Agenda | GescomClienteAlfa | Tabela principal — dados da agenda |
| Paciente | GescomClienteAlfa | Dados do paciente (nome, nome social) |
| PacienteFoto | GescomClienteAlfa | Foto do paciente |
| PEP | GescomClienteAlfa | Prontuário do paciente — liga o diagnóstico (PEPDiagnostico) e as tags atribuídas no prontuário (PEPProgramaApoioPaciente) ao paciente; traz a vigência dessas tags |
| PEPDiagnostico | GescomClienteAlfa | Diagnóstico oncológico do paciente |
| PEPProgramaApoioPaciente | GescomClienteAlfa | Tags atribuídas no prontuário (chave IdPEP, IdProgramaApoio) |
| ProgramaApoio | GescomClienteAlfa | Cadastro de tags da clínica (sigla, descrição, cor, telas, vigência) |
| ProgramaApoioPaciente | GescomClienteAlfa | Tags atribuídas no cadastro do paciente, com vigência |
| TermoTraducao | IpTerminologia | Tradução do modo de atendimento e do nome do status (status.name) |
| DomEstadoAgendaConsulta | IpTerminologia | Cores de cada status nos temas claro e escuro (status.colors) |
| Chave | GescomClienteAlfa | Nome curto da clínica (campo clinic; Chave.Descricao da Agenda.IdChClinica) |
| ClienteEmpresa | IpSeguranca | Idioma e fuso horário (IANA) da clínica |
Mapa de campos
| Campo | Tipo | Banco | Observação | |
|---|---|---|---|---|
id | int | Agenda.IdAgenda | ||
clinic | string | null | Agenda.IdChClinica → Chave.IdChave → Chave.Descricao | Nome curto da clínica da consulta, mesma origem do campo clinic da Agenda do Médico (Mapeamento da Agenda, 4.1). null quando o médico atende em uma só clínica, isto é, quando {ClinicasDoMedico} tem uma só linha (D-CM-066). É a mesma regra de ClinicVisible() da Agenda (“o médico tem acesso a mais de uma clínica”): a Agenda conta os ClienteEmpresa acessíveis e a Central conta as linhas de {ClinicasDoMedico}, o mesmo número enquanto toda clínica acessível tiver SegEmpresa e Clinica (D-CM-067; substitui a regra “o cliente tem mais de uma clínica” de E-CM-033) (RN-CM-032, E-CM-028) | |
startTime | horário | Agenda.DhAgendaIniUTC | só horário, convertido para o fuso e idioma da clínica | |
endTime | horário | Agenda.DhAgendaFimUTC | só horário, convertido para o fuso e idioma da clínica | |
status.domain | string | calculado | vide AppointmentStatus() | |
status.name | string | TermoTraducao.TermoValor | Termo = CodEstado do status (tabela “Status × CodEstado”, em “Domínios”), Origem = DomEstadoAgendaConsulta, Idioma = ClienteEmpresa.IdiomaOficial. Sem tradução: vai a própria chave (CodEstado) e anomalia no log técnico (DT-011) | |
status.colors.light.background / .text | char(7) | DomEstadoAgendaConsulta.CorClaroFundo / CorClaroTexto | Pela mesma chave CodEstado. Base global: iguais para todas as clínicas (DT-016) | |
status.colors.dark.background / .text | char(7) | DomEstadoAgendaConsulta.CorEscuroFundo / CorEscuroTexto | Idem. Se alguma das quatro colunas estiver NULL (são NULL na DDL), colors não vai na resposta (o front mostra chip e avatar neutros) | |
attendanceMode | string | Agenda.Atendimento -> TermoTraducao.TermoValor | Termo = Agenda.Atendimento, Origem=“Indicadores | ModoAtendimento”, Idioma=ClienteEmpresa.IdiomaOficial |
firstTime | boolean | Agenda.PrimeiraConsulta = 'S' | ’S’ = sim, ‘N’ = não | |
delayMinutes | int | Now(no fuso da clínica)-Agenda.DhAgendaIniUTC(no fuso da clínica) | Se o valor for negativo (horário previsto ainda não chegou), retorna 0 — só é positivo quando o horário previsto já passou e a consulta não foi iniciada | |
elapsedMinutes | int | DATEDIFF(MINUTE, Agenda.DhAtendimentoIniUTC, SYSDATETIMEOFFSET()) quando DhAtendimentoIniUTC não é nulo e DhAtendimentoFimUTC é nulo (consulta em atendimento) | NULL nos demais estados (D-CM-017) | |
overtime | boolean | elapsedMinutes > Agenda.Tempo (duração prevista da agenda, em minutos) | false quando elapsedMinutes é nulo ou Agenda.Tempo é nulo; sem tolerância (D-CM-017) | |
patient.id | int | Agenda.IdPaciente | ||
patient.preferredName | string | Paciente.NomeSocial | se existir, usar este como nome principal | |
patient.legalName | string | Paciente.Nome | se NomeSocial não existir, usar este como nome | |
patient.photo | url | PacienteFoto.NomeArquivo, busca IdPaciente e Padrao = ‘S’, se multiplos, retorna o mais recente | url gerada pelo MinIO | |
patient.diagnosis | array de string | PEPDiagnostico.Diagnostico para Tipo = ‘O’ e PEP.IdPaciente | retorna TODOS os diagnósticos oncológicos ativos do paciente (não só um) — o card exibe a lista completa; “ativo” = sem RemovidoEm em PEPDiagnostico e em PEP, e com PEP.DataInicioUTC até o fim de hoje no fuso da clínica (nulo = vigente desde sempre) — o diagnóstico de um PEP que só começa depois de hoje não é retornado; só o início é avaliado, PEP.DataFimUTC não filtra o diagnóstico | |
tags | array de objeto (code, description, color) | União de duas origens, ambas com join em ProgramaApoio: (1) ProgramaApoioPaciente por IdPaciente (atribuição no cadastro do paciente, tags de Finalidade D, inclusive VIP); (2) PEPProgramaApoioPaciente → PEP por PEP.IdPaciente (atribuição no prontuário, tags de Finalidade A) | code = ProgramaApoio.Sigla; description = ProgramaApoio.Descricao; color = ProgramaApoio.Cor (varchar(7), hexadecimal #RRGGBB, fundo do chip — Design System, seção 5; ausente ou inválida, o chip usa --color-neutral-lighter). Filtros comuns às tags de ProgramaApoio: (ProgramaApoio.MostrarEm & 32) = 32 (bit 6, Agendas — não o bit da Central do Médico; ver Domínios, abaixo); vigência da própria tag (ProgramaApoio.DataInicio/DataFim, ver Domínios); ProgramaApoio.RemovidoEm IS NULL. A tag VIP é exceção ao MostrarEm e à vigência da tag (RN-CM-025). Vigência da atribuição ao paciente, avaliada hoje (fuso da clínica): origem (1): ProgramaApoioPaciente.DataInicio/DataFim e ProgramaApoioPaciente.RemovidoEm IS NULL; origem (2): PEP.DataInicioUTC/DataFimUTC (datetimeoffset NULL, os campos de data válidos — PEP.DataInicio/DataFim não são lidos; nulo em DataInicioUTC = vigente desde sempre, nulo em DataFimUTC = sem término) e PEP.RemovidoEm IS NULL (PEPProgramaApoioPaciente não tem datas nem RemovidoEm; a PK é IdPEP — um registro de PEP leva uma tag). Um período vale para hoje quando a data de início é hoje ou anterior e a data de fim, se houver, é hoje ou posterior: comparam-se só as datas (dia de calendário no fuso da clínica), sem a hora, e início e fim são inclusivos (D-CM-021). Vale para todas as vigências acima; os campos datetimeoffset de PEP são convertidos para o fuso da clínica antes de tomar a data. A massa tem os dois casos de borda: fim no próprio dia (VIP do paciente 3, DataFim = 23/09/2026 00:00 — aparece) e início no próprio dia com hora (Yuki Tanaka, PEP 1107, 23/09/2026 11:56 — aparece). As duas origens separam as tags pela finalidade (A só no prontuário, D só no cadastro); se a mesma tag vier das duas, aparece uma vez. Ordem de retorno (D-CM-022): tags de Finalidade A primeiro, depois as de D; dentro de cada grupo, ordem alfabética por ProgramaApoio.Sigla. A tag VIP é uma tag administrativa, atribuída no cadastro (ProgramaApoioPaciente) como as demais; Paciente.PacienteVip não é lido (registrado na Agenda do Médico: fora de escopo até se decidir se o campo será descontinuado). Na massa de referência, VIP está em 2 linhas de ProgramaApoioPaciente (pacientes 3 e 12), e a sigla, a descrição e a cor vêm de IdProgramaApoio=1 (Cor='#80FF38'). |
Funções de cálculo
AppointmentStatus() — calcula o status da consulta a partir dos campos da Agenda. As condições são avaliadas nesta ordem, e vale a primeira que se aplicar:
| Ordem | Status retornado | Condição |
|---|---|---|
| 1 | canceled (Cancelado) | Agenda.Situacao IN (‘C’,‘D’,‘F’,‘I’,‘M’,‘O’,‘T’) |
| 2 | finished (Finalizado) | Agenda.Situacao = ‘V’ AND DhAtendimentoFimUTC IS NOT NULL |
| 3 | consultation (Em atendimento) | Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NOT NULL AND DhAtendimentoFimUTC IS NULL |
| 4 | checked (Recepcionado) | Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NULL |
| 5 | waiting (Aguardando recepção) | Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NOT NULL |
| 6 | scheduled (Agendado) | Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NULL |
A ordem resolve uma sobreposição: Situacao = 'V' com DhAtendimentoFimUTC preenchido e DhAtendimentoIniUTC NULL satisfaz checked e finished — vale finished. É a mesma precedência da Agenda do Médico (Mapeamento, 4.1), que usa esta função. Agenda.Situacao é NOT NULL.
Domínios
Status × CodEstado (IpTerminologia.DomEstadoAgendaConsulta, chave das cores e do nome traduzido): scheduled → A; waiting → D; checked → G; consultation → J; finished → M; canceled → X. É a mesma tabela da Agenda do Médico (Mapeamento, 4.1); canceled não aparece neste painel (filtros, abaixo).
TipoAgenda (domínio de Agenda.TipoAgenda) na tabela Indicadores:
| Valor | Significado |
|---|---|
| C | Consulta |
| Q | Quimioterapia |
| R | Radioterapia |
| S | Reserva de sala para assuntos não assistenciais |
ModoAtendimento (domínio de Agenda.Atendimento) na tabela Indicadores:
| Valor | Significado |
|---|---|
| P | Padrão (Presencial) |
| T | Teleatendimento |
| C | Customizado |
| R | Reservado |
SituacaoAgenda (domínio de Agenda.Situacao) na tabela Indicadores:
| Valor | Significado |
|---|---|
| A | Aberta |
| V | Confirmada (check-in realizado) |
| C | Cancelada pelo usuário |
| D | Cancelada pelo paciente |
| M | Cancelada pelo médico |
| F | Falta |
| I | Cancelado por internação |
| O | Cancelada por óbito |
| T | Transferido (cancelado) |
TipoDiagnostico (domínio de Diagnostico.Tipo):
| Valor | Significado |
|---|---|
| C | Comorbidade |
| O | Doença oncológica |
MostrarEm (domínio de ProgramaApoio.MostrarEm) — mapa de bits que controla em quais telas do sistema uma tag (ProgramaApoio) pode ser exibida; uma tag só aparece numa tela se o bit correspondente estiver ligado. Não é exclusivo deste documento — é consultado por outras funcionalidades do sistema (ex.: Agenda do Médico, RN-AGM-006); esta é a primeira vez que o domínio completo é registrado em forma de tabela num Mapeamento de Banco de Dados — qualquer alteração futura a este domínio deve ser feita apenas aqui, com as demais funcionalidades referenciando por ID em vez de repetir a tabela (Lição #10 da Skill Designer):
| Bit | Valor | Tela habilitada |
|---|---|---|
| 1 | 1 | Cabeçalho do prontuário |
| 2 | 2 | Cadastro do paciente |
| 3 | 4 | Recepção (telas de Quimioterapia e de Consulta) |
| 4 | 8 | Central do Médico |
| 5 | 16 | Confirmação de quimio / Central de atendimento — dois termos em uso para o mesmo bit; qual é o nome oficial da tela não foi decidido aqui |
| 6 | 32 | Agendas (de quimio e de consultas) — usado pelos dois endpoints deste documento (ver nota abaixo) |
| 7 | 64 | sem função definida até esta versão |
| 8 | 128 | sem função definida até esta versão |
MostrarEm = 0 (todos os bits desligados) → a tag não é exibida em nenhuma tela. Vários bits podem estar ligados ao mesmo tempo — ex.: MostrarEm = 38 = bits 2+3+6 ligados = tag exibida no cadastro do paciente, na recepção e nas agendas. Filtro usado nesta funcionalidade (painéis de Consultas e Pacientes em procedimento): (MostrarEm & 32) = 32 (bit 6 — Agendas), não o bit 4 — apesar de os dois painéis estarem dentro da tela “Central do Médico”, cada um é, na prática, uma agenda do dia (de consultas e de quimioterapia/infusão, respectivamente), e é esse o critério que rege a exibição, não o nome da tela que os hospeda. O bit 4 (Central do Médico) não é usado por nenhum endpoint deste documento; se ele se aplica a alguma outra tela do Cockpit não documentada aqui, não está confirmado.
Vigência da tag (ProgramaApoio.DataInicio/DataFim, ambos datetime NULL, opcionais) — distinta da vigência da atribuição da tag a um paciente específico (ProgramaApoioPaciente.DataInicio/DataFim no cadastro do paciente; PEP.DataInicioUTC/DataFimUTC no prontuário — Seção 4.1, campo tags). Quando preenchidos, restringem em quais dias a tag (como conceito, independente de paciente) pode aparecer — por exemplo, uma tag de campanha temporária que a clínica quer parar de usar a partir de uma data:
DataInicio | DataFim | Exibida quando |
|---|---|---|
| NULL | NULL | sempre (sem restrição de vigência) |
| preenchida | NULL | hoje >= DataInicio |
| NULL | preenchida | hoje <= DataFim |
| preenchida | preenchida | DataInicio <= hoje E hoje <= DataFim |
DataFim é inclusiva (tag continua aparecendo no próprio dia de DataFim) — mesma convenção de ProgramaApoioPaciente.DataFim (Seção 4.1). Filtro usado nesta funcionalidade: (DataInicio IS NULL OR hoje >= DataInicio) AND (DataFim IS NULL OR hoje <= DataFim), com “hoje” avaliado como data (dia de calendário no fuso da clínica; só a data conta, não a hora — D-CM-021), como descrito no campo tags (Seção 4.1); não se aplica à tag VIP (mesmo motivo do MostrarEm).
Infraestrutura de apoio
MinIO (Storage de fotos):
- Bucket global:
gemed - Bucket por ambiente do cliente: nome = banco de dados do cliente
- 1 bucket por banco de dados (cliente pode ter múltiplos bancos)
- Pasta de fotos:
FotosPacientes/dentro do bucket do cliente - Seleção da foto:
PacienteFoto.Padrao = 'S'; se múltiplas, selecionar a mais recente (futuro: vamos usar o campoCriadoEmda infraestrutura)
Internacionalização (i18n):
- Idioma da clínica:
ClienteEmpresa.IdiomaOficial(IpSeguranca), o termo segue padrão BCP 47 - Fuso horário da clínica:
ClienteEmpresa.FusoHorarioOficial(IpSeguranca) — identificador IANA (ex.:America/Sao_Paulo); campo novo, ver “Campos novos”, ao final - Traduções: tabela
TermoTraducao(IpTerminologia) usa chave composta por (Termo, Origem, Idioma)- Origem: nome da tabela de origem ou
Indicadores|<NomeIndicador>quando o domínio está na tabela Indicadores - Idioma: idioma da clínica atual (
ClienteEmpresa.IdiomaOficial; DT-012) - Termo: o termo usado como chave na tabela de origem
- Sem tradução no idioma da clínica: vai a própria chave (
Termo) e o back-end registra anomalia no log técnico (Termo,Origem,Idioma); não há queda para pt-BR nem para outro idioma (DT-011)
- Origem: nome da tabela de origem ou
Filtros do endpoint
Agenda.IdChRecurso = {IdChProfissional do médico logado}— apenas consultas do médico- Escopo de clínicas (D-CM-066, RN-CM-032):
Agenda.IdChClinica IN (SELECT IdChClinica FROM {ClinicasDoMedico})— a lista reúne as consultas das clínicas em que o médico atende (Seção 4, bloco “Clínicas em que o médico atende”; D-CM-067); “hoje” e os horários seguem o fuso da clínica em que o usuário está logado (ClienteEmpresa.FusoHorarioOficial, RN-AGM-018) Agenda.TipoAgenda = 'C'- Agendas de consultaPaciente.Paciente <> 'B'(viaAgenda.IdPaciente) — exclui os registros de bloqueio de horário feitos pela Recepção, gravados como agenda de consulta com o paciente reservado “B” (RN-CM-030). A Agenda do Médico lê esses mesmos registros e os exibe emblocks(RN-AGM-019); esta funcionalidade só os excluiAgenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica)— apenas consultas do dia atualAgenda.RemovidoEm IS NULL— exclusão lógica (regra de todo o sistema, ver o início desta Seção)- Toggle “Pendentes”:
Agenda.Situacao IN ('A','V')ANDDhAtendimentoFimUTC IS NULL— exclui canceladas e finalizadas - Toggle “Todas”: inclui finalizadas (canceladas não aparecem no painel — apenas finalizadas esmaecidas)
(ProgramaApoio.MostrarEm & 32) = 32— restringe as tags exibidas (campotags, acima) às habilitadas para agendas (RN-CM-025); não se aplica à tagvip(exceção de RN-CM-025; ver nota de correção em Mapa de Campos, acima, sobre a origem de cor/descrição).(ProgramaApoio.DataInicio IS NULL OR hoje >= ProgramaApoio.DataInicio) AND (ProgramaApoio.DataFim IS NULL OR hoje <= ProgramaApoio.DataFim)— restringe pela vigência da própria tag (RN-CM-025); não se aplica à tagvip; distinto do filtro de vigência da atribuição ao paciente (ProgramaApoioPaciente, já aplicado na origem do campotags).
4.2 Endpoint: GET /api/v1/cockpit/doctor/kpis/appointments-today
Retornar o indicador de Consultas Hoje
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Agenda | GescomClienteAlfa | Tabela principal — dados da agenda |
| Paciente | GescomClienteAlfa | Só para o filtro que exclui registros de bloqueio (Paciente.Paciente <> 'B', RN-CM-030) |
Mapa de campos
| Campo | Tipo | Banco |
|---|---|---|
total | int | count(Agenda.Situacao IN (‘A’, ‘V’)) |
finished | int | count(Agenda.Situacao=‘V’, Agenda.DhAtendimentoFimUTC IS NOT NULL) |
pending | int | count(Agenda.Situacao IN (‘A’, ‘V’), Agenda.DhAtendimentoFimUTC IS NULL) |
delayed | int | count(Agenda.Situacao IN (‘A’, ‘V’), Agenda.DhAtendimentoFimUTC IS NULL, Agenda.DhAtendimentoIniUTC IS NULL, Now(no fuso da clínica)-Agenda.DhAgendaIniUTC(no fuso da clinica)>0) — só consultas ainda não iniciadas; a consulta em atendimento (DhAtendimentoIniUTC preenchido) é pendente, mas não é atrasada |
Domínios
** os mesmos do endpoint acima
Filtros do endpoint
Agenda.IdChRecurso = {IdChProfissional do médico logado}— apenas consultas do médico- Escopo de clínicas (D-CM-066, RN-CM-032):
Agenda.IdChClinica IN (SELECT IdChClinica FROM {ClinicasDoMedico})— a lista reúne as consultas das clínicas em que o médico atende (Seção 4, bloco “Clínicas em que o médico atende”; D-CM-067); “hoje” e os horários seguem o fuso da clínica em que o usuário está logado (ClienteEmpresa.FusoHorarioOficial, RN-AGM-018) Agenda.TipoAgenda = 'C'- agendas de consultaPaciente.Paciente <> 'B'(viaAgenda.IdPaciente) — exclui os registros de bloqueio de horário feitos pela Recepção de todos os números do KPI (RN-CM-030), mesmo filtro da Seção 4.1Agenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica)— apenas consultas do dia atualAgenda.RemovidoEm IS NULL— exclusão lógica (regra de todo o sistema, ver o início desta Seção)
4.3 Endpoint: [GET] /api/v1/cockpit/doctor/procedures
`{ "procedures":
[ { "id": 1234,
"patient":
{ "id": 567,
"preferredName": "",
"legalName": "Roberto Oliveira"
},
"clinic": "Oncocentro Sul",
"location": "Sala de Infusão 2",
"status": "administering",
"startTime": "09:30",
"firstTime": false,
"progress": 65,
"mine": true,
"tags": [ { "code": "LC", "description": "Linha de cuidados", "color": "#FFD6D1" } ]
}
]
}`
Retorna a lista de pacientes em procedimentos no dia atual.
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Agenda | GescomClienteAlfa | Tabela principal — dados da agenda |
| Paciente | GescomClienteAlfa | Dados do paciente (nome, nome social) |
| PacienteFoto | GescomClienteAlfa | Foto do paciente |
| Prescricao | GescomClienteAlfa | Prescrição do procedimento (IdAgenda): código, médico e TempoAplicacao (base do progress) |
| PEP / PEPProgramaApoioPaciente / ProgramaApoio / ProgramaApoioPaciente | GescomClienteAlfa | Tags do paciente (campo tags), como em 4.1 |
| TermoTraducao | IpTerminologia | Tradução do modo de atendimento e do nome do status (status.name) |
| DomEstadoAgendaProcedimento | IpTerminologia | Cores de cada status do procedimento nos temas claro e escuro (status.colors) |
| Chave | GescomClienteAlfa | Nome curto da clínica (campo clinic; Chave.Descricao da Agenda.IdChClinica) |
| ClienteEmpresa | IpSeguranca | Idioma e fuso horário (IANA) da clínica |
Mapa de campos
| Campo | Tipo | Banco | Observação | |
|---|---|---|---|---|
id | int | Prescricao.IdPrescricao | ||
clinic | string | null | Prescricao.IdAgenda → Agenda.IdChClinica → Chave.Descricao | Nome curto da clínica do procedimento, mesma origem e mesma regra de appointments.clinic (4.1); null quando o médico atende em uma só clínica (RN-CM-032, D-CM-061, D-CM-066) | |
prescriptionCode | string | Prescricao.Identificacao | ||
location | string | Prescricao.IdAgenda->Agenda.IdUAtendimento->UnidadeAtendimento.Descricao + Agenda.IdChRecurso->Chave.Descricao | IdUAtendimento pode ser NULL | |
startTime | horário | se finalizado (Situacao=‘V’ AND DhAtendimentoFimUTC IS NOT NULL — mesma condição de finished em ProcedureStatus()), Agenda.DhAtendimentoFimUTC(no fuso da clínica); senão se Situacao=‘V’, Agenda.DhAtendimentoIniUTC(no fuso da clínica); senão Agenda.DhAgendaIniUTC(no fuso da clínica) | horário “HH:mm” no fuso da clínica (D-CM-042), sem data nem fuso na cadeia. Campo continua chamado startTime por herança do endpoint já existente, mas passa a carregar o horário de término quando o procedimento está Finalizado (RN-CM-026, 01-Definição v4.34) — nome mantido para não alterar o contrato já em uso; uma reformulação futura do contrato pode considerar um nome neutro (ex.: displayTime), fora do escopo desta revisão. DhAtendimentoIniUTC marca o início real do atendimento (preparo do paciente, pré-medicações etc.), anterior ao início da infusão propriamente dita; DhInfusaoIniUTC/DhInfusaoFimUTC (usados só em ProcedureStatus(), não neste campo) marcam início/fim do primeiro medicamento do protocolo, que ocorre depois desse preparo — startTime usa corretamente o horário de atendimento, não o de infusão | |
firstTime | boolean | Agenda.PrimeiraConsulta = 'S' | mesmo campo e mesma origem de appointments.firstTime (4.1); o front mostra o ícone de 1ª Consulta (RN-CM-028, D-CM-029) | |
status.domain | string | calculado | vide ProcedureStatus(), avaliado em ordem; valores scheduled, waiting, checked, preparation, administering, administered, finished, canceled (D-CM-030, D-CM-074) | |
status.name | string | TermoTraducao.TermoValor | Termo = CodEstado do status (tabela “Status × CodEstado”, em “Domínios”), Origem = DomEstadoAgendaProcedimento, Idioma = ClienteEmpresa.IdiomaOficial. Sem tradução: vai a própria chave (CodEstado) e anomalia no log técnico (DT-011) | |
status.colors.light.background / .text | char(7) | DomEstadoAgendaProcedimento.CorClaroFundo / CorClaroTexto | Pela mesma chave CodEstado. Base global: iguais para todas as clínicas (DT-016) | |
status.colors.dark.background / .text | char(7) | DomEstadoAgendaProcedimento.CorEscuroFundo / CorEscuroTexto | Idem. Se alguma das quatro colunas estiver NULL (são NULL na DDL), colors não vai na resposta (o front mostra chip e avatar neutros) | |
progress | int | CAST(ROUND(DATEDIFF(MINUTE, Agenda.DhAtendimentoIniUTC, SYSDATETIMEOFFSET()) * 100.0 / NULLIF(Prescricao.TempoAplicacao, 0), 0) AS int) (TempoAplicacao é numeric(6,0), em minutos; arredondado ao inteiro mais próximo; NULLIF evita a divisão por zero e devolve nulo) | NULL quando Prescricao.TempoAplicacao é nulo ou zero — o front não desenha a barra. Substitui Agenda.Tempo como base (D-CM-015) | |
mine | boolean | Prescricao.IdChProfissionalMed={IdChProfissional do médico logado} | ||
patient.id | int | Prescricao.IdPaciente | ||
patient.preferredName | string | Paciente.NomeSocial | se existir, usar este como nome principal | |
patient.legalName | string | Paciente.Nome | se NomeSocial não existir, usar este como nome | |
patient.photo | url | PacienteFoto.NomeArquivo, busca IdPaciente e Padrao = ‘S’, se multiplos, retorna o mais recente | url gerada pelo MinIO | |
tags | array de objeto (code, description, color) | mesma origem, mesmos campos e mesmos filtros de appointments.tags (Seção 4.1): duas origens (cadastro do paciente e prontuário), MostrarEm pelo bit de agendas (não o da Central do Médico, mesmo este painel estando dentro dela), vigência da tag, vigência da atribuição e RemovidoEm |
Funções de cálculo
ProcedureStatus() — calcula o status do procedimento a partir dos campos da Agenda. As condições são avaliadas nesta ordem, e vale a primeira que se aplicar (D-CM-030):
| Ordem | Status retornado | Condição |
|---|---|---|
| 1 | canceled (Cancelado) | Agenda.Situacao IN (‘C’,‘D’,‘F’,‘I’,‘M’,‘O’,‘T’) |
| 2 | finished (Finalizado) | Agenda.Situacao = ‘V’ AND DhAtendimentoFimUTC IS NOT NULL |
| 3 | administered (Completo) | Agenda.Situacao = ‘V’ AND DhInfusaoFimUTC IS NOT NULL AND DhAtendimentoFimUTC IS NULL |
| 4 | administering (Em aplicação) | Agenda.Situacao = ‘V’ AND DhInfusaoIniUTC IS NOT NULL AND DhInfusaoFimUTC IS NULL |
| 5 | preparation (Em preparo) | Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NOT NULL AND DhInfusaoIniUTC IS NULL |
| 6 | checked (Recepcionado) | Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NULL |
| 7 | waiting (Aguardando recepção) | Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NOT NULL |
| 8 | scheduled (Agendado) | Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NULL |
A ordem resolve as sobreposições: finished vale mesmo com o fim da infusão vazio (23 linhas da massa de referência têm alta e DhInfusaoFimUTC NULL); com DhInfusaoFimUTC preenchido o procedimento nunca é administering; com início de infusão preenchido e DhAtendimentoIniUTC NULL vale administering, não checked. O valor de contrato do status 3 é administered (D-CM-074; CodEstado ASD em DomEstadoAgendaProcedimento). Agenda.Situacao é NOT NULL.
Domínios
Status × CodEstado (IpTerminologia.DomEstadoAgendaProcedimento, chave das cores e do nome traduzido): scheduled → SCH; waiting → WTI; checked → CKD; preparation → PRP; administering → ADM; administered → ASD; finished → FNS; canceled → CNL. As cores de SCH, WTI, CKD, FNS e CNL são as mesmas dos status equivalentes da consulta; PRP, ADM e ASD têm cores próprias (Design System, seção 4).
TipoAgenda (domínio de Agenda.TipoAgenda) na tabela Indicadores:
| Valor | Significado |
|---|---|
| C | Consulta |
| Q | Quimioterapia |
| R | Radioterapia |
| S | Reserva de sala para assuntos não assistenciais |
SituacaoAgenda (domínio de Agenda.Situacao) na tabela Indicadores:
| Valor | Significado |
|---|---|
| A | Aberta |
| V | Confirmada (check-in realizado) |
| C | Cancelada pelo usuário |
| D | Cancelada pelo paciente |
| M | Cancelada pelo médico |
| F | Falta |
| I | Cancelado por internação |
| O | Cancelada por óbito |
| T | Transferido (cancelado) |
Infraestrutura de apoio
MinIO (Storage de fotos):
- Bucket global:
gemed - Bucket por ambiente do cliente: nome = banco de dados do cliente
- 1 bucket por banco de dados (cliente pode ter múltiplos bancos)
- Pasta de fotos:
FotosPacientes/dentro do bucket do cliente - Seleção da foto:
PacienteFoto.Padrao = 'S'; se múltiplas, selecionar a mais recente (futuro: vamos usar o campoCriadoEmda infraestrutura)
Internacionalização (i18n):
- Idioma da clínica:
ClienteEmpresa.IdiomaOficial(IpSeguranca), o termo segue padrão BCP 47 - Fuso horário da clínica:
ClienteEmpresa.FusoHorarioOficial(IpSeguranca) — identificador IANA (ex.:America/Sao_Paulo); campo novo, ver “Campos novos”, ao final - Traduções: tabela
TermoTraducao(IpTerminologia) usa chave composta por (Termo, Origem, Idioma)- Origem: nome da tabela de origem ou
Indicadores|<NomeIndicador>quando o domínio está na tabela Indicadores - Idioma: idioma da clínica atual (
ClienteEmpresa.IdiomaOficial; DT-012) - Termo: o termo usado como chave na tabela de origem
- Sem tradução no idioma da clínica: vai a própria chave (
Termo) e o back-end registra anomalia no log técnico (Termo,Origem,Idioma); não há queda para pt-BR nem para outro idioma (DT-011)
- Origem: nome da tabela de origem ou
Filtros do endpoint
Prescricao.IdAgenda IS NOT NULL- Escopo de clínicas (D-CM-066, RN-CM-032):
Agenda.IdChClinica IN (SELECT IdChClinica FROM {ClinicasDoMedico})— a lista reúne os procedimentos das clínicas em que o médico atende (Seção 4, bloco “Clínicas em que o médico atende”; D-CM-067); “hoje” e os horários seguem o fuso da clínica em que o usuário está logado (RN-AGM-018) Agenda.TipoAgenda IN ('Q', 'R')- Agendas de quimio, radioAgenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica)— apenas procedimentos do dia atualAgenda.RemovidoEm IS NULL— exclusão lógica (regra de todo o sistema, ver o início desta Seção)- Toggle “Meus”: Prescricao.IdChProfissionalMed={IdChProfissional do médico logado}
- Toggle “Todos”: sem restrições
(ProgramaApoio.MostrarEm & 32) = 32e o filtro de vigência deProgramaApoio.DataInicio/DataFim— mesmos filtros de tags do painel de Consultas, ver Seção 4.1.
4.4 Endpoint GET /api/v1/cockpit/doctor/kpis/procedures-today
GET] /api/v1/cockpit/doctor/kpis/procedures-today
{ "total": 8, "inProgress": 2, "waiting": 4, "scheduled": 2 }
Função: Retornar o indicador de Procedimentos Hoje
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Agenda | GescomClienteAlfa | Tabela principal — dados da agenda |
| Paciente | GescomClienteAlfa | Dados do paciente (nome, nome social) |
| PacienteFoto | GescomClienteAlfa | Foto do paciente |
| Prescricao | GescomClienteAlfa | Diagnóstico oncológico do paciente |
| TermoTraducao | IpTerminologia | Tradução do modo de atendimento |
| ClienteEmpresa | IpSeguranca | Idioma e fuso horário da clínica |
Mapa de campos
| Campo | Tipo | Banco |
|---|---|---|
total | int | count(Agenda.Situacao IN (‘A’, ‘V’)) — inclui os procedimentos já completos e finalizados (D-CM-038); os três subtotais não precisam somar o total |
inProgress | int | count(ProcedureStatus()=administering) |
waiting | int | count(ProcedureStatus()=waiting OR checked OR preparation) |
scheduled | int | count(ProcedureStatus()=scheduled) |
Funções de cálculo
ProcedureStatus() — calcula o status do procedimento a partir dos campos da Agenda. As condições são avaliadas nesta ordem, e vale a primeira que se aplicar (D-CM-030):
| Ordem | Status retornado | Condição |
|---|---|---|
| 1 | canceled (Cancelado) | Agenda.Situacao IN (‘C’,‘D’,‘F’,‘I’,‘M’,‘O’,‘T’) |
| 2 | finished (Finalizado) | Agenda.Situacao = ‘V’ AND DhAtendimentoFimUTC IS NOT NULL |
| 3 | administered (Completo) | Agenda.Situacao = ‘V’ AND DhInfusaoFimUTC IS NOT NULL AND DhAtendimentoFimUTC IS NULL |
| 4 | administering (Em aplicação) | Agenda.Situacao = ‘V’ AND DhInfusaoIniUTC IS NOT NULL AND DhInfusaoFimUTC IS NULL |
| 5 | preparation (Em preparo) | Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NOT NULL AND DhInfusaoIniUTC IS NULL |
| 6 | checked (Recepcionado) | Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NULL |
| 7 | waiting (Aguardando recepção) | Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NOT NULL |
| 8 | scheduled (Agendado) | Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NULL |
A ordem resolve as sobreposições: finished vale mesmo com o fim da infusão vazio (23 linhas da massa de referência têm alta e DhInfusaoFimUTC NULL); com DhInfusaoFimUTC preenchido o procedimento nunca é administering; com início de infusão preenchido e DhAtendimentoIniUTC NULL vale administering, não checked. O valor de contrato do status 3 é administered (D-CM-074; CodEstado ASD em DomEstadoAgendaProcedimento). Agenda.Situacao é NOT NULL.
Domínios
TipoAgenda (domínio de Agenda.TipoAgenda) na tabela Indicadores:
| Valor | Significado |
|---|---|
| C | Consulta |
| Q | Quimioterapia |
| R | Radioterapia |
| S | Reserva de sala para assuntos não assistenciais |
SituacaoAgenda (domínio de Agenda.Situacao) na tabela Indicadores:
| Valor | Significado |
|---|---|
| A | Aberta |
| V | Confirmada (check-in realizado) |
| C | Cancelada pelo usuário |
| D | Cancelada pelo paciente |
| M | Cancelada pelo médico |
| F | Falta |
| I | Cancelado por internação |
| O | Cancelada por óbito |
| T | Transferido (cancelado) |
Infraestrutura de apoio
Internacionalização (i18n):
- Idioma da clínica:
ClienteEmpresa.IdiomaOficial(IpSeguranca), o termo segue padrão BCP 47 - Fuso horário da clínica:
ClienteEmpresa.FusoHorarioOficial(IpSeguranca) — identificador IANA (ex.:America/Sao_Paulo); campo novo, ver “Campos novos”, ao final - Traduções: tabela
TermoTraducao(IpTerminologia) usa chave composta por (Termo, Origem, Idioma)- Origem: nome da tabela de origem ou
Indicadores|<NomeIndicador>quando o domínio está na tabela Indicadores - Idioma: idioma da clínica atual (
ClienteEmpresa.IdiomaOficial; DT-012) - Termo: o termo usado como chave na tabela de origem
- Sem tradução no idioma da clínica: vai a própria chave (
Termo) e o back-end registra anomalia no log técnico (Termo,Origem,Idioma); não há queda para pt-BR nem para outro idioma (DT-011)
- Origem: nome da tabela de origem ou
Filtros do endpoint
- Escopo de clínicas (D-CM-066, RN-CM-032):
Agenda.IdChClinica IN (SELECT IdChClinica FROM {ClinicasDoMedico})— o indicador conta os procedimentos das clínicas em que o médico atende, o mesmo conjunto do painel (4.3); “hoje” no fuso da clínica em que o usuário está logado Agenda.TipoAgenda IN ('Q', 'R')- Agendas de quimio, radioAgenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica)— apenas procedimentos do dia atualAgenda.RemovidoEm IS NULL— exclusão lógica (regra de todo o sistema, ver o início desta Seção)- `Prescricao.IdChProfissionalMed={IdChProfissional do médico logado} - só os meus pacientes
4.5 Endpoint [GET] /api/v1/cockpit/doctor/kpis/in-treatment
/api/v1/cockpit/doctor/kpis/in-treatment
`{ "inTreatment": 43,
"nonAdherent": 2 }`
Função: Retornar o indicador de Em Tratamento
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Agenda | GescomClienteAlfa | Agendamento real do C1D1 (Agenda.DhAgendaIniUTC, via Prescricao.IdAgenda) — condição 1 |
| Paciente | GescomClienteAlfa | Dados do paciente (nome, nome social) |
| Prescricao | GescomClienteAlfa | Diagnóstico oncológico do paciente; data real de cada prescrição vinculada a protocolo |
| PrescricaoProtocolo | GescomClienteAlfa | Vínculo entre cada prescrição real e o protocolo/ciclo/sessão aplicados (Ciclo, Sessao) — base das condições 2 e 3 de TreatmentPlanAdherenceCount() |
| Protocolo | GescomClienteAlfa | ToleranciaEntreSessoes/ToleranciaEntreCiclos (margens de tolerância, ver função abaixo) |
| ProtocoloGrupo | GescomClienteAlfa | SessoesSugerido — string de dias sugeridos por ciclo (ex. “1,8,15”); o médico informa “é a sessão N do ciclo” e o sistema copia o N-ésimo valor para PrescricaoProtocolo.Sessao (fora deste endpoint) |
| PEP | GescomClienteAlfa | Vínculo prontuário↔paciente (IdPaciente) — usado só para localizar o plano terapêutico do paciente (condição 1) |
| PEPProjetoTerapeutico | GescomClienteAlfa | Plano terapêutico do paciente, quando existe — condição 1 só se aplica se houver um para o mesmo protocolo |
| PEPProjetoTerapeuticoProtocolo | GescomClienteAlfa | Vínculo entre o plano terapêutico e o protocolo (IdProtocolo) — usado para checar se existe plano para o protocolo da prescrição real |
| PEPProjetoTerapeuticoProtocoloProgramacao | GescomClienteAlfa | DataEstimada do C1D1 planejado (Ciclo=1/Sessao=1) — comparada ao C1D1 real na condição 1 |
| TermoTraducao | IpTerminologia | Tradução do modo de atendimento |
| IpParametro | GescomClienteAlfa | Definição dos parâmetros TempoPacienteAtivoAgenda/TempoPacienteAtivoPrescricao (janela de atividade, em dias) — PatientInTreatmentCount() |
| IpParametroChave | GescomClienteAlfa | Valor de cada parâmetro por clínica (IdChave = Clinica.IdChClinica, Valor em dias) — PatientInTreatmentCount() |
Mapa de campos
| Campo | Tipo | Banco |
|---|---|---|
inTreatment | int | PatientInTreatmentCount() |
nonAdherent | int | TreatmentPlanAdherenceCount() |
Funções de cálculo
PatientInTreatmentCount() — calcula a quantidade de pacientes em tratamento do médico
- refere-se aos pacientes com agenda realizada e/ou prescrição registrada dentro da janela de atividade da clínica (RN-CM-024, padrão 180 dias, usado também quando o parâmetro não existe para a clínica)
- essa janela vem de dois parâmetros da clínica, em dias, que dizem o tempo máximo de inatividade para considerar o paciente inativo:
- quanto às agendas:
IpParametro.TempoPacienteAtivoAgenda->IpParametroChave.Valor(dias) - quanto às prescrições:
IpParametro.TempoPacienteAtivoPrescricao->IpParametroChave.Valor(dias)
- quanto às agendas:
- Nas agendas obter as agendas com:
- Situação ‘V’ e
Agenda.RemovidoEm IS NULL; paciente comPaciente.RemovidoEm IS NULL(nas duas partes da consulta) - DhAgendaIniUTC > Hoje()-IpParametroChave.Valor (onde IpParametro=TempoPacienteAtivoAgenda)
- Situação ‘V’ e
- Nas prescrições obter as prescrições com:
- Situação <> ‘C’ (canceladas — ver “Domínio: Situação da Prescrição” abaixo)
- Data > Hoje()-IpParametroChave.Valor (onde IpParametro=TempoPacienteAtivoPrescricao)
-
A query fica mais ou menos assim:
SELECT DISTINCT p.IdChProfissional, p.IdPaciente FROM paciente p INNER JOIN agenda a ON a.IdPaciente = p.IdPaciente AND a.IdChRecurso = p.IdChProfissional WHERE a.Situacao = 'V' AND a.RemovidoEm IS NULL AND p.RemovidoEm IS NULL AND a.DhAgendaIniUTC > dateadd(day, -COALESCE( (SELECT ipc.Valor FROM IpParametroChave ipc WHERE ipc.IdParametro = 'TempoPacienteAtivoAgenda' AND ipc.IdChave = {IdClinica}), 180), -- default 180 dias se IpParametro/IpParametroChave não existir getdate()) -- janela de atividade das agendas, em dias UNION SELECT DISTINCT p.IdChProfissional , p.IdPaciente FROM Paciente p INNER JOIN Prescricao p2 on p2.IdPaciente = p.IdPaciente AND p.IdChProfissional = p2.IdChProfissionalMed WHERE p2.Situacao <> 'C' AND p.RemovidoEm IS NULL AND p2.[Data] > dateadd(day, -COALESCE( (SELECT ipc.Valor FROM IpParametroChave ipc WHERE ipc.IdParametro = 'TempoPacienteAtivoPrescricao' AND ipc.IdChave = {IdClinica}), 180), -- default 180 dias se IpParametro/IpParametroChave não existir getdate()) -- janela de atividade das prescrições, em diasClínica dos parâmetros (D-CM-063):
{IdClinica}é oClinica.IdChClinicada clínica em que o médico está logado (cadeia descrita no início desta Seção, D-CM-065). O indicador conta pacientes do médico, que não pertencem a uma só clínica; valem os parâmetros da clínica logada.
Comportamento se o parâmetro não existir para a clínica: o sistema assume 180 dias (RN-CM-024) — ver COALESCE na query acima. Os dois parâmetros já existem em produção; seed de referência, com 180 dias por clínica, em Infra-estrutura/(BD-M) Dados incluídos obrigatórios.md.
Então conta a quantidade de pacientes do profissional logado.
TreatmentPlanAdherenceCount() — calcula os pacientes cujo tratamento se desvia do planejado no protocolo. A base é a prescrição real: entra na contagem todo paciente do médico com ao menos uma prescrição vinculada a protocolo (PrescricaoProtocolo) — não depende de um plano terapêutico formal (PEPProjetoTerapeutico) ter sido criado, já que nem todo médico chega a criar um. A única exceção é a condição 1, abaixo, que só se aplica quando um plano existe. Um paciente conta como não aderente quando QUALQUER UMA das três condições abaixo é verdadeira (lógica OU — basta uma delas estar fora do parametrizado):
Exclusão lógica: a contagem ignora pacientes com Paciente.RemovidoEm preenchido, planos terapêuticos cujo PEP tem RemovidoEm preenchido e, no C1D1 real, agendas (via Prescricao.IdAgenda) com Agenda.RemovidoEm preenchido.
Âncora de cada ciclo: para cada Ciclo N de um paciente/protocolo, a “âncora do ciclo” é a linha de PrescricaoProtocolo daquele Ciclo com o menor valor de Sessao (a 1ª sessão do ciclo, conforme ProtocoloGrupo.SessoesSugerido), unida a Prescricao (via IdPrescricao) para obter a data real. A âncora do Ciclo 1 é o “C1D1” — usado sozinho na condição 1. A condição 3 abaixo usa a âncora de CADA ciclo, não só a do Ciclo 1 (a condição 2 não depende de âncora nenhuma).
-
Condição 1 — C1D1 real diverge do C1D1 planejado (só quando há plano terapêutico): aplica-se apenas se existir um plano terapêutico do paciente para o mesmo protocolo da prescrição real — isto é, uma linha de
PEPProjetoTerapeuticoProtocolocujoIdProtocolobate com oIdProtocolodePrescricaoProtocoloe cujoIdPEPpertence aoPEPdo paciente (PEP.IdPaciente). Quando não existe esse plano para o protocolo, a condição simplesmente não se aplica ao paciente (não pesa nem a favor nem contra a adesão). Quando existe: compara-se a data agendada do C1D1 real (Agenda.DhAgendaIniUTC, viaPrescricao.IdAgendado C1D1 dePrescricaoProtocolo) com a data estimada do C1D1 do plano (PEPProjetoTerapeuticoProtocoloProgramacao.DataEstimadana linhaCiclo=1/Sessao=1daquelePEPProjetoTerapeuticoProtocolo); diferença maior queProtocolo.ToleranciaEntreSessoesconta como não aderente. -
Condição 2 — prescrição esperada não realizada: para qualquer linha de
PrescricaoProtocolodo paciente cujaPrescricao.Datajá passou e cujaPrescricao.Situacaoestá em('P','G','A')— ou seja, a sessão estava agendada para uma data que já passou, mas a prescrição segue em um status de “ainda por realizar” (Confirma Prescrição, Gerada ou Admitida — ver domínio abaixo), sem nunca ter sido efetivamente concluída (Q/F) — conta como não aderente. Não conta uma sessão cancelada (C) — cancelamento é uma decisão deliberada, não uma omissão, e por isso foi excluído desta condição nesta versão (até então,Centrava indevidamente na lista). Mecânica quanto ao restante inalterada desde a v4.30 — não dependia de plano terapêutico nem antes. -
Condição 3 — sessão realizada diverge da data esperada: tem duas partes, conforme a linha de
PrescricaoProtocoloseja ou não a âncora do seu próprio ciclo:- 3a — sessão comum (não é a âncora do ciclo):
diasDecorridos = Prescricao.Data (da linha) − Prescricao.Data (âncora do MESMO Ciclo); compara-se diretamente ao valor deSessaoda própria linha (o dia bruto deSessoesSugeridodaquela sessão): seABS(diasDecorridos − Sessao)for maior queProtocolo.ToleranciaEntreSessoes, conta como não aderente. - 3b — início de um novo ciclo (a linha É a âncora do seu ciclo, e o ciclo não é o 1º):
diasDecorridos = Prescricao.Data (âncora do Ciclo N) − Prescricao.Data (âncora do Ciclo N−1); compara-se aProtocolo.IntervaloCiclosEmDias: seABS(diasDecorridos − IntervaloCiclosEmDias)for maior queProtocolo.ToleranciaEntreCiclos, conta como não aderente. Não se aplica à âncora do Ciclo 1 (C1D1), já coberta pela condição 1.
Exemplo:
SessoesSugerido = "1,8,15",IntervaloCiclosEmDias = 21. C1D1 (Ciclo 1, âncora) em 01/01. Ciclo 1/Sessao 8 (3a) realizada em 09/01:diasDecorridos = 8,ABS(8−8) = 0→ aderente. Âncora do Ciclo 2 (3b) realizada em 23/01:diasDecorridos (vs. âncora do Ciclo 1) = 22,ABS(22−21) = 1→ compara comToleranciaEntreCiclos. Ciclo 2/Sessao 8 (3a) realizada em 31/01:diasDecorridos (vs. âncora do Ciclo 2 = 23/01) = 8,ABS(8−8) = 0→ aderente. - 3a — sessão comum (não é a âncora do ciclo):
Como
Sessaoé definida (fora do escopo deste endpoint, documentado aqui só como contexto): ao criar uma prescrição, o médico informa “é a sessão N do ciclo X” de um protocolo; o sistema busca o N-ésimo valor deProtocoloGrupo.SessoesSugerido(ex.: N=2 em"1,8,15"→ valor 8) e grava esse valor bruto emPrescricaoProtocolo.Sessao(e X emCiclo) — por issoSessaoreinicia a cada ciclo, não é cumulativo desde o C1D1. Existe também um processo de criação em massa: ao definir o protocolo no plano terapêutico com o número de ciclos do tratamento, o sistema gera de uma vez todas as prescrições cruzando ciclo e sessão — cada uma com sua própria configuração de medicamentos/procedimentos (não é atribuição meramente classificatória).
[PROPOSTA] Colunas novas em
Protocolo(GescomClienteAlfa):ToleranciaEntreSessoeseToleranciaEntreCiclos(int, dias de tolerância — a primeira para desvios dentro do mesmo ciclo, a segunda para desvios que atravessam fronteira de ciclo). Substituem a proposta anterior de uma coluna única (ToleranciaDiasAdesao, v4.30) — são dois parâmetros distintos, não um só. Não existem hoje na Biblioteca de Schema (DDL) nem noEsquemaGemed21.csv— a criar antes da implementação deste KPI.
Domínio: Situação da Prescrição (Prescricao.Situacao, GescomClienteAlfa)
Situacao é char(1) NOT NULL em Prescricao (confirmado na Biblioteca de Schema — DDL); a DDL não traz um CHECK explícito listando os valores permitidos, então o domínio abaixo foi informado pelo negócio, fora da DDL (origem no Histórico de Versões). É um fluxo próprio da prescrição, distinto da situação da agenda associada (domínio SituacaoAgenda, já mapeado neste documento) — uma prescrição pode estar numa situação diferente da agenda que a originou, e as duas não avançam necessariamente juntas.
| Situação | Nome | Descrição |
|---|---|---|
P | Confirma Prescrição | Precede a situação G; ocorre quando um agendamento é feito com a opção “Sem Prescrição” — o Gemed cria junto a prescrição nesta situação (com o protocolo e CID do agendamento), como pendência para o médico revisar e confirmar medicamentos/doses. |
G | Gerada | Situação logo após o médico salvar (ou confirmar, quando veio de agenda “Sem Prescrição”) a prescrição; permanece “Gerada” mesmo depois de agendada. |
A | Admitida | A agenda vinculada à prescrição teve a recepção confirmada (paciente recepcionado). Prescrição fica disponível para a enfermagem no processo de Confirmação de Quimioterapia (ou Central de Atendimentos). |
Q | Confirmada/Finalizada | Informada pela enfermagem após concluída a infusão/quimioterapia (atendimento finalizado). Enquanto não confirmada, a prescrição não cai no faturamento. Nesta situação, fica disponível tanto para a enfermagem (pode desfazer a confirmação, se necessário) quanto para o faturamento (Consulta de Folha de Gastos, aba “Prescrições para Faturamento”). |
F | Faturada | Quando o faturamento termina de lançar gastos e ajustes na fatura (fatura marcada como “Fecha Fatura”). |
O | Aguardando Orçamento | Disparada pelo botão de solicitar orçamento no prontuário; prescrições nesta situação entram no processo de Orçamento para o faturamento. |
E | Atendimento Externo | Substitui a situação G logo após o médico salvar a prescrição, quando o convênio do paciente está configurado para permitir essa opção. Indica que o paciente fará o tratamento/quimioterapia fora da clínica — a prescrição não segue para as demais situações (não fica disponível para agendamento, enfermagem ou faturamento). |
C | Cancelada | Cancelável pelo prontuário (que tem filtro próprio para consultar prescrições canceladas) ou ao cancelar a agenda do paciente. |
Motivador de documentar aqui: o KPI “Em Tratamento” (PatientInTreatmentCount(), acima) já filtra prescrições por Situacao <> 'C', e TreatmentPlanAdherenceCount() filtra por Situacao IN ('P','G','A') (excluindo C, cancelada, desde esta versão) para detectar prescrição passada não realizada — este domínio documenta o que cada um desses códigos significa, em vez de deixá-los como letras sem contexto no meio das funções de cálculo.
Filtros do endpoint
Paciente.IdChProfissional={IdChProfissional do médico logado}- Pacientes em que o médico é o médico assistente
4.6 Endpoint: GET /api/v1/cockpit/doctor/kpis/prescription-alerts
Retorna o indicador de Alertas de Prescrição (urgentes, a revisar, a assinar nos próximos 7 dias).
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Prescricao | GescomClienteAlfa | Tabela principal — prescrições em Situacao P/G/A/O (RN-CM-020), médico prescritor |
| PrescricaoAssinatura | GescomClienteAlfa | Histórico de assinaturas/revisões — usada para determinar se a prescrição está revisada |
| Agenda | GescomClienteAlfa | Data/hora agendada da aplicação (via Prescricao.IdAgenda) |
| Paciente | GescomClienteAlfa | Médico assistente (IdChProfissional) e exclusão lógica |
| IpParametro | GescomClienteAlfa | Definição dos parâmetros NumeroDiasRevisaoPrescricoes (já existente no sistema atual) e PrescricaoTempoAssinatura (novo), ambos em dias |
| IpParametroChave | GescomClienteAlfa | Valor de cada parâmetro por clínica (IdChave = Clinica.IdChClinica) |
| Clinica | GescomClienteAlfa | Uma linha por clínica; as de {ClinicasDoMedico} (D-CM-066) são a base de {LimitesPorClinica} (E-CM-032); Agenda.IdChClinica aponta para ela |
| ClienteEmpresa | IpSeguranca | Fuso (FusoHorarioOficial, IANA) da clínica em que o usuário está logado (D-CM-062) |
Mapa de campos
| Campo | Tipo | Banco | Observação |
|---|---|---|---|
urgent | int | PrescriptionUrgentCount() | |
toReview | int | PrescriptionToReviewCount() | |
toSignNext7Days | int | PrescriptionToSignNext7DaysCount() | nome mantido por compatibilidade; conta dentro da janela da clínica |
toSignWindowDays | int | COALESCE((SELECT TRY_CONVERT(int, ipc.Valor) FROM IpParametroChave ipc WHERE ipc.IdParametro = 'PrescricaoTempoAssinatura' AND ipc.IdChave = {IdClinica}), 7) | janela de assinatura em dias, da clínica em que o médico está logado (D-CM-063; as clínicas do cliente podem ter janelas diferentes e o campo é um só), com {IdClinica} = Clinica.IdChClinica da clínica logada; o front monta o rótulo “p/ assinar (próx. N dias)“ |
Funções de cálculo
PrescriptionToReviewCount() — conta as prescrições “a revisar” do médico logado (RN-CM-020, Precedência 2), restritas a prescrições em que o médico logado é o prescritor ou o médico assistente do paciente. A regra segue 2 níveis de precedência, nunca avaliados ao mesmo tempo — desde a v4.39, sem nenhum conceito de validade/vencimento de assinatura (abolido; até a v4.38, uma assinatura “vencida” — mais de PrescricaoValidadeAssinatura dias — devolvia a prescrição para “a assinar”; essa verificação não existe mais):
- Precedência 1 (RN-CM-020) — já foi assinada, em qualquer momento: verifica 2 fontes, por compatibilidade com prescrições gravadas antes da adoção da tabela de assinaturas atual (RN-CM-029) —
PrescricaoAssinaturacomTipoAssinatura = 'A'(fonte moderna), ou o par legadoPrescricao.DataAssinaturaPrescricao/Prescricao.IdChProfissionalAssinou(mesmo evento de assinatura —IdChProfissionalAssinoué quem assinou,DataAssinaturaPrescricaoé quando). Basta a existência de qualquer uma das 2 — não há mais cálculo de idade/recência. Uma prescrição sem nenhuma das 2 fontes não é “a revisar” — é “a assinar” (RN-CM-020, Precedência 1; verPrescriptionToSignNext7DaysCount()abaixo). - Precedência 2 (RN-CM-020) — aplicação dentro da janela de antecedência de revisão (
NumeroDiasRevisaoPrescricoes, padrão 1 dia), sem confirmação de revisão: só avaliada quando a Precedência 1 acima é satisfeita. ReaproveitaPrescricaoAssinaturade novo — um registro comTipoAssinatura = 'R'é uma confirmação de revisão (“Marcar como Revisada”). Diferente da assinatura, essa confirmação não tem prazo de validade: se existir QUALQUER registroRpara a prescrição, a revisão já está feita e a prescrição não conta como “a revisar” (nem volta a ser “a assinar” — simplesmente não aparece nesta contagem nem na dePrescriptionToSignNext7DaysCount()), para sempre. - Exceção (a) — assinatura dentro da janela de revisão (D-CM-040, E-CM-019): a prescrição não conta como “a revisar” quando existe assinatura do médico (
PrescricaoAssinaturacomTipoAssinatura = 'A', ouPrescricao.DataAssinaturaPrescricao) com data igual ou posterior à meia-noite, no fuso da clínica logada (D-CM-062), do dia da aplicação menos N dias — isto é, feita depois de a janela de revisão daquela prescrição ter aberto. A assinatura dispensa a revisão. Com N = 1 e aplicação no dia 11, vale assinatura de 10 às 00:00 em diante; assinatura do dia 9 não dispensa.PrescricaoAssinatura.Dataédatetimesem fuso e é tratada como hora local da clínica; essa leitura, e a conversão no SQL, são escolha do Designer a confirmar (E-CM-019). - Exceção (b) — administração iniciada (D-CM-039, E-CM-018): a prescrição não conta como “a revisar” quando
Agenda.DhInfusaoIniUTC(agenda da prescrição) está preenchido. Vale só para “a revisar”; “a assinar” com administração iniciada continua na lista (verPrescriptionToSignNext7DaysCount()). - Pré-requisito —
Prescricao.Situacao“em andamento”: só entram no cálculo prescrições comSituacaoemP/G/A/O(domínio completo na Seção 4.5, “Domínio: Situação da Prescrição”). Motivo: sem esse filtro, e sem mais o mecanismo de expiração para “limpar” o histórico, prescrições jáQ(finalizada) ouF(faturada) há muito tempo, mas nunca formalmente revisadas, ficariam acumulando na lista “a revisar” indefinidamente — achado confirmado contra a massa de referência no momento da regra; os números atuais da massa estão nos Cenários de Teste.
A janela que dispara “a revisar” (RN-CM-020) — descrita na Seção 1 como “dias de calendário” (padrão: 1 dia) — não é um valor fixo no código: é um parâmetro configurável por clínica, mesmo padrão já usado em 4.5 (TempoPacienteAtivoAgenda/TempoPacienteAtivoPrescricao): IpParametro.NumeroDiasRevisaoPrescricoes → IpParametroChave.Valor (dias). A janela é em dias de calendário no fuso da clínica em que o usuário está logado (D-CM-023, D-CM-062): com N dias e hoje sendo o dia 10, entram as aplicações de todos os dias até o fim do dia 10+N (N = 1: dias 10 e 11, até 23:59:59), mais as anteriores — não há limite para trás. Um dia, portanto, não são 24 horas. Ver “Parâmetro de configuração — NumeroDiasRevisaoPrescricoes” logo abaixo. Este parâmetro só entra na Precedência 2 — a janela de “a assinar” usa o parâmetro distinto PrescricaoTempoAssinatura (também em dias, ver subseção abaixo).
SELECT COUNT(*)
FROM Prescricao p
INNER JOIN Agenda a ON a.IdAgenda = p.IdAgenda AND a.RemovidoEm IS NULL -- exclusão lógica da agenda
INNER JOIN Paciente pc ON pc.IdPaciente = p.IdPaciente AND pc.RemovidoEm IS NULL -- exclusão lógica do paciente
INNER JOIN {LimitesPorClinica} lc ON lc.IdChClinica = a.IdChClinica -- janelas da clínica de cada prescrição e filtro das clínicas do médico (D-CM-060, D-CM-062, D-CM-066, E-CM-032); ver "Cálculo do limite"
WHERE p.Situacao IN ('P','G','A','O') -- "em andamento" (RN-CM-020) — não Q/F/E/C
AND (
EXISTS (SELECT 1 FROM PrescricaoAssinatura pa
WHERE pa.IdPrescricao = p.IdPrescricao AND pa.TipoAssinatura = 'A')
OR p.DataAssinaturaPrescricao IS NOT NULL -- compatibilidade legada, RN-CM-029 (par com IdChProfissionalAssinou — mesmo evento de assinatura)
OR p.IdChProfissionalAssinou IS NOT NULL -- redundante com a condição acima na prática (mesmo evento, sempre preenchidos juntos) — mantido por segurança contra dado legado incompleto
) -- Precedência 1 (RN-CM-020): já foi assinada, por qualquer uma das 2 fontes (moderna + par legado) — sem cálculo de idade/vencimento
AND a.DhAgendaIniUTC < lc.LimiteRevisaoUTC -- Precedência 2: até o fim do dia (hoje + N), sem piso, com N da clínica da prescrição (D-CM-060)
-- lc.LimiteRevisaoUTC = meia-noite local de (hoje + N + 1) no fuso da clínica em que o usuário está logado, em UTC, calculada pela aplicação para cada clínica (D-CM-062, E-CM-032)
-- lc.N = COALESCE((SELECT TRY_CONVERT(int, ipc.Valor) FROM IpParametroChave ipc
-- WHERE ipc.IdParametro = 'NumeroDiasRevisaoPrescricoes' AND ipc.IdChave = lc.IdChClinica), 1) -- default 1 dia (padrão do Gemed 2.1)
-- {InicioJanelaRevisaoLocal} = DATEADD(DAY, -lc.N, CAST(<DhAgendaIniUTC no fuso da clínica da prescrição> AS date)): meia-noite local do dia da aplicação menos N dias.
-- Ex.: CAST(a.DhAgendaIniUTC AT TIME ZONE 'UTC' AT TIME ZONE {FusoWindowsLogin} AS date), com {FusoWindowsLogin} = nome Windows do fuso IANA da clínica logada (`ClienteEmpresa.FusoHorarioOficial`), traduzido pela aplicação (E-CM-019, D-CM-062). Valor calculado POR LINHA (depende da `DhAgendaIniUTC` de cada prescrição e do N da clínica dela)
AND NOT EXISTS (
SELECT 1 FROM PrescricaoAssinatura pa2
WHERE pa2.IdPrescricao = p.IdPrescricao
AND pa2.TipoAssinatura = 'R' -- Precedência 2: nenhuma confirmação de revisão jamais registrada (sem prazo de validade)
)
AND NOT EXISTS (
SELECT 1 FROM PrescricaoAssinatura pa3
WHERE pa3.IdPrescricao = p.IdPrescricao
AND pa3.TipoAssinatura = 'A'
AND pa3.Data >= {InicioJanelaRevisaoLocal} -- Exceção (a): assinatura feita depois de a janela de revisão abrir dispensa a revisão (D-CM-040, E-CM-019)
)
AND (p.DataAssinaturaPrescricao IS NULL OR p.DataAssinaturaPrescricao < {InicioJanelaRevisaoLocal}) -- idem, para o par legado (RN-CM-029)
AND a.DhInfusaoIniUTC IS NULL -- Exceção (b): administração iniciada retira só "a revisar" (D-CM-039, E-CM-018)
AND (p.IdChProfissionalMed = {IdChProfissional do médico logado}
OR EXISTS (SELECT 1 FROM Paciente pac WHERE pac.IdPaciente = p.IdPaciente
AND pac.IdChProfissional = {IdChProfissional do médico logado}
AND pac.RemovidoEm IS NULL))Nota: a cláusula de escopo acima é fechada (só prescritor OU assistente) — o KPI é uma contagem pessoal de “quanto precisa da sua atenção”, diferente do toggle “Todos” do painel (Seção 4.7), que deliberadamente amplia para qualquer médico das clínicas em que o médico logado atende porque ali o médico está decidindo ajudar a revisar colegas. Não existe (nem deveria existir) uma permissão RBAC de “revisor geral” que amplie o KPI — isso inflaria a contagem pessoal com prescrições de pacientes sem nenhum vínculo com o médico logado.
Parâmetro de configuração — NumeroDiasRevisaoPrescricoes
A janela de disparo de “a revisar” usa o parâmetro NumeroDiasRevisaoPrescricoes, que já existe no sistema atual (catálogo de parâmetros ParametrosGemedLegado.csv: “Informa o número máximo de dias a frente que o revisor visualiza prescrições para revisar”, tipo numérico) e é usado pela Central do Médico do sistema atual. Não é uma tabela nem um parâmetro novo: o valor por clínica fica em IpParametroChave (IdParametro = NumeroDiasRevisaoPrescricoes, IdChave = {Id da Clínica}, Valor = número de dias, IdChave2 = NULL), com a definição em IpParametro.
Comportamento se o parâmetro não existir: se a linha em IpParametroChave (ou em IpParametro) não existir para a clínica, o sistema assume 1 dia (ver COALESCE na query acima). O código do sistema atual assume 2 dias nessa situação; o Gemed 2.1 define 1 dia como padrão próprio (D-CM-006), valendo outro valor só se o parâmetro da clínica o definir. Com o padrão, uma prescrição assinada e ainda não revisada aparece em “a revisar” a partir da meia-noite do dia anterior à aplicação (no padrão de 1 dia), isto é, com antecedência de cerca de 24 a 48 horas conforme a hora. Se o valor gravado não for numérico, TRY_CONVERT o descarta e vale o padrão de 1 dia.
Cálculo do limite (por clínica; D-CM-060, D-CM-062, D-CM-066, E-CM-032): o médico vê as prescrições das clínicas em que atende, e cada clínica tem os próprios parâmetros. Por isso a aplicação monta, a cada chamada, a tabela {LimitesPorClinica} com uma linha para cada clínica de {ClinicasDoMedico} (toda Agenda.IdChClinica aponta para Clinica). O INNER JOIN com essa tabela é também o filtro de clínicas: prescrição de clínica em que o médico não atende não tem linha e não entra (D-CM-066). Cada linha traz: IdChClinica, N (NumeroDiasRevisaoPrescricoes, padrão 1), S (PrescricaoTempoAssinatura, padrão 7) e os limites LimiteRevisaoUTC e LimiteAssinaturaUTC = meia-noite local do dia (hoje + N + 1) ou (hoje + S + 1), no fuso da clínica em que o usuário está logado (ClienteEmpresa.FusoHorarioOficial, IANA), convertida para UTC; o “hoje” também é o da clínica logada (D-CM-062), para o médico ver um só dia em toda a tela. A prescrição é ligada à linha da clínica dela por Agenda.IdChClinica: só N e S vêm da clínica da prescrição, o fuso é um só. A condição é Agenda.DhAgendaIniUTC < lc.LimiteRevisaoUTC (ou lc.LimiteAssinaturaUTC). Os ids de clínica seguem a cadeia descrita no início desta Seção (D-CM-065). A forma de entregar a tabela ao SQL (parâmetro de tabela, tabela temporária ou VALUES) é escolha de implementação e não muda a regra. Os limites são calculados fora do SQL para respeitar mudança de horário de verão. [PROPOSTA] O desenho da tabela é do Designer (E-CM-032). Mesma ideia do sistema atual (dias de calendário, de hoje até hoje + N); a Central não usa mais janela contínua em horas (D-CM-023).
Não criar PrescricaoTempoRevisao: o parâmetro existente NumeroDiasRevisaoPrescricoes cobre a necessidade; nenhum seed novo é necessário para a janela de revisão.
Parâmetro de configuração — PrescricaoTempoAssinatura
[PROPOSTA] A janela de antecedência de “a assinar” (RN-CM-020, Precedência 1 — “aplicação hoje ou nos próximos 7 dias de calendário”, D-CM-037) precisa existir como parâmetro real de banco, mesmo padrão do parâmetro acima — IpParametro/IpParametroChave, 2 linhas novas de dado (seed), não uma mudança de schema. Retira e substitui PrescricaoValidadeAssinatura (criado na v4.30 deste documento para a janela de validade/vencimento de assinatura, hoje abolida — RN-CM-020, v4.39 do 01-Definição): como PrescricaoValidadeAssinatura nunca chegou a ser aplicado em produção em nenhum cliente ([PROPOSTA] em todo o histórico deste documento), a substituição não tem custo de migração — não existe seed a desfazer. Nome escolhido pelo Designer (convenção “Tempo” + conceito), a confirmar:
IpParametro (linha nova):
| Campo | Valor |
|---|---|
IdParametro | PrescricaoTempoAssinatura |
Descricao | Dias de calendário a partir de hoje em que prescrição nunca assinada aparece em "a assinar" |
Dominio | NULL |
UsuarioControla | S |
Tipo | N |
IpParametroChave (linha nova, valor por clínica — exemplo com o padrão-sugerido de 7 dias, correspondente à regra da Seção 1):
| Campo | Valor |
|---|---|
IdParametro | PrescricaoTempoAssinatura |
IdChave | {Id da Clínica} |
Valor | 7 |
IdChave2 | NULL |
Comportamento se o parâmetro não existir: se a linha em IpParametro ou em IpParametroChave não existir para a clínica, o sistema assume 7 dias como default — ver o COALESCE do SQL de PrescriptionToSignNext7DaysCount() abaixo. O seed abaixo (Seção “Seeds da Funcionalidade”) deve ainda assim ser aplicado em todo cliente, pelo mesmo motivo do parâmetro anterior.
Atenção Dev/DevOps: mesma observação do parâmetro anterior — dado novo de configuração, não migration de schema; incluir na documentação de deploy/seed de cada cliente. Ver “Seeds da Funcionalidade” abaixo. Não criar parâmetro de validade da assinatura (PrescricaoValidadeAssinatura): o conceito de assinatura vencida não existe (RN-CM-020).
PrescriptionUrgentCount() — soma duas contagens, ambas restritas ao médico logado (prescritor ou assistente) e filtradas por hoursRemaining < 12 (RN-CM-011): (a) PrescriptionToReviewCount() restrita a hoursRemaining < 12; (b) PrescriptionToSignNext7DaysCount() (ver abaixo — já cobre as 2 fontes de RN-CM-029, RN-CM-020 Precedência 1, sem mais nenhuma condição de assinatura vencida) restrita a hoursRemaining < 12; o corte do limite de assinatura da clínica (lc.LimiteAssinaturaUTC) já cobre qualquer aplicação a menos de 12h (supondo S ≥ 1, o que o parâmetro não garante: com S = 0 uma aplicação a menos de 12h, mas no dia seguinte, ficaria fora; se o valor 0 ou negativo for possível, validar o mínimo de 1 dia ou aceitar a divergência), então o KPI urgente e a lista de 4.7 contam as mesmas prescrições. hoursRemaining = DATEDIFF(MINUTE, SYSDATETIMEOFFSET(), a.DhAgendaIniUTC) / 60 (inteiro truncado, como em 4.7); a classificação “urgente” usa os minutos (< 720), sem arredondar.
PrescriptionToSignNext7DaysCount() — prescrições “a assinar” (RN-CM-020, Precedência 1) em que o médico logado é o prescritor ou o médico assistente do paciente (Prescricao.IdChProfissionalMed = {médico logado} OU Paciente.IdChProfissional = {médico logado} — mesmo critério de “Meus” usado por PrescriptionToReviewCount(), ver 4.7), com Agenda.DhAgendaIniUTC até o fim do dia (hoje + X) no fuso da clínica logada, em dias de calendário (D-CM-037) — lc.LimiteAssinaturaUTC = meia-noite local de (hoje + X + 1) no fuso da clínica logada, em UTC, calculada pela aplicação por clínica (ver “Cálculo do limite” acima) (sem piso — aplicações já atrasadas continuam elegíveis indefinidamente, mesma regra de PrescriptionToReviewCount()), X = PrescricaoTempoAssinatura da clínica da prescrição (parâmetro novo, default 7 dias — ver subseção acima; nome mantido “Next7Days” por compatibilidade com o contrato de API já existente, mesmo o valor agora sendo configurável). Prescricao.Situacao IN ('P','G','A','O') (RN-CM-020), Agenda.RemovidoEm IS NULL e Paciente.RemovidoEm IS NULL, e nenhuma das 2 fontes de assinatura existe (nem PrescricaoAssinatura.TipoAssinatura = 'A', nem o par legado Prescricao.DataAssinaturaPrescricao/IdChProfissionalAssinou — RN-CM-029). Não há mais ramo (b) de “assinatura vencida que volta a ser a assinar” — abolido na v4.39; uma vez assinada, a prescrição nunca mais aparece aqui, só em PrescriptionToReviewCount() (ou em nenhuma das duas, se já revisada, assinada depois de a janela de revisão abrir, com administração iniciada ou fora da janela de revisão). Uma prescrição “a assinar” com administração iniciada (Agenda.DhInfusaoIniUTC preenchido) continua nesta contagem: sem assinatura em procedimento é falha grave de processo e deve ficar visível (D-CM-039, E-CM-018).
SQL de referência de PrescriptionToSignNext7DaysCount() (montado a partir das regras acima; as condições de assinatura são as mesmas do SQL de PrescriptionToReviewCount(), negadas):
SELECT COUNT(*)
FROM Prescricao p
INNER JOIN Agenda a ON a.IdAgenda = p.IdAgenda AND a.RemovidoEm IS NULL
INNER JOIN Paciente pc ON pc.IdPaciente = p.IdPaciente AND pc.RemovidoEm IS NULL
INNER JOIN {LimitesPorClinica} lc ON lc.IdChClinica = a.IdChClinica -- janelas da clínica de cada prescrição e filtro das clínicas do médico (D-CM-060, D-CM-062, D-CM-066, E-CM-032)
WHERE p.Situacao IN ('P','G','A','O')
AND NOT EXISTS (SELECT 1 FROM PrescricaoAssinatura pa
WHERE pa.IdPrescricao = p.IdPrescricao AND pa.TipoAssinatura = 'A') -- fonte moderna
AND p.DataAssinaturaPrescricao IS NULL -- par legado (RN-CM-029)
AND p.IdChProfissionalAssinou IS NULL
AND a.DhAgendaIniUTC < lc.LimiteAssinaturaUTC -- até o fim do dia (hoje + S), sem piso, com S da clínica da prescrição: já atrasadas continuam elegíveis (D-CM-037, D-CM-060)
-- lc.S = COALESCE((SELECT TRY_CONVERT(int, ipc.Valor) FROM IpParametroChave ipc
-- WHERE ipc.IdParametro = 'PrescricaoTempoAssinatura' AND ipc.IdChave = lc.IdChClinica), 7) -- default 7 dias
-- lc.LimiteAssinaturaUTC = meia-noite local de (hoje + S + 1) no fuso da clínica em que o usuário está logado, em UTC (D-CM-062, E-CM-032)
-- sem filtro de DhInfusaoIniUTC: "a assinar" com administração iniciada continua contada (D-CM-039)
AND (p.IdChProfissionalMed = {IdChProfissional do médico logado}
OR pc.IdChProfissional = {IdChProfissional do médico logado}) -- prescritor ou médico assistente (v4.46)Filtros do endpoint
- Escopo do médico logado, fechado nas 3 métricas: prescritor (
Prescricao.IdChProfissionalMed) OU médico assistente do paciente (Paciente.IdChProfissional) paratoReviewe a parcela de revisão deurgent; o mesmo critério (prescritor OU médico assistente) vale paratoSignNext7Dayse para a parcela de assinatura deurgent, desde a v4.46. O KPI nunca inclui prescrições de outros médicos sem esse vínculo — ver nota acima sobre a diferença em relação ao toggle “Todos” do painel (Seção 4.7).
4.7 Endpoint: GET /api/v1/cockpit/doctor/prescriptions
Retorna a lista de prescrições pendentes (assinatura e revisão) do médico logado, para o painel e para a tela dedicada.
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Prescricao | GescomClienteAlfa | Tabela principal — versão ativa (Situacao <> 'C'); Identificacao já traz protocolo + ciclo/sessão formatados |
| PrescricaoAssinatura | GescomClienteAlfa | Determina se a prescrição está assinada e/ou revisada (ver 4.6) |
| Paciente | GescomClienteAlfa | Nome social/civil do paciente e médico assistente |
| Agenda | GescomClienteAlfa | Data/hora agendada da aplicação e clínica (IdChClinica) |
| Chave | GescomClienteAlfa | Nome curto da clínica (campo clinic) |
Domínio — PrescricaoAssinatura.TipoAssinatura
| Valor | Significado |
|---|---|
A | Assinatura do médico (assinatura original da prescrição ou de uma nova versão gerada por edição) |
R | Confirmação de revisão sem alteração da prescrição (“Marcar como Revisada”, RN-CM-020 Precedência 2) |
Nota: o esquema também sugere os tipos
F(farmácia) e outros, usados por outras funcionalidades fora do escopo do Cockpit — não detalhados aqui.
Nota — compatibilidade legada (RN-CM-029): para prescrições gravadas antes da adoção desta tabela,
Prescricao.DataAssinaturaPrescricao(a data) ePrescricao.IdChProfissionalAssinou(o profissional) formam um par — o mesmo evento legado de assinatura, não duas fontes independentes; juntos, valem como se fosse um registroTipoAssinatura = 'A'emPrescricaoAssinatura, mas nenhum dos dois gera uma linha real ali — são lidos diretamente dePrescricaonas queries de 4.6. Desde a v4.39 (01-Definição), nenhuma das 2 fontes (moderna + par legado) precisa de uma data para calcular idade/vencimento — a presença de qualquer uma já basta (RN-CM-020 não usa mais o conceito de assinatura vencida).
Mapa de campos
| Campo | Tipo | Banco | Observação |
|---|---|---|---|
id | int | Prescricao.IdPrescricao | identifica diretamente a versão ativa — não há campo de número de versão a considerar à parte |
clinic | string | null | Prescricao.IdAgenda → Agenda.IdChClinica → Chave.Descricao | Nome curto da clínica da agenda da prescrição; null quando o médico atende em uma só clínica, igual ao clinic de 4.1 (RN-CM-032, E-CM-028, D-CM-066) |
patient.id | int | Prescricao.IdPaciente | |
patient.preferredName | string | Paciente.NomeSocial | mesmo padrão de appointments (4.1) e procedures (4.3) — enviado sempre, mesmo vazio, para o front sinalizar nome social ao médico |
patient.legalName | string | Paciente.Nome | enviado sempre, junto com preferredName |
prescriptionCode | string | Prescricao.Identificacao | substitui os antigos protocol/cycle — já vem formatado do banco (ex: “CARBO-TAXOL C3D1”), sem necessidade de montar a string a partir de Protocolo/PrescricaoProtocolo |
scheduleDate | datetime | Agenda.DhAgendaIniUTC, via Prescricao.IdAgenda | convertida para o fuso da clínica na exibição |
hoursRemaining | int | calculado: DATEDIFF(MINUTE, SYSDATETIMEOFFSET(), Agenda.DhAgendaIniUTC) / 60 — divisão inteira do T-SQL, que trunca em direção a zero (ex.: 90 min → 1; -90 min → -1) (D-CM-026); a classificação “urgente” (< 12) usa os minutos (< 720), então um tempo de 11h59 é urgente mesmo aparecendo como 11 | menor ou igual a zero quando a hora da aplicação já passou (a janela não tem piso — a prescrição segue na lista até ser assinada ou revisada, e conta como urgente, < 12, RN-CM-011) |
minutesRemaining | int | calculado: DATEDIFF(MINUTE, SYSDATETIMEOFFSET(), Agenda.DhAgendaIniUTC) | menor ou igual a zero quando a hora da aplicação já passou; base dos textos de tempo restante e “atrasada” no card (D-CM-013, D-CM-041) |
type | string | calculado | to_sign se RN-CM-020 Precedência 1 se aplica — nunca assinada (checando as 2 fontes de RN-CM-029, ver 4.6) e aplicação dentro da janela de PrescricaoTempoAssinatura (padrão 7 dias de calendário); to_review se RN-CM-020 Precedência 2 se aplica — já assinada (qualquer época), aplicação dentro da janela de NumeroDiasRevisaoPrescricoes (padrão 1 dia), sem nenhuma confirmação de revisão (TipoAssinatura = 'R') jamais registrada (ver PrescriptionToReviewCount, 4.6), sem assinatura feita depois de a janela de revisão abrir e sem administração iniciada (exceções (a) e (b) de 4.6); em ambos os casos, Prescricao.Situacao IN ('P','G','A','O') (filtro de RN-CM-020) |
isPreferredReviewer | bool | calculado | true se médico logado = Prescricao.IdChProfissionalMed OU = Paciente.IdChProfissional; presente para as duas categorias (to_sign e to_review) — usado pelo front para a borda “Meu” em ambos os tipos de card. Os campos prescriberName/attendingDoctorName cogitados antes foram removidos — o booleano basta para o front |
Filtros do endpoint
type = to_sign: mesma condição dePrescriptionToSignNext7DaysCount()(Seção 4.6 — RN-CM-020 Precedência 1: nunca assinada, 2 fontes de RN-CM-029) ANDAgenda.DhAgendaIniUTC < lc.LimiteAssinaturaUTC— até o fim do dia (hoje +PrescricaoTempoAssinaturada clínica da prescrição), em dias de calendário no fuso da clínica logada (D-CM-062) (parâmetro por clínica, ver 4.6 — não mais um corte de 7 dias fixo; D-CM-037). Inclui as com administração iniciada (D-CM-039). Essa janela evita inflar a lista com prescrições distantes no tempo, sem relevância imediata para o médico.type = to_review: condição completa dePrescriptionToReviewCount()(Seção 4.6 — RN-CM-020 Precedência 1 e 2) — i.e.,Situacao IN ('P','G','A','O')(filtro de RN-CM-020), já assinada (qualquer época) por uma das fontes de RN-CM-029 (Precedência 1, sem verificação de validade/vencimento), aplicação dentro da janela deIpParametro.NumeroDiasRevisaoPrescricoes(parâmetro por clínica, ver 4.6), sem nenhuma confirmação de revisão (TipoAssinatura = 'R') jamais registrada (Precedência 2, também sem prazo de validade), sem assinatura feita depois de a janela de revisão abrir (exceção (a), D-CM-040) e sem administração iniciada (exceção (b), D-CM-039) — mesmas condições do SQL dePrescriptionToReviewCount().- Escopo de médico (
reviewScope), aplicado igualmente às duas categorias — qualquer médico pode assinar ou revisar uma prescrição, não só o prescritor original (a 4.6 é sempre “mine” nas duas funções, porque cada uma é uma contagem pessoal do KPI; o painel de prescrições permite alternar):reviewScope = mine(default): adiciona(Prescricao.IdChProfissionalMed = {médico logado} OR Paciente.IdChProfissional = {médico logado}), tanto ato_signquanto ato_reviewreviewScope = all: sem restrição adicional de médico em nenhuma das duas categorias — todas as prescrições pendentes, de todos os médicos, mas só das clínicas em que o médico logado atende (D-CM-066)
- Sem parâmetro
type: união das duas categorias, ordenada porminutesRemainingascendente, desempate pelo nome do paciente —COALESCE(NULLIF(Paciente.NomeSocial, ''), Paciente.Nome), comparado sem diferenciar maiúsculas e acentos (collation do banco, pt-BR) — e, para o mesmo nome, porid(RN-CM-011, D-CM-047, E-CM-027;hoursRemainingé truncado e não distingue -40 min de +20 min);reviewScopeaplicado às duas partes da união, conforme acima Agenda.RemovidoEm IS NULL(agenda da prescrição, viaPrescricao.IdAgenda) ePaciente.RemovidoEm IS NULL— exclusão lógica, nos dois tiposPrescricao.Situacao IN ('P','G','A','O')em ambos os casos (RN-CM-020) — como há no máximo 1 prescrição ativa por cadeia de versões dentro dessas situações, este filtro também garante que apenas a versão vigente e ainda “em andamento” apareça na lista, sem risco de duplicidade- Escopo de clínicas (D-CM-066, RN-CM-032): só entram as prescrições das clínicas em que o médico atende — o
INNER JOINcom{LimitesPorClinica}(uma linha por clínica de{ClinicasDoMedico}; 4.6) faz o filtro, tanto emreviewScope = minequanto emall; a clínica de cada uma vem deAgenda.IdChClinica(campoclinic); as janelas de “a assinar” e “a revisar” usam os parâmetrosPrescricaoTempoAssinaturaeNumeroDiasRevisaoPrescricoesda clínica de cada prescrição (Agenda.IdChClinica) (D-CM-060, D-CM-062, E-CM-032).
Nota: os endpoints de ação de prescrições (GET /prescriptions/{id}, POST /sign, PATCH /review, PUT /prescriptions/{id}) pertencem a um documento de processo de Prescrições à parte, fora do escopo deste documento. RN-CM-020 continua na Seção 2 porque alimenta o KPI/painel deste Cockpit (Seções 4.6/4.7). O esquema já suporta assinatura/revisão via
PrescricaoAssinatura.TipoAssinatura(A/R) e versionamento viaPrescricaoVersao, sem necessidade de tabela nova.
4.8 Endpoint: GET /api/v1/cockpit/doctor/conversations
Retorna as conversas não finalizadas do médico logado — lidas e não lidas (painel compacto do Cockpit — ver escopo em RN-CM-015 e Seção 2.5), com base no modelo de Conversas e Alertas (IP.Mensageria). O schema desse domínio (GescomClienteAlfa.mensageria) passou a ter DDL real na Biblioteca de Schema (DDL) do projeto (GescomMensageria.sql) a partir de 28/08/2026 — antes disso, o mapeamento abaixo era baseado só na descrição do documento externo “Conversas-e-Alertas”, sem o DDL para conferir nomes e tipos de campo exatos. Esta versão corrige os campos que o DDL real revelou estarem descritos incorretamente (ver “Resolução do nome do autor” abaixo e o changelog desta versão). Diferente das demais tabelas mapeadas neste documento, as tabelas de mensageria abaixo pertencem ao mesmo banco operacional do cliente (GescomClienteAlfa), mas são de um schema separado (mensageria), não do schema dbo assistencial.
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Conversa | GescomClienteAlfa | Tabela principal — thread, assunto, status, prazo, origem, paciente relacionado, criação (desempate da ordem) |
| ConversaDestinatario | GescomClienteAlfa | Snapshot de quem recebeu a conversa — usada para filtrar pelo médico logado e para saber se há outros participantes (autoenvio, readByOthers) |
| ConversaLeitura | GescomClienteAlfa | Determina se a conversa está lida para o médico logado e se a última mensagem dele foi lida pelos outros participantes (readByOthers) |
| Mensagem | GescomClienteAlfa | Conteúdo e autor da última mensagem da thread (preview do card) |
| Indicadores, TermoTraducao | IpTerminologia | Nome do grau de urgência (Dominio = GrauUrgencia), traduzido para o idioma da clínica [PROPOSTA] (D-CM-088) |
| Equipe | GescomClienteAlfa | Nome de exibição da equipe (Nome) — usado no sufixo “(Equipe)” do autor quando aplicável (ver “Resolução do nome da equipe” abaixo) |
| EquipeMembro | GescomClienteAlfa | Determina se o autor da mensagem é membro da equipe destino da conversa (Conversa.EquipeId) — decide se o sufixo de equipe aparece |
| SegUsuario | GescomClienteAlfa | Ponte legada entre o identificador local (int) e o GUID do IPSeguranca (ver resolução de nome abaixo) |
| Paciente | GescomClienteAlfa | Nome social/civil do paciente relacionado, quando Conversa.IdPaciente existe |
| Clinica | GescomClienteAlfa | Clínica de origem da conversa: Clinica.IdEmpresa = Conversa.IdEmpresa (E-CM-033; confirmado em D-CM-069) → IdChClinica |
| Chave | GescomClienteAlfa | Nome curto da clínica (Chave.Descricao de Clinica.IdChClinica) |
Resolução do nome do autor (DDL real de
mensageria, disponibilizado em 28/08/2026):Mensagem.IdUsuarioAutor,Conversa.IdUsuarioRemetente,Conversa.IdUsuarioDestino,ConversaDestinatario.IdUsuarioeEquipeMembro.IdUsuariosão todosint, não GUID — o mesmo tipo de identificador legado local já usado emProfissional.IdUsuario/Prescricao.IdUsuarioAssinatura. O DDL real desmente a suposição de que esses campos armazenam diretamente o GUID deIPSeguranca.dbo.Usuario.Id. A triangulação correta é:IdUsuarioAutor(int) =SegUsuario.IdUsuario(smallint, PK — join dentro do próprioGescomClienteAlfa) →SegUsuario.SegurancaUsuarioId(GUID; nome de campo conforme “Log de Mudanças Estruturais do Banco de Dados”, que prevalece sobre a Biblioteca de Schema (DDL) para este campo específico) → nome de exibição emIPSeguranca.dbo.Usuario.Apelido(mesmo GUID). A mesma triangulação vale paraIdUsuarioRemetente,IdUsuarioDestinoeConversaDestinatario.IdUsuario.
Resolução do nome da equipe: o autor de uma mensagem ganha o sufixo da equipe quando
Conversa.DestinoTipo = 'Team'E existe uma linha emEquipeMembrocomEquipeId = Conversa.EquipeId,IdUsuarioigual aoSegUsuario.IdUsuariodo autor resolvido acima, e vínculo vigente na data de envio da mensagem (não o vínculo atual no momento em que o card/thread é exibido):AdicionadoEmUtc <= Mensagem.CriadoEmUtc AND (RemovidoEmUtc IS NULL OR RemovidoEmUtc > Mensagem.CriadoEmUtc). Quando as condições são verdadeiras, o nome de exibição final éUsuario.Apelido+ ” (” +Equipe.Nome+ ”)” (ex.: “Sandra (Farmácia)”); caso contrário, é sóUsuario.Apelido. Decidido nesta versão (resolve o[PROPOSTA]da v4.24): o vínculo é sempre o da época do envio — alguém que já saiu da equipe mantém o sufixo nas mensagens antigas que escreveu como membro dela, e alguém que entrou depois não ganha o sufixo retroativamente em mensagens anteriores à sua entrada.
O ícone continua binário: bell (Lucide) para OrigemTipo = 'System', ícone genérico de pessoa para OrigemTipo = 'User', sem variação por equipe (recepção/farmácia/enfermagem) — a identificação da equipe, quando aplicável, é resolvida como texto (acima), não como ícone. Diferente do que versões anteriores deste documento afirmavam, a tabela Equipe (e EquipeMembro) é necessária neste endpoint — não apenas no backend de roteamento — porque a exibição do sufixo “(Equipe)” no authorName depende dela (ver “Resolução do nome da equipe” acima).
Mapa de campos
| Campo | Tipo | Banco | Observação |
|---|---|---|---|
id | uuid | Conversa.Id | |
subject | string | Conversa.Assunto | nvarchar(200), obrigatório no banco (Mapeamento da Mensageria, 4.1) |
sourceType | string | calculado a partir de Conversa.OrigemTipo | System se OrigemTipo = 'System'; User se OrigemTipo = 'User' (D-CM-042) |
authorName | string | IPSeguranca.dbo.Usuario.Apelido do autor da mensagem de maior Sequencia, via SegUsuario (ver “Resolução do nome do autor” acima); com sufixo " (" + Equipe.Nome + ")" quando Conversa.DestinoTipo = 'Team' e o autor é membro dessa Equipe (ver “Resolução do nome da equipe” acima); ou “Sistema” quando sourceType = System | |
lastMessage | string | Mensagem.Conteudo (maior Sequencia da Conversa) | |
lastMessageAt | datetime | Mensagem.CriadoEmUtc (mesma linha) | |
deadline | datetime | Conversa.PrazoEmUtc | pode ser nulo |
urgencyLevel | object|null | Conversa.GrauUrgencia (chave) e nome em IpTerminologia.dbo.Indicadores (Dominio = GrauUrgencia) com TermoTraducao (idioma da clínica, DT-011, DT-012) | [PROPOSTA] coluna varchar(10) NULL ainda a criar (Mapeamento da Mensageria, L-09); chaves routine, urgent, asap, stat em minúsculas (D-MSG-046); null quando a coluna é nula (D-CM-088) |
status | string | Conversa.Status | mapeado para sent/read/responded (ver 2.9; D-CM-087) |
unread | bool | calculado: Conversa.UltimaSequencia > ConversaLeitura.UltimaSequenciaLida (ou sem ConversaLeitura) | usado para destaque visual e camada de prioridade (RN-CM-015); não filtra o resultado |
authorIsMe | bool | calculado: Mensagem.IdUsuarioAutor (maior Sequencia) = SegUsuario.IdUsuario do médico logado | false em alerta do sistema (autor nulo) |
readByOthers | bool | null | calculado [PROPOSTA], sem coluna nova (mesma regra da Mensageria, Mapeamento 4.1): NULL quando Conversa.OrigemTipo = 'System' ou quando o autor da última mensagem não é o médico logado; senão 1 quando existe ConversaLeitura de outro usuário (IdUsuario diferente do médico) com UltimaSequenciaLida >= Mensagem.Sequencia da última mensagem, ou quando a conversa não tem outro participante (o remetente é o médico e nenhum ConversaDestinatario é outro usuário: autoenvio, inclusive conversa de equipe em que o médico é o único membro); senão 0 | Junções com IdEmpresa e ConversaId, como as demais tabelas de mensageria |
patient | object | null | Paciente, via Conversa.IdPaciente |
clinic | string | null | Conversa.IdEmpresa → Clinica.IdEmpresa → Clinica.IdChClinica → Chave.IdChave → Chave.Descricao | Nome curto da clínica de origem da conversa (D-CM-064), mesma origem do clinic de 4.1; null quando o médico atende em uma só clínica (mesma regra de 4.1, D-CM-066). Conversa.IdEmpresa é o SegEmpresa.IdEmpresa (D-CM-069; P-CM-052) |
Filtros do endpoint
ConversaDestinatario.IdUsuario = {médico logado}— recebida diretamente ou via snapshot de equipe (EquipeOrigemId)- Escopo de clínicas (D-CM-066, RN-CM-032):
Conversa.IdEmpresa IN (SELECT IdEmpresa FROM {ClinicasDoMedico})— o médico vê as conversas das clínicas em que atende (Conversa.IdEmpresa=SegEmpresa.IdEmpresa, D-CM-069); o cliente vem sempre da sessão validada, nunca escolhido livremente pelo cliente da API (conforme fronteira de responsabilidade do IPSeguranca), e o vínculo do médico com a conversa continua pelo filtro de destinatário acima. Schema (Biblioteca de Schema (DDL),GescomMensageria.sql):Conversa,ConversaDestinatario,ConversaLeitura,Mensagem,ConversaAcao,OutboxEvento,EquipeeEquipeMembrotêmIdEmpresaNOT NULL e chaves estrangeiras compostas (por exemploId+IdEmpresa): as junções entre essas tabelas devem usar as duas colunas, e o filtro deIdEmpresasai só da lista, não das junções. O card mostra a clínica de origem (D-CM-064, campoclinic) Conversa.Status IN ('Sent', 'Read', 'Responded')— exclui'Resolved'e'Dismissed'Conversa.UltimaSequencia > ConversaLeitura.UltimaSequenciaLida, OU não existeConversaLeiturapara o médico logado — calcula o campounread, usado como critério de ordenação (não filtra o WHERE).- Ordenação (RN-CM-015; RN-MSG-002 da Mensageria; D-CM-087, D-CM-088):
unreaddescendente (não lidas primeiro); depois o grau, descendente (CASE Conversa.GrauUrgencia WHEN 'stat' THEN 4 WHEN 'asap' THEN 3 WHEN 'urgent' THEN 2 WHEN 'routine' THEN 1 ELSE 0 END, o mesmo que aOrdemdeIndicadores; nulo vale 0); depois a chaveCASE WHEN Conversa.PrazoEmUtc > lastMessageAt THEN Conversa.PrazoEmUtc ELSE lastMessageAt ENDdescendente (com prazo nulo, valelastMessageAt); empate:Conversa.CriadoEmUtcdescendente; por fimConversa.Id, para a ordem ser determinística
4.9 Endpoints de ação: GET /conversations/{id}, POST /read, POST /reply, PATCH /resolve, PATCH /discard
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Conversa | GescomClienteAlfa | Status atual, UltimaSequencia |
| Mensagem | GescomClienteAlfa | Thread completa (GET detalhe); nova linha inserida em POST /reply |
| ConversaLeitura | GescomClienteAlfa | Atualizada em POST /read |
| ConversaAcao | GescomClienteAlfa | Histórico append-only — nova linha em toda ação (leitura, resposta, resolução, descarte) |
| OutboxEvento | GescomClienteAlfa | Evento assíncrono gravado na mesma transação de qualquer mudança de estado (fora do escopo deste front, mencionado por completude) |
Efeitos em BD por endpoint de ação
Escopo de clínicas (D-CM-066): as ações só valem para conversas de clínicas em que o médico atende (Conversa.IdEmpresa IN (SELECT IdEmpresa FROM {ClinicasDoMedico})), como a lista (4.8); uma ação sobre conversa de outra clínica é recusada, mesmo que o id seja conhecido. Como IdEmpresa é NOT NULL e faz parte das chaves estrangeiras compostas, toda linha nova (Mensagem, ConversaLeitura, ConversaAcao, OutboxEvento) grava o IdEmpresa da conversa, não o da clínica da sessão; do contrário a chave estrangeira falha ou a linha cai na clínica errada.
- GET /conversations/{id}: somente leitura — retorna todas as
Mensagemda conversa ordenadas porSequencia, mais os dados deConversa(assunto, status, prazo, paciente);statusno contrato usarespondedpara'Responded'(D-CM-087). Para cada mensagem, resolve o sufixo de equipe do autor do mesmo jeito que o endpoint de lista (Seção 4.8, “Resolução do nome da equipe”) — a thread completa também mostra “Sandra (Farmácia)” quando aplicável, não só o card compacto. No contrato,messages[].typetem um único valor,Response(D-CM-042): o tipo de mensagem não distingue mais inicial, resposta e atualização. - POST /read: insere ou atualiza
ConversaLeitura(chaveConversaId+IdUsuario) comUltimaSequenciaLida = Conversa.UltimaSequencia; insere uma linha emConversaAcao(Tipo=Read); seConversa.Status = 'Sent', atualiza para'Read'— nunca regride um status já mais avançado ('Responded'permanece'Responded'). - POST /reply: insere uma nova linha em
Mensagem(Sequencia = Conversa.UltimaSequencia + 1,IdUsuarioAutor= médico logado,Conteudodo request,Tipo='Response'); atualizaConversa.UltimaSequencia; insere ou atualizaConversaLeiturado autor comUltimaSequenciaLida= a novaSequencia(a própria resposta conta como leitura, Especificação 2.5; sem isso, a conversa ficaria não lida para quem respondeu); atualizaConversa.Statuspara'Responded'; insere uma linha emConversaAcao(Tipo='Response';MensagemIdda nova mensagem); gravaOutboxEvento(TipoEvento=ConversaRespondida). O valor'Reply', antes um segundo valor válido paraMensagem.Tipo/ConversaAcao.Tipono mesmoCHECK, foi abolido —'Response'é o único valor usado para a ação de responder, resolvendo a pendência [A DEFINIR] da v4.24 (ver Log de Mudanças Estruturais do Banco de Dados). OCHECKdeMensagem.Tipodeve aceitar só'Response'(D-CM-052; hoje a Biblioteca de Schema (DDL) ainda mostra'Initial','Update'e'Reply'): mudança de banco a aplicar, registrada no Log de Mudanças Estruturais do Banco de Dados. - PATCH /resolve: atualiza
Conversa.Statuspara'Resolved'; insere uma linha emConversaAcao(Tipo='Resolve'); gravaOutboxEvento(TipoEvento=ConversaResolvida). Não altera nem excluiMensagem. - PATCH /discard: atualiza
Conversa.Statuspara'Dismissed'; insere uma linha emConversaAcao(Tipo='Dismiss'); gravaOutboxEvento(TipoEvento=ConversaDescartada). Mesma observação — nada é excluído fisicamente. O estado fica emConversa, não emConversaDestinatario: resolver ou descartar vale para todos os destinatários — a conversa sai da lista de todos (endereçada a uma equipe ou a mais de uma pessoa), pois a lista filtra porConversa.Status.
Fora do escopo deste documento
A criação de conversas (envio inicial por um usuário) e a publicação de alertas automáticos (AlertaPublicacao, com chave de idempotência) partem de outros módulos ou telas — o Cockpit é consumidor/participante das conversas, não o ponto de origem. O cadastro e a gestão de equipes (criar/renomear/desativar uma Equipe, adicionar ou remover membros em EquipeMembro) também partem de outro módulo — o Cockpit só lê Equipe/EquipeMembro para resolver o sufixo do nome do autor (Seção 4.8), nunca escreve nelas. O processamento assíncrono via OutboxEvento pertence ao domínio do IP.Mensageria e também não é especificado aqui.
4.10 Endpoint: GET /api/v1/patients/search
Retorna pacientes que casam com o termo digitado no campo de busca do cabeçalho (RN-CM-004). A correspondência aproximada (pesos de proximidade fonológica e semântica) usa um mecanismo já existente no sistema, fora do escopo desta especificação — este mapeamento cobre apenas os campos de busca direta e de resposta que esse motor já existente consome/retorna.
Tabelas envolvidas
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Paciente | GescomClienteAlfa | Tabela única consultada — todos os campos de busca e resposta vêm dela |
Mapa de campos
| Campo | Tipo | Banco | Observação |
|---|---|---|---|
id | int | Paciente.IdPaciente | |
name | string | Paciente.Nome | segue o mesmo padrão de preferredName/legalName dos demais endpoints quando Paciente.NomeSocial existir |
medicalRecordNumber | string | Paciente.NumProntuario | |
gender | char | Paciente.Sexo | domínio ‘M’/‘F’ |
birthDate | data | Paciente.Nascimento | campo de busca quando a entrada começa com dígito (RN-CM-004) |
motherName | string | Paciente.NomeMae | campo de busca quando a entrada começa com letra (RN-CM-004) |
cpf | string | Paciente.CPF | campo de busca quando a entrada começa com dígito (RN-CM-004) |
Filtros do endpoint
- Sem filtro por médico logado — diferente dos demais painéis do Cockpit, a busca do cabeçalho não é restrita aos pacientes do médico, pois ele pode precisar localizar qualquer paciente da clínica.
- Mínimo de 2 caracteres (RN-CM-004) antes de disparar a busca.
Paciente.RemovidoEm IS NULL— paciente excluído logicamente não aparece na busca.
Nota sobre o motor de correspondência aproximada
O EsquemaGemed21.csv não tem uma coluna dedicada de correspondência fonética/semântica em Paciente — o motor de busca aproximada citado em RN-CM-004 já existe e está em produção fora deste documento; presume-se que ele consulta os mesmos campos mapeados acima, mas o algoritmo em si (ranking, tolerância, índice usado) não é redefinido aqui.
Tabelas novas
Nenhuma proposta por esta funcionalidade. Usa IpTerminologia.DomEstadoAgendaConsulta (4.1) e IpTerminologia.DomEstadoAgendaProcedimento (4.3), criadas em 27/10/2026 (estrutura no Log de Mudanças Estruturais do Banco de Dados, 27/10/2026: CodEstado char(3) PK, Descricao varchar(30), CorClaroTexto, CorClaroFundo, CorEscuroTexto, CorEscuroFundo char(7)); ainda não estão na Biblioteca de Schema (DDL), que precisa de nova extração. São base global: as cores valem para todas as clínicas (DT-016). O indicador EstadoAgendaConsulta de IpTerminologia.Indicadores, que guardava a cor do status em Caracteristica, será descontinuado depois que estas tabelas estiverem em uso (D-CM-081); a Central não o lê.
Campos novos
| Tabela | Campo | Tipo | Finalidade | Definição completa |
|---|---|---|---|---|
ClienteEmpresa (IpSeguranca) | FusoHorarioOficial | varchar(64), NOT NULL depois de preencher as clínicas existentes | Fuso da clínica em convenção IANA (ex.: America/Sao_Paulo), usado em “hoje” e em todos os horários de 4.1 a 4.4 e 4.7 no lugar do deslocamento FusoOficial (smallint), que não identifica o fuso | Agenda do Médico, Mapeamento de Banco de Dados, “Campos novos”; migração a criar (Log de Mudanças Estruturais do Banco de Dados, 07/10/2026); não repetida aqui (Lição #10 da Skill Designer) |
Índices
[PROPOSTA] O índice proposto na Agenda do Médico (IX_Agenda_IdChRecurso_TipoAgenda_DhAgendaIniUTC, Mapeamento da Agenda, “Índices”; a confirmar com o time de banco) atende também os filtros de 4.1 e 4.2 (IdChRecurso, TipoAgenda, dia de DhAgendaIniUTC). A Central lê mais colunas de Agenda (DhChegadaUTC, DhAtendimentoIniUTC, DhAtendimentoFimUTC, Atendimento, PrimeiraConsulta): se o time de banco as incluir no INCLUDE, ajusta-se essa única definição para as duas funcionalidades, sem criar um segundo índice. 4.3 e 4.4 filtram por TipoAgenda e dia, sem o médico — o índice não os atende como está; avaliar com o time de banco.
Seeds da Funcionalidade
Lista consolidada de todo dado (seed) que precisa existir em produção — não schema novo, mas linhas de dado que este documento pressupõe — para que a funcionalidade se comporte como especificado. Pensada como checklist de deploy para Dev/DevOps: cada linha aponta para a seção com a definição completa dos campos, não a repete (evita duplicar a mesma informação em dois lugares — Lição #10 da Skill Designer).
| Seed | Tabela(s) | Por cliente ou global? | Status | Detalhe completo |
|---|---|---|---|---|
NumeroDiasRevisaoPrescricoes — janela (em dias) antes da aplicação em que uma prescrição assinada vira “a revisar” (RN-CM-020) | IpParametro (1 linha) + IpParametroChave (1 linha por clínica) | Por cliente (IpParametroChave); a linha de IpParametro é única, compartilhada entre clientes | Parâmetro já existente no sistema atual (não é seed novo); conferir a presença da linha de IpParametro nas bases novas. Padrão de 1 dia no código (Gemed 2.1) se a linha de IpParametroChave (ou a de IpParametro) não existir para a clínica; o código do sistema atual assume 2 | Seção 4.6, “Parâmetro de configuração — NumeroDiasRevisaoPrescricoes” |
PrescricaoTempoAssinatura — janela (em dias) a partir de agora em que uma prescrição nunca assinada aparece em “a assinar” (RN-CM-020) | IpParametro (1 linha) + IpParametroChave (1 linha por clínica) | Por cliente (IpParametroChave); a linha de IpParametro é única, compartilhada entre clientes | [PROPOSTA] — ainda não aplicado em produção. Não há parâmetro de validade da assinatura (RN-CM-020). Default de 7 dias no código se a linha de IpParametroChave (ou a de IpParametro) não existir para a clínica, mas o seed deve ser aplicado mesmo assim | Seção 4.6, “Parâmetro de configuração — PrescricaoTempoAssinatura” |
| Cores dos status de consulta (6) e de procedimento (8) nos dois temas | DomEstadoAgendaConsulta e DomEstadoAgendaProcedimento (IpTerminologia) | Global | Tabelas criadas; conferir os valores contra o Design System, seção 4 | 4.1 e 4.3, campo status.colors |
| Nome dos status de consulta e de procedimento em pt-BR, en-US e es-419 | TermoTraducao (IpTerminologia), Origem = nome da tabela de estado | Global | Existentes nos 3 idiomas — conferir | 4.1 e 4.3, campo status.name |
Nenhum outro seed é necessário por este documento — os demais parâmetros citados (TempoPacienteAtivoAgenda, TempoPacienteAtivoPrescricao, Seção 4.5, em dias) já existem em produção, não são propostos aqui; seed de referência em Infra-estrutura/(BD-M) Dados incluídos obrigatórios.md.
Modo de assinatura (RN-CM-012) — [A DEFINIR]: a assinatura com ou sem certificado digital é definida por configuração do cliente, mas o parâmetro/tabela que guarda essa configuração ainda não foi identificado. Não mapeado neste documento.
METADADOS FINAIS
- Prioridade: Alta (Core do Sistema)
- Complexidade: Média/Alta (Devido às integrações em tempo real)
- Próximos Passos:
- Homologação do serviço de atualização automática.
- Teste de carga para múltiplos médicos acessando simultaneamente.
- Validação da assinatura digital em ambiente de sandbox.
Definir ícones definitivos para os KPI cards— feito no Protótipo v3.14 (biblioteca Lucide, vialucide.js).Substituir ícones placeholder de comunicação por SVGs da biblioteca Lucide— feito no Protótipo v3.14 (bellpara alertas de sistema,userpara conversas com pessoa).- Validar acessibilidade (WCAG) com usuários reais — navegação por teclado dos títulos como links, toggles pill e KPI cards já implementada no Protótipo v3.14 (tabindex/role/Enter-Space), falta validação formal.
- Testar usabilidade do título como link com seta no hover com médicos.
- Validar touchpoints de workflow com médicos em ambiente real (shadowing).
- Mapear touchpoints de workflows ainda não documentados (ex: workflow de alta, workflow de intercorrência).
- Especificar os demais itens do menu do usuário: autocadastro/edição de perfil, dados de faturamento e pagamento (conta bancária, PIX) e dados de especialidade (CRM, RQE) — hoje o menu só tem o seletor “Tema” e “Sair”.
Histórico de Versões
-
v6.0 (29/10/2026) — Abertura da versão 6.0 a pedido do solicitante: a série v5 foi fechada na v5.20, que foi para desenvolvimento, e fica em
Histórico/sem alterações. Esta versão é, por ora, cópia da v5.20: nenhuma mudança de regra, tela, contrato ou schema. As mudanças da v6 serão descritas para o time de desenvolvimento emPara Desenvolvedores/Central do Médico - mudanças da v6 - guia para desenvolvimento.md. Acompanha 01-Definição v6.0, 02-Especificação v6.0, 03-Protótipo v6.0, 04-Mapeamento v6.0, Cenários de Teste v6.0 e 05-Registro de Decisões v1.20. -
v5.20 (29/10/2026) — Acompanha as versões v5.20 dos demais documentos e 05-Registro de Decisões v1.19. Decisão D-CM-090: o campo da conversa passa de
urgencyaurgencyLevel(4.8). Sem outra mudança. -
v5.19 (29/10/2026) — Acompanha 01-Definição v5.19, 02-Especificação v5.19, 03-Protótipo v5.19, Cenários de Teste v5.19 e 05-Registro de Decisões v1.18. Decisão D-CM-088. 4.8: campo
urgency(Conversa.GrauUrgenciaeIndicadores/TermoTraducao) e a ordem pelo grau antes da data; chaves em minúsculas. Depende da criação da coluna (L-09 da Mensageria). Sem mudança nas ações (4.9); o botão do card (D-CM-089) é só de interface. -
v5.18 (28/10/2026) — Acompanha 01-Definição v5.18, 02-Especificação v5.18, 03-Protótipo v5.18, Cenários de Teste v5.18 e 05-Registro de Decisões v1.17. Decisões D-CM-086 e D-CM-087 (05 - Registro de Decisões v1.17). 4.8: novos campos
subject(Conversa.Assunto),authorIsMeereadByOthers(calculado, sem coluna nova, [PROPOSTA] como na Mensageria);statuscomresponded; nova ordenação (não lidas; depois o maior entre a última mensagem e o prazo, decrescente; empate porConversa.CriadoEmUtc), D-CM-087. 4.9: o detalhe da conversa traz o assunto;POST /replygrava a leitura do autor (a resposta conta como leitura), que o cálculo deunreade dereadByOthersusa. Desempate final da ordem porConversa.Id. Revisão por crítico técnico (subagente) aplicada antes de fechar. Até a v5.17, o valor de'Responded'erareplied. -
v5.17 (28/10/2026) — Acompanha 01-Definição v5.17, 02-Especificação v5.17, 03-Protótipo v5.17, Cenários de Teste v5.17 e 05-Registro de Decisões v1.16. Decisões D-CM-084 e D-CM-085 (05 - Registro de Decisões v1.16). Sem mudança de mapeamento: só o número da versão (as mudanças são de nome exibido e de botões).
-
v5.16 (27/10/2026) — Acompanha 01-Definição v5.16, 02-Especificação v5.16, 03-Protótipo v5.16, Cenários de Teste v5.16 e 05-Registro de Decisões v1.15. Decisões D-CM-077 a D-CM-083 (05 - Registro de Decisões v1.15). (1) “Tabelas novas”: o indicador
EstadoAgendaConsultaserá descontinuado depois da implementação nova (D-CM-081). (2) nomes de status como cadastrados emTermoTraducao— “Em atendimento”, “Em preparo” e “Em aplicação” (antes “Em Atendimento”, “Preparo” e “Em administração”; D-CM-082), nas tabelas deProcedureStatus(). (3) menções de proveniência de decisões (“solicitante”) retiradas do corpo, que passam a existir só aqui e no Registro de Decisões (D-CM-083). -
v5.15 (27/10/2026) — Acompanha 01-Definição v5.15, 02-Especificação v5.15, 03-Protótipo v5.15, Cenários de Teste v5.15 e 05-Registro de Decisões v1.14. Decisões D-CM-073 a D-CM-076 (05 - Registro de Decisões v1.14). (1) 4.1 e 4.3: o campo
statusvira objeto —status.domain(calculado),status.name(TermoTraducao,Termo=CodEstado,Origem= nome da tabela) estatus.colors(tabelasIpTerminologia.DomEstadoAgendaConsultaeDomEstadoAgendaProcedimento; DT-016, D-CM-073); tabelas novas em “Tabelas envolvidas”; tabelas “Status ×CodEstado” em “Domínios”. (2)ProcedureStatus()(4.3 e 4.4): status 3 volta aadministered(D-CM-074). (3) Nova seção “Tabelas novas” e duas linhas em “Seeds da Funcionalidade” (cores e nomes; global). -
v5.14 (26/10/2026) — Acompanha 01-Definição v5.14, 02-Especificação v5.14, 03-Protótipo v5.14, Cenários de Teste v5.14 e 05-Registro de Decisões v1.13. Decisões D-CM-070 a D-CM-072. (1) Bloco “Perda de acesso” da Seção 4 corrigido: perde-se agendas e prescrições, não pacientes; “Em Tratamento”, adesão e busca seguem sem filtro por clínica;
Paciente.IdChClinicanão é usado pela Central (D-CM-070). (2) Nome do campo deSegEmpresafixado no do DDL,SegurancaClienteEmpresaId(D-CM-071); sai o aviso de dois nomes. (3)Clinica.FusoHorarioregistrada como descontinuada, com remissão ao Log (D-CM-072). SQL e filtros não mudam. -
v5.13 (26/10/2026) — Acompanha 01-Definição v5.13, 02-Especificação v5.13, 03-Protótipo v5.13, Cenários de Teste v5.13 e 05-Registro de Decisões v1.12. Decisões D-CM-067 a D-CM-069. (1) Bloco “Clínicas em que o médico atende”: a proposta E-CM-034 vira decisão (D-CM-067); o parágrafo das alternativas da DDL é trocado por duas notas, “Fora desta regra” (
Recurso.IdChClinicaeRecursoHorariosão da marcação de agendas) e “Perda de acesso” (D-CM-068). (2)Conversa.IdEmpresa=SegEmpresa.IdEmpresaconfirmado (D-CM-069); a troca porIdChClinicaficou adiada (P-CM-052). (3) Fonte do fuso confirmada:ClienteEmpresa.FusoHorarioOficial; nenhuma consulta lêClinica.FusoHorario(D-CM-069). (4) Nome do campo deSegEmpresa: o solicitante deu dois nomes; fica o do DDL (P-CM-050). SQL e filtros não mudam. -
v5.12 (26/10/2026) — Acompanha 01-Definição v5.12, 02-Especificação v5.12, 03-Protótipo v5.12, Cenários de Teste v5.12 e 05-Registro de Decisões v1.11. Decisão em 05 - Registro de Decisões v1.11 (D-CM-066): o médico vê só as clínicas em que atende. (1) Novo bloco no início da Seção 4, “Clínicas em que o médico atende”: tabela
{ClinicasDoMedico}montada a partir do acesso do usuário às clínicas (ClientePerfilAcessoUsuario, mesmo critério deClinicVisible()da Agenda) e da cadeia de D-CM-065 — [PROPOSTA] E-CM-034, a confirmar. (2) 4.1, 4.3 e 4.4: filtroAgenda.IdChClinica INessa tabela no lugar de “sem filtro de clínica”;clinicnulo quando o médico atende em uma só clínica. (3) 4.6 e 4.7:{LimitesPorClinica}passa a ter uma linha por clínica do médico, e oINNER JOINvira também o filtro (vale para “Meus” e “Todos”). (4) 4.8: filtroConversa.IdEmpresa INe ações restritas às mesmas clínicas. (5) Nota do KPI de alertas: o toggle “Todos” amplia para médicos das clínicas do médico logado. -
v5.11 (26/10/2026) — Acompanha 01-Definição v5.11, 02-Especificação v5.11, 03-Protótipo v5.11, Cenários de Teste v5.11 e 05-Registro de Decisões v1.10. Decisões em 05 - Registro de Decisões v1.10 (D-CM-061 a D-CM-065). (1) Novo bloco no início da Seção 4, “Ligação entre a clínica do login e a base do cliente”:
ClienteEmpresa.Id=SegEmpresa.SegurancaClienteEmpresaId→SegEmpresa.IdEmpresa→Clinica.IdEmpresa→Clinica.IdChClinica=Agenda.IdChClinica=IpParametroChave.IdChave(D-CM-065). (2) 4.6 e 4.7: “hoje” e o fim do dia das duas janelas no fuso da clínica logada (D-CM-062);{LimitesPorClinica}passa a ter uma linha porClinicado banco do cliente (semFusoWindows; o fuso é o da clínica logada), o que também encerra o risco de oINNER JOINperder prescrição;{FusoWindowsLogin}no lugar delc.FusoWindowsna exceção (a). (3) 4.5 e 4.6:{IdClinica}etoSignWindowDayssão da clínica logada, sem “interino” (D-CM-063). (4) 4.8: novo campoclinicna lista de conversas, comClinicaeChavenas tabelas (D-CM-064, E-CM-033). (5) 4.1: contagem das clínicas do cliente porClinicaligada aSegEmpresa. (6) E-CM-030 vira D-CM-061. -
v5.10 (26/10/2026) — Acompanha 01-Definição v5.10, 02-Especificação v5.10, 03-Protótipo v5.10, Cenários de Teste v5.10 e 05-Registro de Decisões v1.9. Decisões em 05 - Registro de Decisões v1.9 (D-CM-055 a D-CM-060). (1) 4.3: campo
clinic(E-CM-030) e escopo sem filtro de clínica; 4.4: mesmo escopo no indicador. (2) 4.1:clinicnulo quando o cliente tem uma só clínica. (3) 4.6 e 4.7: as janelas de assinatura e de revisão usam os parâmetros da clínica de cada prescrição, por meio de uma tabela por clínica entregue pela aplicação ({LimitesPorClinica}, E-CM-031); otoSignWindowDayse o “Em Tratamento” (4.5) usam a clínica de entrada, interino em P-CM-048. (4) 4.8: sem filtro porConversa.IdEmpresa; o médico vê as conversas de todas as clínicas do cliente (D-CM-060). -
v5.9 (26/10/2026) — Acompanha 01-Definição v5.9, 02-Especificação v5.9, 03-Protótipo v5.9, Cenários de Teste v5.9 e 05-Registro de Decisões v1.8. Decisões D-CM-047 a D-CM-054. (1) 4.1 e 4.7: campo novo
clinic(deAgenda.IdChClinica,nullcom uma só clínica) e nota de que as consultas de 4.1, 4.2 e as prescrições de 4.7 não têm filtro de clínica — todas as clínicas do cliente (D-CM-050; E-CM-028, E-CM-029); parâmetros por clínica em aberto (P-CM-046). (2) 4.7: desempate pelo nome do paciente e, depois, porid(D-CM-047, E-CM-027). (3) 4.9: oCHECKdeMensagem.Tipopassa a aceitar só'Response'(D-CM-052); mudança de banco a aplicar, registrada no Log de Mudanças Estruturais. Sem outra mudança de schema nem de contrato. -
v5.8 (26/10/2026) — Acompanha 01-Definição v5.8, 02-Especificação v5.8, 03-Protótipo v5.8, Cenários de Teste v5.8 e 05-Registro de Decisões v1.7. Decisão em 05 - Registro de Decisões v1.7 (D-CM-046). Sem mudança de schema nem de contrato.
-
v5.7 (21/10/2026) — Acompanha 01-Definição v5.7, 02-Especificação v5.7, 03-Protótipo v5.7, Cenários de Teste v5.7 e 05-Registro de Decisões v1.6. Decisão em 05 - Registro de Decisões v1.6 (D-CM-045). Sem mudança de schema nem de contrato.
-
v5.6 (21/10/2026) — Acompanha 01-Definição v5.6, 02-Especificação v5.6, 03-Protótipo v5.6, Cenários de Teste v5.6 e 05-Registro de Decisões v1.5. Decisão em 05 - Registro de Decisões v1.5 (D-CM-044, decisões transversais DT-011 e DT-012). Nos três blocos “Internacionalização”: idioma = o da clínica atual (era “Idioma do cliente”); sem tradução, vai a chave e o back-end registra anomalia, sem queda para pt-BR. Sem mudança de schema nem de contrato.
TermoTraducao.Termopassa avarchar(128)(Log de Mudanças, 21/10/2026) — sem efeito nos termos usados pela Central. -
v5.5 (14/10/2026) — Acompanha 01-Definição v5.5, 02-Especificação v5.5 e 03-Protótipo v5.5. Decisão em 05 - Registro de Decisões v1.4 (D-CM-043). Sem mudança de schema nem de contrato: a versão alinha a Central ao Design System de 14/10/2026 (cores).
-
v5.4 (13/10/2026) — Acompanha 01-Definição v5.4, 02-Especificação v5.4 e 03-Protótipo v5.4. Decisões em 05 - Registro de Decisões v1.3 (D-CM-027 a D-CM-042, E-CM-018 a E-CM-021). Sem mudança de schema. (1) 4.3 e 4.4:
ProcedureStatus()passa a ser avaliada em ordem, com coluna Ordem (D-CM-030);administeredviracompleted;firstTime(Agenda.PrimeiraConsulta = 'S') emprocedures(D-CM-029);startTimeem “HH:mm” no fuso da clínica (D-CM-042); o total de 4.4 inclui os finalizados (D-CM-038). (2) 4.6 e 4.7: janela de “a assinar” em dias de calendário, com{LimiteAssinaturaUTC}(D-CM-037); “a revisar” exclui a prescrição assinada depois de a janela abrir (exceção (a), D-CM-040, E-CM-019) e a de administração iniciada (exceção (b), D-CM-039, E-CM-018); “a assinar” com administração iniciada continua contada;minutesRemainingé a base dos textos de tempo (D-CM-041). (3) 4.8 e 4.9:sourceTypeUser | Systememessages[].type=Response(D-CM-042). (4) Revisão por Dois Críticos:typede 4.7 com as exceções (a) e (b);{InicioJanelaRevisaoLocal}marcado como valor por linha; texto do KPIurgentalinhado ao SQL; tabelaPacientelistada em 4.6; contagem da massa desatualizada retirada do corpo. -
v5.3 (10/10/2026) — Acompanha 01-Definição v5.3 e 02-Especificação v5.3. Decisões em 05 - Registro de Decisões v1.2 (D-CM-017 a D-CM-026, E-CM-016 e E-CM-017). Revisão por Dois Críticos (técnico e negócio/UX) antes de fechar: ver o Histórico do Registro. Sem mudança de schema. (1) 4.6: o limite de “a revisar” passa a
Agenda.DhAgendaIniUTC < {LimiteRevisaoUTC}, meia-noite local de (hoje + N + 1) no fuso da clínica (D-CM-023); o texto da diferença para o sistema atual foi reescrito. (2) 4.1:elapsedMinuteseovertime(D-CM-017);tagsretorna ordenada por finalidade e sigla (D-CM-022); vigência de tag por data, início e fim inclusivos (D-CM-021). (3) 4.7:minutesRemaining(E-CM-016). (4) Prescrições semIdAgendaficam fora (D-CM-025). (5) O painel “Pacientes em procedimento” substitui “Procedimentos hoje” (D-CM-019). -
v5.2 (09/10/2026) — Acompanha 01-Definição v5.2 e 02-Especificação v5.2. Decisões em 05 - Registro de Decisões v1.1. Revisão por Dois Críticos (técnico e negócio/UX) antes de fechar: achados aplicados; os que dependem do solicitante estão em P-CM-019 a P-CM-027. Sem mudança de schema. (1) 4.6: padrão de 1 dia no
COALESCEdeNumeroDiasRevisaoPrescricoes(comTRY_CONVERT), seeds e textos; o sistema atual assume 2;toSignWindowDayscom SQL executável; SQL de referência dePrescriptionToSignNext7DaysCount()incluído;Paciente.RemovidoEmno SQL de “a revisar”; texto de escopo alinhado à v4.46 (prescritor ou médico assistente nas três métricas). (2) 4.7:hoursRemainingnegativo, inteiro truncado em direção a zero, classificação sobre minutos (E-CM-015);typecom padrão de 1 dia. (3) 4.3:progress=CAST(ROUND(DATEDIFF(MINUTE, DhAtendimentoIniUTC, agora) * 100.0 / NULLIF(TempoAplicacao, 0), 0) AS int), nulo sem tempo (D-CM-015, E-CM-012). (4) 4.1 (tags):DataFimigual ao início de hoje ainda vale hoje (E-CM-014). -
v5.1 (09/10/2026) — Acompanha 01-Definição v5.1 e 02-Especificação v5.1; decisões em 05 - Registro de Decisões. (1) 4.2:
delayedpassa a exigirDhAtendimentoIniUTCnulo — consulta em atendimento é pendente, não atrasada (D-CM-008). (2) 4.1:patient.diagnosissó retorna diagnóstico cujoPEP.DataInicioUTCé até o fim de hoje no fuso da clínica (D-CM-010);PEP.DataInicio/DataFimnão são lidos, só os campos UTC (D-CM-009). (3) 4.6 e Seeds:PrescricaoTempoRevisao(proposto, nunca aplicado) substituído porNumeroDiasRevisaoPrescricoes, parâmetro já existente no sistema atual, com padrão de 2 dias na ausência da linha; a janela continua contínua em horas, e não em dias de calendário como no sistema atual (D-CM-006, E-CM-005); o parâmetro deixa de ser um seed novo. (4) 4.9: o estado de resolvida/descartada fica naConversa, e vale para todos os destinatários (D-CM-011). (5) Termo “Procedimentos hoje” no lugar de “Procedimentos na Clínica” no corpo (D-CM-005). (6) Corpo atemporal: retiradas algumas frases “nesta versão” das seções de prescrição; as demais, e as menções a versões antigas de documentos nas seções de mensageria e de pendências, seguem como estavam. (7) Revisão por Dois Críticos (09/10/2026): crítico técnico e crítico de negócio/UX sobre o pacote v5.1; o Designer conferiu cada achado contra os arquivos antes de aplicar. Aplicado:IpParametro.Descricaodo seed dePrescricaoTempoAssinaturareduzida para caber em varchar(100); descrição dePrescricaona 4.6 alinhada ao filtro P/G/A/O;TRY_CONVERT(int, ...)na leitura deNumeroDiasRevisaoPrescricoes; redação atemporal dos parágrafos dos parâmetros e da resolução do nome do autor. Em aberto: escopo “prescritor ou assistente” × “apenas prescritor” nas funções de prescrição (P-CM-005). -
v5.0 (08/10/2026) — Abertura da versão 5.0 a pedido do solicitante (“Pode ajustar todos os pontos pendentes derivadas das outras funcionalidades”). Acompanha 01-Definição v5.0 e 02-Especificação v5.0. Atende as pendências que a Agenda do Médico (Mapeamento v1.6, Pendências, item 2), o Log de Mudanças Estruturais do Banco de Dados (07 e 08/10/2026) e o Design System deixaram para a Central: (1) Bloqueio de horário (RN-CM-030): o filtro
Paciente.Paciente <> 'B'passa a descrever o bloqueio feito pela Recepção (RN-AGM-019); sai a remissão a “mecanismo e seed a detalhar” na Agenda (RN-AGM-004, retirada, e RN-AGM-011). O filtro em si não muda. (2) Tags (4.1 e 4.3):tagspassa de lista de nomes para lista de objetoscode/description/color, como na Agenda (o Mapeamento já dizia que cor e descrição vêm deProgramaApoio); entra a origem do prontuário,PEPProgramaApoioPaciente→PEP, com a vigência dePEP.DataInicioUTC/DataFimUTC(camposdatetimeoffset NULLconfirmados nocatalog.jsonda Biblioteca de Schema — a afirmação contrária, que constava na Agenda e no Log de 08/10, não procede) e regra de intervalo para períodos com hora; a tag VIP vem deProgramaApoioPacienteePaciente.PacienteVipdeixa de ser lido, seguindo a decisão do solicitante registrada na Agenda do Médico (Mapeamento v1.6: “desconsidere o campoPaciente.PacienteVip, por enquanto”) — o achado sobre a origem de VIP, que estava [A DEFINIR], fica encerrado também aqui; tabelasPEP,PEPProgramaApoioPaciente,ProgramaApoioeProgramaApoioPacienteentram em “Tabelas envolvidas” de 4.1 e 4.3. A nota sobre a cor da tag VIP foi reescrita sem referência a versões (o histórico está nas entradas anteriores). (3) Exclusão lógica: regra geral no início da Seção 4 (RemovidoEm IS NULLnas tabelas que têm o campo, conferidas na Biblioteca de Schema —Agenda,Paciente,PEP,PEPDiagnostico,ProgramaApoio,ProgramaApoioPaciente;Prescricao,PacienteFotoePEPProgramaApoioPacientenão têm) e filtro explícito em 4.1 a 4.5, 4.6 (consulta de revisão) e 4.7;patient.diagnosisignoraPEPePEPDiagnosticoexcluídos; também emPatientInTreatmentCount(),TreatmentPlanAdherenceCount(),PrescriptionToSignNext7DaysCount(), 4.8 (paciente da conversa) e 4.10 (busca de pacientes). OStatusA/I do legado não é usado como critério de ativo. (4) Fuso:ClienteEmpresa.FusoOficial(deslocamento) dá lugar aClienteEmpresa.FusoHorarioOficial(IANA) em 4.1, 4.3 e 4.4; nova subseção “Campos novos” remete à definição na Agenda. (5)AppointmentStatus(): passa a ser avaliada em ordem de precedência (canceled, finished, consultation, checked, waiting, scheduled), a mesma da Agenda; resolve a sobreposição deSituacao = 'V'com fim preenchido e início vazio (valefinished). (6) Índices: nova subseção, [PROPOSTA], remetendo ao índice proposto na Agenda (a confirmar com o time de banco) e avaliando se atende 4.1 a 4.4. (7) Próximos passos: o menu do usuário passa a ter “Tema” e “Sair”. (8) Correções de consistência achadas na revisão:firstTimepassa aboolean(Agenda.PrimeiraConsulta = 'S'), como na Especificação e na Agenda;prefferedNamecorrigido parapreferredName; ids deprocedureseprescriptions(4.3, 4.7) passam aint(Prescricao.IdPrescricao/IdPacientesãointno DDL; o exemplo de 4.3 traziauuid);DhAtendimentoFim(coluna inexistente) corrigido paraDhAtendimentoFimUTCemProcedureStatus();Conversa.PacienteIdcorrigido paraConversa.IdPaciente(4.8). Não aplicado: limpeza das referências a versões anteriores (“nesta versão”, “v4.39” etc.) que ainda existem nas seções de prescrições e de mensageria — fora do escopo desta rodada. -
v4.48 (29/09/2026) — Acompanha 01-Definição v4.42 (RN-CM-030) e 02-Especificação v4.37: (1) novo filtro
Paciente.Paciente <> 'B'nos endpointsGET /appointments(4.1) eGET /kpis/appointments-today(4.2), comPacienteincluído nas tabelas envolvidas de 4.2 — o registro de bloqueio de horário da Agenda do Médico é gravado como agenda de consulta (TipoAgenda = 'C', default decidido pelo solicitante) com o paciente reservado “B” (Paciente.Paciente = 'B', campo já confirmado na Biblioteca de Schema — DDL, na Definição v1.2 da Agenda do Médico), então o filtro porTipoAgendasozinho não o excluía; o filtro é pelo paciente reservado, não pelo convênio reservado, por ser o identificador já usado como chave de junção do endpoint. Outros endpoints deste documento não precisam do filtro: 4.3/4.4 filtram outros tipos de agenda, e 4.5 só conta agendas comSituacao = 'V'(check-in), que um bloqueio nunca recebe — suposição do Designer, a confirmar na Seção 4 da Agenda do Médico, que definirá aSituacaogravada no bloqueio; (2) campotypede 4.1 renomeado paraattendanceMode(mesma origem,Agenda.Atendimento). -
v4.47 (29/09/2026) — Acompanha 01-Definição v4.41: 2 esclarecimentos do solicitante, ambos sem mudança de comportamento observável no painel. (1)
IdChProfissionalAssinou/DataAssinaturaPrescricaosão um par, não 2 fontes independentes: RN-CM-029 (Precedência 1) verificava “3 fontes” de assinatura —PrescricaoAssinatura.TipoAssinatura = 'A',Prescricao.DataAssinaturaPrescricao,Prescricao.IdChProfissionalAssinou— tratando os 2 campos legados como independentes, um deles “sem data própria” ([A DEFINIR] desde a v4.28). O solicitante esclareceu que são o mesmo evento de assinatura:IdChProfissionalAssinoué quem assinou,DataAssinaturaPrescricaoé quando. Reescrito para “2 fontes” (moderna + par legado) em toda a Seção 4.6/4.7 (prosa dePrescriptionToReviewCount(),PrescriptionUrgentCount(),PrescriptionToSignNext7DaysCount(), comentários da SQL, Nota de compatibilidade legada, mapa de campos e filtroto_signdo endpoint). A SQL não muda (oORdas 2 colunas legadas é mantido por segurança contra dado legado incompleto, mas os comentários deixam de descrevê-las como independentes). (2) Resolução do nome da equipe —[PROPOSTA]da v4.24 decidida: o solicitante escolheu a alternativa de vínculo histórico — o sufixo “(Equipe)” noauthorNamepassa a checarEquipeMembro.AdicionadoEmUtc <= Mensagem.CriadoEmUtc AND (RemovidoEmUtc IS NULL OR RemovidoEmUtc > Mensagem.CriadoEmUtc), refletindo o vínculo na época do envio da mensagem, em vez do vínculo atual no momento em que o card/thread é exibido. Isso preserva o sufixo em mensagens antigas de quem já saiu da equipe, e não aplica o sufixo retroativamente a mensagens anteriores à entrada de um membro novo. Revisão por Dois Críticos: não aplicável — esclarecimentos/decisões diretas do solicitante sobre pontos já documentados como em aberto. -
v4.46 (29/09/2026) — Acompanha 01-Definição v4.40 e 02-Especificação v4.36: 2 correções do solicitante sobre achados que a v4.45 havia deixado em aberto. (1) Escopo de
to_signcorrigido: até esta versão,PrescriptionToSignNext7DaysCount()e o filtroto_signdo endpoint (4.7) restringiam a assinatura ao próprio prescritor (IdChProfissionalMed = médico logado, citando RN-CM-012) e nunca eram afetados porreviewScope— o solicitante esclareceu que isso está errado: qualquer médico pode assinar uma prescrição.to_signpassa a usar o mesmo critério “mine”/“all” deto_review(reviewScope):mine=IdChProfissionalMed = médico logadoOUPaciente.IdChProfissional = médico logado;all= sem restrição. CampoisPreferredReviewer(4.7), antes presente só emtype = to_review, passa a ser calculado também paratype = to_sign. A citação a RN-CM-012 para essa restrição nunca esteve correta (essa regra trata do modo de assinatura — certificado ou sessão —, não de quem pode assinar). (2)TreatmentPlanAdherenceCount()(Seção 4.5) não deve mais contar prescrições canceladas: a Condição 2 (“prescrição esperada não realizada”) incluíaSituacao = 'C'(Cancelada) na lista de situações que contam como não-aderência — o solicitante esclareceu que uma sessão cancelada é uma decisão deliberada, não uma omissão, e não deveria contar. ListaSituacao IN ('P','G','A','C')corrigida paraIN ('P','G','A'); texto do comentário (“não chegou a Q/F”), que o solicitante não entendeu, reescrito em linguagem mais direta. Ambas as correções vieram de esclarecimento direto do solicitante sobre achados já relatados na v4.45 (crítico técnico) — não de interpretação nova. Revisão por Dois Críticos: não aplicável nesta rodada. -
v4.45 (28/09/2026) — Acompanha 01-Definição v4.39: RN-CM-020 simplificada, abolindo o conceito de “assinatura vencida” (v4.30-v4.44). Reescritos
PrescriptionToReviewCount()(SQL e prosa),PrescriptionUrgentCount()ePrescriptionToSignNext7DaysCount()(Seção 4.6), e os filtros/mapa de campos do endpoint/prescriptions(Seção 4.7): a Precedência 1 (“a assinar”) não verifica mais idade de assinatura, só existência (3 fontes de RN-CM-029); a Precedência 2 (“a revisar”) não verifica mais validade da confirmação de revisão, só existência de QUALQUER registroTipoAssinatura = 'R'. Isso resolve, por tabela, a ambiguidade [A DEFINIR] aberta desde a v4.28 sobrePrescricao.IdChProfissionalAssinousem data própria (sem vencimento a calcular, essa fonte passa a valer como as demais). ParâmetroPrescricaoValidadeAssinatura(v4.30) retirado — sua única função (janela de validade da assinatura) deixou de existir; como nunca foi aplicado em produção em nenhum cliente ([PROPOSTA] durante toda sua existência neste documento), a remoção não tem custo de migração. Novo parâmetroPrescricaoTempoAssinatura[PROPOSTA] — mesmo padrãoIpParametro/IpParametroChavedePrescricaoTempoRevisao, default 7 dias — passa a governar a janela de “a assinar” (PrescriptionToSignNext7DaysCount()), que até esta versão usava um corte de 7 dias fixo no código, sem parâmetro (pedido explícito do solicitante: “parâmetro — se não existir, vamos criar”). NomePrescricaoTempoAssinaturaé uma decisão do Claude nesta versão (convenção “Tempo” + conceito, espelhandoPrescricaoTempoRevisao), não um nome pedido pelo solicitante — sujeito a ajuste. Novo filtro dePrescricao.Situacao(RN-CM-020), também pedido pelo solicitante nesta rodada:PrescriptionToReviewCount(),PrescriptionToSignNext7DaysCount()e o endpoint/prescriptionspassam a exigirSituacao IN ('P','G','A','O')— motivado por um achado ao conferir a nova regra contraCargaCMZero.xlsx: sem esse filtro, e sem o mecanismo de expiração para “limpar” o histórico, 34 das 74 prescrições da massa (incluindo registros de dez/2025, já finalizados/faturados) apareceriam em “a revisar” para sempre, por não existir nenhum registroTipoAssinatura = 'R'na massa hoje; com o filtro de situação, apenas 8 prescrições “em andamento” qualificam — quantificação completa e por médico nos Cenários de Teste v1.19. Precedente: entre 25-27/09/2026, uma simplificação semelhante já havia sido tentada e revertida a pedido do solicitante (“me precipitei” — ver Histórico/04 - Mapeamento de Banco de Dados v4.40 - REVERTIDA); confirmado explicitamente com o solicitante nesta rodada que o pedido atual (mais específico: parâmetros nomeados, filtro de situação, janela de “a assinar” parametrizada) é deliberado. Acompanha 02-Especificação v4.35, 01-Definição v4.39 e Cenários de Teste v1.19 (03-Protótipo sem mudança de conteúdo — apenas sincronização de cabeçalho). Revisão por Dois Críticos (crítico técnico): 2 correções — (1) alinhado o texto dePrescriptionToSignNext7DaysCount()(Seção 4.6) ao do filtroto_sign(Seção 4.7): a janela usa só limite superior, sem piso em “agora” — aplicações já atrasadas continuam elegíveis, como já valia paraPrescriptionToReviewCount(); (2) mantida a formulação anterior do filtroto_sign(nunca afetado porreviewScope). Achados adicionais registrados para decisão do solicitante, fora do escopo desta rodada (não introduzidos por ela): possível inconsistência entre a restrição deto_signao próprio prescritor e o comportamento observado no toggle “Todas” nos Cenários de Teste (prescrições 61/71 cruzando entre médicos); badge do cartão de Benjamin Thompson C1D2 em CT-PRES-02.1/02.2 a conferir contra a massa real; e inclusão deSituacao = 'C'na Condição 2 deTreatmentPlanAdherenceCount()(Seção 4.5, código anterior a esta rodada) — ver relatório completo do crítico técnico. -
(sincronização, 28/09/2026) — sem mudança de conteúdo deste documento; apenas a linha de cabeçalho “Documentos desta funcionalidade” atualizada para apontar Especificação v4.34 e Protótipo v3.18 (mensagem de estado vazio dividida por estado do toggle nos painéis de Prescrições Pendentes e Procedimentos na Clínica — ver Histórico desses dois documentos).
-
v4.44 (28/09/2026) — Contexto acrescentado ao achado em aberto da v4.43 (Seção 4.1, campo
tags): o solicitante classificouPaciente.PacienteVipcomo um conceito legado, de uso futuro incerto — não uma confirmação de que a associaçãovip↔paciente venha desse campo (bit), nem uma decisão de descontinuá-lo. A nota da Seção 4.1 foi reescrita para refletir essa posição; o achado continua em aberto e a lógica documentada (UNION entrePaciente.PacienteVipeProgramaApoioPaciente/ProgramaApoio) não muda nesta rodada, apesar de a massa real já usar apenas o segundo mecanismo para os 2 pacientes VIP cadastrados (3 e 12). Acompanha Cenários de Teste v1.17 (nova pendência aberta em “Pendências de Massa de Dados”, para que a QA não monte casos de teste assumindoPaciente.PacienteVipcomo fonte). -
v4.43 (28/09/2026) — Correção pedida pelo solicitante: a cor da tag VIP é verde,
#80FF38, conforme cadastrada emProgramaApoio— confirmado contraCargaCMZero.xlsx(IdProgramaApoio=1, Nome=‘VIP’). Isso contradiz a nota da Seção 4.1 (campotags) que, desde sempre neste documento, dizia quevip“usa o token de destaque do Design System, Seção 2.8” — uma suposição que nunca teve entrada própria no Histórico como decisão confirmada, e que a Seção 2.8 da Especificação (conferida nesta rodada) não sustenta. Corrigido: cor/descrição deviptambém vêm deProgramaApoio(mesma fonte das outras 7 tags), mantendo intacta a exceção devipaos filtros deMostrarEme vigência (regra de negócio à parte, RN-CM-025, confirmada e revisada em versões anteriores — sem mudança aqui). Achado em aberto, sinalizado mas não resolvido nesta rodada: a massa real já temvipassociado a pacientes viaProgramaApoioPaciente(mesmo mecanismo das outras tags, não viaPaciente.PacienteVip) — ver nota completa e pendência de confirmação na Seção 4.1. Acompanha 02-Especificação (sem mudança de conteúdo nesta rodada) e Cenários de Teste v1.16 (3 ocorrências de “VIP (lilás-claro)” corrigidas para “VIP (verde)”) e 03-Protótipo v3.17 (.chip-vipcorrigido de azul para verde). -
v4.42 (28/09/2026) — Decisões do solicitante sobre os pontos em aberto da v4.41: (1)
PatientInTreatmentCount()(4.5): default de 180 dias quandoTempoPacienteAtivoAgenda/TempoPacienteAtivoPrescricaonão existirem para a clínica — implementado viaCOALESCE(..., 180)nas duas subconsultas, substituindo o[A DEFINIR]; (2) divergência de valor resolvida — o correto é 180 dias; o seed deInfra-estrutura/(BD-M) Dados incluídos obrigatórios.md(que gravava 120) foi corrigido, com a cópia anterior arquivada emInfra-estrutura/Histórico/; (3) janela dePrescricaoTempoRevisaoconfirmada como contínua a partir do momento atual (1 dia = 24 horas), como já descrito na v4.41 — sem mudança de texto. -
v4.41 (28/09/2026) — Pedido do solicitante, após levantamento dos parâmetros usados pela Central do Médico. (1) Seção 4.5,
PatientInTreatmentCount(): a query de exemplo usavadateadd(day,-180, ...)fixo — passa a lerTempoPacienteAtivoAgendaeTempoPacienteAtivoPrescricaodeIpParametroChave(mesmo padrão de 4.6); unidade dos dois parâmetros definida como dias; corrigido o erro de digitaçãoIpParametroTempoPacienteAtivoPrescricao→IpParametro.TempoPacienteAtivoPrescricao;IpParametro/IpParametroChave(GescomClienteAlfa, conferidas na Biblioteca de Schema — DDL,gescomAlfa.sql) adicionadas às Tabelas envolvidas. Registrados como pendência: comportamento quando esses parâmetros não existem para a clínica ([A DEFINIR]) e a divergência entre o seed deInfra-estrutura/(BD-M) Dados incluídos obrigatórios.md(120 dias) e o padrão de RN-CM-024 (180 dias). (2)PrescricaoTempoRevisaoem dias (Seção 4.6, 4.7 e Seeds): unidade muda de horas para dias;DATEADD(HOUR, ..., 24)→DATEADD(DAY, ..., 1); seedValor24 → 1;DescricaodoIpParametroajustada; explicitado que a janela é contínua a partir de agora (1 dia = 24 horas), não por dia de calendário — mantém o comportamento anterior.IpParametro/IpParametroChaveadicionadas às Tabelas envolvidas de 4.6. (3) Modo de assinatura (RN-CM-012): registrado como [A DEFINIR] ao final de “Seeds da Funcionalidade” — o parâmetro que guarda a configuração ainda não é conhecido. -
(sincronização, 28/09/2026) — sem mudança de conteúdo deste documento; apenas a linha de cabeçalho “Documentos desta funcionalidade” atualizada para apontar Especificação v4.31 (janela de antecedência de revisão de RN-CM-020 descrita como parâmetro por clínica,
PrescricaoTempoRevisao, em vez de 24h fixo). -
v4.40 (28/09/2026) — Reescrita das funções de assinar/revisar (4.6) e do endpoint 4.7, para RN-CM-020 (Precedência 1/2, reescrita) e RN-CM-029 (nova) em 01-Definição v4.36, corrigindo uma rodada anterior (25-27/09/2026) revertida por ser precipitada. Mudanças: (1)
PrescriptionToReviewCount()reescrita para separar claramente as duas precedências — a idade que importa para “vencida → a assinar” (Precedência 1) é a mais recente entrePrescricaoAssinatura.TipoAssinatura = 'A'e o campo legadoPrescricao.DataAssinaturaPrescricao(RN-CM-029, viaOUTER APPLY/UNION ALL, não mais umCOALESCEsimples); a existência deTipoAssinatura = 'R'dentro da mesma janela de validade agora é checada separadamente (Precedência 2, “já foi revisada”) em vez de estar misturada na mesma cláusulaNOT EXISTSque também comparavaTipoAssinatura = 'A'. (2)PrescriptionToSignNext7DaysCount()reescrita — antes só cobria “nunca assinada”; agora cobre a Precedência 1 completa de RN-CM-020 (nunca assinada OU assinada mas vencida), usando a mesma lógica de idade dePrescriptionToReviewCount()com o sinal invertido. (3)PrescriptionUrgentCount()atualizada para reaproveitarPrescriptionToSignNext7DaysCount()em vez de duplicar sua própria checagem de “não assinada” desatualizada. (4) Domínio dePrescricaoAssinatura.TipoAssinatura(4.7) ganhou nota explicando quePrescricao.DataAssinaturaPrescricao/IdChProfissionalAssinounão geram linha real na tabela — são lidos diretamente dePrescricao. (5) Campotypee filtrosto_sign/to_reviewdo endpoint 4.7 atualizados para apontar para as funções corrigidas, em vez de repetir a lógica antiga inline. [A DEFINIR] registrado em RN-CM-029/01-Definição:Prescricao.IdChProfissionalAssinou, sem data própria, é tratado como assinatura sem vencimento enquanto não houver confirmação do solicitante em contrário — refletido nas queries acima (assinatura.UltimaData IS NULLcomo caso separado, nunca reprovado por idade). Nenhuma tabela nova —PrescricaoAssinatura.TipoAssinatura = 'R'já estava documentado no domínio desde antes desta versão, só não tinha uma query própria que o isolasse da checagem de vencimento da assinatura original. Verificado contra a massa real (CargaCMZero.xlsx, data-base 24/09/2026 12:00): das prescrições rastreadas emCenários de Teste, só a 70 muda de classificação (sai de “a assinar” — via RN-CM-029, sua assinatura mais recente,DataAssinaturaPrescricaode 18/09, está dentro da validade, mas a aplicação está a mais de 24h, então também não entra em “a revisar”); nenhum registroTipoAssinatura = 'R'existe na massa hoje, então a Precedência 2 não reclassifica nenhuma prescrição adicional nesta rodada — cobertura de dado real para esse caminho fica pendente para uma carga futura. Detalhamento completo:Cenários de Teste v1.10. Revisão por Dois Críticos (crítico técnico): 1 correção — a primeira versão desta query usavaCOALESCEsimples entre a subquery dePrescricaoAssinaturaeDataAssinaturaPrescricao, o que escolhe o primeiro valor não nulo em vez do mais recente; corrigido paraUNION ALL+MAX(), garantindo que a data mais recente das duas fontes prevalece mesmo quando a fonte legada é a mais nova (caso real da prescrição 70). -
(sincronização, 25/09/2026) — sem mudança de conteúdo deste documento; apenas a linha de cabeçalho “Documentos desta funcionalidade” atualizada para apontar Definição v4.35 e Especificação v4.30 (RN-CM-027 e RN-CM-028, ordenação do Painel de Procedimentos e tag “1ª Consulta” — ver Histórico desses dois documentos).
-
(sincronização, 24/09/2026) — sem mudança de conteúdo deste documento; apenas a linha de cabeçalho “Documentos desta funcionalidade” atualizada para apontar Especificação v4.29 (confirmação do critério de desempate das conversas lidas no painel de Mensagens — ver Histórico desse documento).
-
v4.39 (24/09/2026) — Esclarecimento do solicitante, fechando um ponto que eu tinha sinalizado como não confirmado na v4.38:
DhAtendimentoIniUTCmarca o início real do atendimento — preparo do paciente, pré-medicações etc. — que antecede o início da infusão propriamente dita;DhInfusaoIniUTC/DhInfusaoFimUTC(usados só emProcedureStatus()) marcam início/fim do primeiro medicamento do protocolo, que ocorre depois desse preparo. Confirma questartTime(Seção 4.3) já usa o campo correto (atendimento, não infusão) — não muda a fórmula, só documenta o porquê. Observação acrescentada ao Mapa de Campos. Sem mudança de RN/regra de negócio (01/02/03 não mudam — apenas cabeçalho sincronizado). Revisão por Dois Críticos: não aplicável (esclarecimento factual, sem decisão nova a revisar). -
v4.38 (23/09/2026) — Pedido do solicitante, complementando RN-CM-026 (01-Definição v4.34) e Seção 2.6 (02-Especificação v4.28): fórmula de
startTime(4.3) ganhou um terceiro ramo, avaliado primeiro — quando o procedimento está Finalizado (Situacao='V' AND DhAtendimentoFimUTC IS NOT NULL, mesma condição definishedemProcedureStatus()), o campo passa a trazerAgenda.DhAtendimentoFimUTCem vez deDhAtendimentoIniUTC. Observação adicionada sinalizando que o campo continua se chamandostartTimepor herança do contrato já em uso, mesmo passando a carregar um horário de término em um dos casos — não renomeado nesta revisão, por ser mudança de contrato fora do pedido desta rodada. Revisão por Dois Críticos (crítico técnico): nenhuma correção necessária. -
(sincronização, 23/09/2026) — sem mudança de conteúdo deste documento; apenas a linha de cabeçalho “Documentos desta funcionalidade” atualizada para apontar Definição v4.33, Especificação v4.27 e Protótipo v3.15 (RN-CM-011 — texto simples para tempo restante ≥24h no painel de Prescrições Pendentes, sem badge — ver Histórico desses três documentos). Sem mudança de Seção 4: a lógica é só de apresentação sobre o campo
hoursRemaining, que já existia. -
v4.37 (23/09/2026, mesmo dia) — Correção do solicitante: o filtro de
MostrarEmdos dois endpoints (Consultas, Seção 4.1; Procedimentos na Clínica, Seção 4.3) usava o bit 4 (& 8, “Central do Médico”) desde a v4.34 — presumido por ser o nome da própria tela, sem confirmar com o solicitante. Está errado: os dois painéis são, na prática, agendas do dia (de consultas e de quimioterapia/infusão), e o bit que rege a exibição é o 6 (& 32, “Agendas”), independente de qual tela os hospeda; corrigido nos dois endpoints (Mapa de Campos e Filtros). Confirmado com o solicitante que o segundo painel (Procedimentos na Clínica) segue a mesma regra do primeiro, em vez de perguntar duas vezes. Tabela de domínio (Seção 4.1) ajustada: removida a nota errada “(este documento)” do bit 4; anotado no bit 6 que é o usado pelos dois endpoints daqui; acrescentada nota explícita de que o bit 4 não é usado por nenhum endpoint deste documento, e que sua aplicação em outro lugar do Cockpit (se houver) não foi confirmada nesta rodada — para não deixar a impressão de que a investigação cobriu mais do que cobriu. RN-CM-025 (01-Definição) não muda — a regra de negócio (“habilitada para esta tela”) continua correta em linguagem de negócio, só o bit técnico por trás dela mudou. Revisão por Dois Críticos (crítico técnico): conferido que a correção não deixou nenhuma menção residual a& 8/bit 4 em nenhum dos dois endpoints, nem no exemploMostrarEm = 38(que já usava bit 6, não precisou mudar); nenhuma correção adicional necessária. -
v4.36 (23/09/2026) — Pedido do solicitante: harmonizada a convenção de borda de
ProgramaApoio.DataFim— passa a ser inclusiva (hoje <= DataFim), igual aProgramaApoioPaciente.DataFim; era exclusiva (hoje < DataFim) desde a v4.35, quando as duas tabelas foram documentadas lado a lado com convenções diferentes (cada uma seguindo o que havia sido informado literalmente para aquele campo, sem harmonizar por conta própria). Atualizados: tabela de domínio (4 casos), Mapa de Campos (campotags) e Filtros do endpoint, Seção 4.1; Seção 4.3 referencia 4.1, sem alteração própria. Sem mudança emMostrarEmnem no filtro de vigência da atribuição ao paciente (ProgramaApoioPaciente, inalterado). RN-CM-025 (01-Definição) não muda — a regra de negócio já era atemporal, sem mencionar a convenção de borda; ajuste é só técnico. Revisão por Dois Críticos (crítico técnico): conferido que a mudança não afeta a lógica combinada comMostrarEmnem o casoDataInicio+DataFim(agora ambos os limites inclusivos), nenhuma correção necessária. -
v4.35 (22/09/2026) — Pedido do solicitante, complementando a v4.34 no mesmo tema: adicionado o filtro de vigência da própria tag,
ProgramaApoio.DataInicio/DataFim(ambosdatetime NULL, confirmados na Biblioteca de Schema — DDL,gescomAlfa.sql) — distinto do filtro de vigência da atribuição ao paciente (ProgramaApoioPaciente.DataInicio/DataFim), já existente e sem mudança. Criada, na Seção 4.1 (Domínios), a tabela dos 4 casos (nenhuma data / só início / só fim / ambas) com a condição de exibição de cada um — caso “só início” confirmado pelo solicitante comohoje >= DataInicio(a leitura literal da primeira formulação dada pelo solicitante nesta rodada,DataInicio > hoje, contradizia a lógica simétrica dos outros dois casos — perguntado antes de escrever, não presumido). Sinalizada explicitamente a diferença de convenção de borda entre esta tabela eProgramaApoioPaciente(DataFimexclusivo aqui vs. inclusivo lá) — mantida como informada por cada campo, não harmonizada por conta própria. Filtro adicionado aos dois endpoints (Seções 4.1 e 4.3), combinado por E com o filtro deMostrarEmjá existente; não se aplica à tagvip. RN-CM-025 (01-Definição v4.32) reescrita em paralelo. Revisão por Dois Críticos (crítico técnico): conferida a coerência das duas convenções de borda documentadas lado a lado, nenhuma correção necessária. -
v4.34 (22/09/2026) — Pedido do solicitante: documentado o filtro de exibição de tags de atenção, ausente até esta versão — o campo
tags(Seções 4.1 e 4.3) buscava todas as tags ativas do paciente (Paciente.PacienteVipUNIONProgramaApoioPaciente/ProgramaApoio) sem checar em quais telas cada tag foi habilitada. Adicionado o filtro(ProgramaApoio.MostrarEm & 8) = 8aos dois endpoints (bit 4 do domínio — Central do Médico), à tabela “Mapa de campos” (campotags) e à lista “Filtros do endpoint” de cada um; comportamento passa a ser efetivamente implementado, não só documentado. Criada, na Seção 4.1 (Domínios), a primeira tabela completa do domínioProgramaApoio.MostrarEmdeste projeto — mapa de bits de 6 telas com função definida (prontuário, cadastro do paciente, recepção, Central do Médico, confirmação de quimio/Central de atendimento, agendas) e 2 bits (7 e 8) ainda sem função, informado pelo solicitante. O rótulo do bit 5 (valor 16) ficou registrado com dois termos — “Confirmação de quimio” (já registrado antes no Histórico da Agenda do Médico, RN-AGM-006, v1.2) e “Central de atendimento” (informado pelo solicitante nesta rodada) — sem decidir qual é o nome correto/oficial da tela; nenhuma das duas fontes foi descartada, e a divergência foi sinalizada ao solicitante antes de escrever a tabela, sem invenção de qual estaria certa. RN-CM-025 (01-Definição v4.31) reescrita em paralelo para refletir a regra em linguagem de negócio, sem nomes de campo nem aritmética de bits (Lição #20 da Skill Designer). Revisão por Dois Críticos (crítico técnico, Skill Designer) sobre a Seção 4.1/4.3: conferida a aritmética da tabela de domínio contra o exemplo do próprio solicitante (MostrarEm = 38= bits 2+3+6 = 32+4+2, cadastro do paciente + recepção + agendas — bate); conferido que o filtro(MostrarEm & 8) = 8não é aplicado à tagvip(correto,vipnão vem deProgramaApoio); conferido que 4.3 referencia 4.1 em vez de duplicar a tabela (Lição #10). Nenhuma correção necessária. -
v4.33 (16/09/2026) — Quarta correção de
TreatmentPlanAdherenceCount()(Seção 4.5): o solicitante explicou comoPrescricaoProtocolo.Sessaoé de fato definida — o médico informa “é a sessão N do protocolo X, ciclo Y” e o sistema copia o N-ésimo valor deProtocoloGrupo.SessoesSugeridoparaSessao(e Y paraCiclo);Sessaoportanto REINICIA a cada ciclo (não é cumulativo desde o C1D1, como a v4.32 assumia por interpretação própria, não confirmada — e que estava errada). Isso quebrava a condição 3 para sessões deCiclo > 1: comparardiasDecorridos(contado desde o C1D1 global, sem limite) direto contraSessao(sempre um valor pequeno, reiniciado por ciclo) não fecha a conta a partir do 2º ciclo. Corrigido com âncora LOCAL por ciclo: cada Ciclo N tem sua própria âncora (a linha dePrescricaoProtocolodaquele ciclo com o menorSessao, isto é, a 1ª sessão do ciclo); a condição 3 passa a ter duas partes — 3a) sessão comum do ciclo:diasDecorridoscontado desde a âncora do MESMO ciclo, comparado aSessaocomToleranciaEntreSessoes; 3b) início de um novo ciclo (a própria âncora, exceto a do Ciclo 1):diasDecorridosentre a âncora do ciclo atual e a do ciclo anterior, comparado aProtocolo.IntervaloCiclosEmDiascomToleranciaEntreCiclos. Isso também dá finalmente um uso concreto e coerente paraToleranciaEntreCiclos, que nas versões v4.31/v4.32 não tinha um cenário claro de aplicação. Confirmado pelo solicitante com exemplo numérico completo (SessoesSugerido="1,8,15",IntervaloCiclosEmDias=21) antes de escrever no documento. Tabela “Tabelas envolvidas”: descrição deProtocoloGrupo.SessoesSugeridocorrigida (não é mais “valor cumulativo”, é o valor bruto indexado por sessão). Nota sobre criação de prescrições (individual e em massa) adicionada como contexto, fora do escopo deste endpoint. -
v4.32 (16/09/2026) — Terceira correção de
TreatmentPlanAdherenceCount()(Seção 4.5), pedido do solicitante ao revisar a v4.31: (1) a condição 1 (C1D1 real vs. previsto) não pode comparar contra o agendamento (Agenda) sozinho — ela só é possível quando o paciente tem um plano terapêutico (PEPProjetoTerapeuticoProtocolo) para o mesmo protocolo da prescrição real; quando existe, compara-se o C1D1 real (Agenda.DhAgendaIniUTC) com o C1D1 planejado (PEPProjetoTerapeuticoProtocoloProgramacao.DataEstimada,Ciclo=1/Sessao=1); quando não existe plano para aquele protocolo, a condição não se aplica ao paciente.PEP,PEPProjetoTerapeutico,PEPProjetoTerapeuticoProtocoloePEPProjetoTerapeuticoProtocoloProgramacaovoltam à tabela “Tabelas envolvidas”, agora só para esta condição. (2) A condição 3 estava mais complicada do que deveria:Sessao, emPrescricaoProtocolo, já é o total de dias corridos esperados desde o C1D1 (não um deslocamento só dentro do ciclo) — a comparação é direta,ABS(diasDecorridos − Sessao)contra a tolerância, sem a fórmula(Ciclo−1) × IntervaloCiclosEmDias + Sessaoque a v4.31 usava (removida); a escolha entreToleranciaEntreSessoes/ToleranciaEntreCiclospelo ciclo da linha-alvo continua igual. Exemplo numérico do solicitante incorporado ao texto para eliminar ambiguidade futura. -
v4.31 (16/09/2026) — Segunda correção de conceito em
TreatmentPlanAdherenceCount()(Seção 4.5), pedido do solicitante ao revisar a v4.30: o mecanismo adotado na v4.30 (comparar a sessão realizada comPEPProjetoTerapeuticoProtocoloProgramacao.DataEstimada) dependia de um plano terapêutico formal (PEPProjetoTerapeutico) ter sido criado — na prática isso falha porque (a) nem sempre há vínculo entre a prescrição real e a sessão projetada do plano, e (b) muitos médicos não chegam a criar um plano terapêutico no sistema. Substituído por um cálculo ancorado na prescrição C1D1 real (PrescricaoProtocolocomCiclo=1/Sessao=1), sem depender de nenhum plano: para cada prescrição real vinculada a protocolo, compara-se a diferença de dias em relação ao C1D1 com o valor deSessao(que já armazena dias corridos desde o C1D1, não um índice ordinal — esclarecido pelo solicitante), somado a(Ciclo−1) × IntervaloCiclosEmDiasquando a sessão está em outro ciclo. Duas tolerâncias distintas substituem a proposta anterior de uma únicaToleranciaDiasAdesao:Protocolo.ToleranciaEntreSessoes(desvio dentro do mesmo ciclo) eProtocolo.ToleranciaEntreCiclos(desvio que atravessa fronteira de ciclo) — ambas [PROPOSTA], esclarecido pelo solicitante que são dois parâmetros, não um só. A condição 1 (C1D1 vs. agendado) e a condição 2 (prescrição esperada não realizada) tiveram mecânica inalterada; a condição 1 continua com sua origem (“data prevista” = agendamento emAgenda) marcada como interpretação não confirmada nesta rodada, sinalizada no corpo do documento. Tabela “Tabelas envolvidas” da Seção 4.5 atualizada:PEPProjetoTerapeutico,PEPProjetoTerapeuticoProtocoloePEPProjetoTerapeuticoProtocoloProgramacaoremovidas (não são mais usadas por este endpoint);PrescricaoProtocoloeProtocoloGrupoadicionadas. RN-CM-023 da Definição (v4.28) reescrita em paralelo para refletir o novo cálculo em linguagem de negócio, sem nomes de campo. -
v4.30 (16/09/2026) — Rodada de correções após a primeira revisão de versão aprovada (Agente Técnico, ver Skill Designer). (1) Correção de conceito em
TreatmentPlanAdherenceCount()(Seção 4.5): a 2ª das três condições de não adesão comparava incorretamente o intervalo entre sessões consecutivas aProtocolo.IntervaloCiclosEmDias(campo que é o intervalo ENTRE CICLOS, não entre sessões de um mesmo ciclo — apontado pelo solicitante). Reescrita para comparar a data real de cada sessão realizada comPEPProjetoTerapeuticoProtocoloProgramacao.DataEstimada(campo já existente na Biblioteca de Schema — DDL, confirmado nesta versão), que já materializa a data prevista de cada sessão a partir deProtocoloGrupo.SessoesSugerido. Tabela “Tabelas envolvidas” da Seção 4.5 atualizada —Protocolo,PEPProjetoTerapeutico,PEPProjetoTerapeuticoProtocoloePEPProjetoTerapeuticoProtocoloProgramacaojá eram usadas na função mas não apareciam listadas ali. (2) Criado o parâmetroIpParametro.PrescricaoValidadeAssinatura(Seção 4.6) para a “janela de 7 dias” de validade de assinatura/revisão de RN-CM-020, que até esta versão era umDATEADD(DAY, -7, ...)fixo no SQL dePrescriptionToReviewCount()— mesmo padrão dePrescricaoTempoRevisao; adicionado à tabela “Seeds da Funcionalidade”. (3) Removidas as ocorrências de “confirmado com/pelo solicitante” e afins do corpo da Seção 4 (proveniência de decisão não deve aparecer fora do Histórico — ver Lições Aprendidas da Skill Designer); o conteúdo de cada uma está preservado nas entradas de Histórico correspondentes (v4.26/v4.27, acima, para os parâmetros; este parágrafo, para a lógica “OU” de três condições e a colunaToleranciaDiasAdesao, ambas [PROPOSTA] já registradas na Seção 4.5 desde antes da divisão em 4 arquivos). (4) “Próximos Passos” (itens 4 e 5) marcados como feitos — ícones Lucide implementados no Protótipo v3.14; item 6 ajustado para refletir que a navegação por teclado já foi implementada, restando apenas validação formal com usuários. -
v4.25 (29/08/2026) — Arquivo criado pela divisão do documento único
CM_CockPit_do_medico_v4_25.mdem 4 arquivos por seção (ver Skill Designer, “Organização Física: Pasta por Funcionalidade”, Lição #18). Conteúdo desta seção sem alteração de substância em relação à v4.25 do documento original — apenas reorganização física. O histórico de revisões anterior a esta divisão (v4.0 a v4.25, incluindo o racional de cada mudança) está preservado integralmente no documento original, arquivado emHistórico/CM_CockPit_do_medico_v4_25 (documento único, antes da divisão em 4 arquivos).md. -
v4.26 (30/08/2026) — Pedido do solicitante: a janela de “1 dia (24h)” que dispara o estado “a revisar” de uma prescrição (RN-CM-020) precisa existir como parâmetro real de banco, não só como texto de regra de negócio — mesmo padrão já usado para outros parâmetros por clínica neste documento (
TempoPacienteAtivoAgenda/TempoPacienteAtivoPrescricao, Seção 4.5). Adicionado, na Seção 4.6: (1) referência ao parâmetroIpParametro.PrescricaoTempoRevisao→IpParametroChave.Valorna query dePrescriptionToReviewCount(), substituindo oDATEADD(HOUR, 24, ...)fixo; (2) nova subseção “Parâmetro de configuração — PrescricaoTempoRevisao” [PROPOSTA], com a definição completa das 2 linhas de dado necessárias (IpParametro:IdParametro='PrescricaoTempoRevisao',Descricao,Dominio=NULL,UsuarioControla='S',Tipo='N';IpParametroChave:IdParametro='PrescricaoTempoRevisao',IdChave={Id da Clínica},Valor=24,IdChave2=NULL) e um alerta explícito para Dev/DevOps sobre a necessidade de incluir esse seed na documentação de deploy de cada cliente. Não é uma tabela nova —IpParametro/IpParametroChavejá existem. Filtrotype = to_reviewdo endpoint 4.7 atualizado para referenciar o mesmo parâmetro em vez de “D-1” fixo. -
v4.27 (30/08/2026) — Pedido do solicitante, resolvendo o
[A DEFINIR]da v4.26: (1) comportamento definido para quandoIpParametro/IpParametroChavedePrescricaoTempoRevisaonão existir para a clínica — default de 24h, confirmado pelo solicitante — implementado na query dePrescriptionToReviewCount()(Seção 4.6) viaCOALESCE(..., 24)em vez doSELECTdireto; parágrafo “Atenção Dev/DevOps” reescrito para descrever esse comportamento e remover a pendência; (2) nova subseção “Seeds da Funcionalidade” ao final da Seção 4, consolidando em uma tabela todo dado (não schema) que precisa existir em produção para a funcionalidade funcionar como especificado — pedido explícito do solicitante (“seria bom termos uma subseção com os seeds da funcionalidade”). Por ora contém 1 linha (PrescricaoTempoRevisao, [PROPOSTA]), apontando para a Seção 4.6 em vez de repetir a definição (Lição #10). -
v4.29 (15/09/2026) — Pedido do solicitante: documentado o domínio completo de
Prescricao.Situacao(P/G/A/Q/F/O/E/C — Confirma Prescrição, Gerada, Admitida, Confirmada/Finalizada, Faturada, Aguardando Orçamento, Atendimento Externo, Cancelada), na Seção 4.5 (KPI “Em Tratamento”), onde o campo já era usado em dois filtros (PatientInTreatmentCount(),TreatmentPlanAdherenceCount()) sem a semântica de cada código estar registrada. Confirmado contra a Biblioteca de Schema (DDL):Prescricao.Situacaoéchar(1) NOT NULL, consistente com os 8 códigos de uma letra informados pelo solicitante; a DDL não temCHECKexplícito listando os valores, então o domínio em si vem do solicitante, não da DDL. Deixado explícito que este domínio é distinto do da agenda associada (SituacaoAgenda) — uma prescrição não avança necessariamente junto com sua agenda. -
v4.28 (11/09/2026) — Correção pontual do solicitante: o valor de
PrescricaoAssinatura.TipoAssinaturapara a assinatura do médico está errado em todo o documento — era'M', o correto é'A'. Corrigido em todas as ocorrências da Seção 4.6 (prosa e SQL dePrescriptionToReviewCount(),PrescriptionUrgentCount(),PrescriptionToSignNext7DaysCount()) e da Seção 4.7 (tabela de domínio, mapa de campos, filtros do endpoint, nota final). Não é o mesmo valor dePrescricaoAssinaturaEnfermagem.TipoAssinatura = 'E'(tabela distinta, confirmada na Biblioteca de Schema/DDL) — apenas o'M'→'A'dePrescricaoAssinaturaestava incorreto. Nenhuma outra seção deste conjunto de documentos (01, 02, 03) referenciava esse campo — correção isolada à Seção 4.