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

TabelaBancoFunção no endpoint
AgendaGescomClienteAlfaTabela principal — dados da agenda
PacienteGescomClienteAlfaDados do paciente (nome, nome social)
PacienteFotoGescomClienteAlfaFoto do paciente
PEPGescomClienteAlfaProntuá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
PEPDiagnosticoGescomClienteAlfaDiagnóstico oncológico do paciente
PEPProgramaApoioPacienteGescomClienteAlfaTags atribuídas no prontuário (chave IdPEP, IdProgramaApoio)
ProgramaApoioGescomClienteAlfaCadastro de tags da clínica (sigla, descrição, cor, telas, vigência)
ProgramaApoioPacienteGescomClienteAlfaTags atribuídas no cadastro do paciente, com vigência
TermoTraducaoIpTerminologiaTradução do modo de atendimento e do nome do status (status.name)
DomEstadoAgendaConsultaIpTerminologiaCores de cada status nos temas claro e escuro (status.colors)
ChaveGescomClienteAlfaNome curto da clínica (campo clinic; Chave.Descricao da Agenda.IdChClinica)
ClienteEmpresaIpSegurancaIdioma e fuso horário (IANA) da clínica

Mapa de campos

CampoTipoBancoObservação
idintAgenda.IdAgenda
clinicstring | nullAgenda.IdChClinica → Chave.IdChave → Chave.DescricaoNome 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)
startTimehorárioAgenda.DhAgendaIniUTCsó horário, convertido para o fuso e idioma da clínica
endTimehorárioAgenda.DhAgendaFimUTCsó horário, convertido para o fuso e idioma da clínica
status.domainstringcalculadovide AppointmentStatus()
status.namestringTermoTraducao.TermoValorTermo = 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 / .textchar(7)DomEstadoAgendaConsulta.CorClaroFundo / CorClaroTextoPela mesma chave CodEstado. Base global: iguais para todas as clínicas (DT-016)
status.colors.dark.background / .textchar(7)DomEstadoAgendaConsulta.CorEscuroFundo / CorEscuroTextoIdem. 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)
attendanceModestringAgenda.Atendimento -> TermoTraducao.TermoValorTermo = Agenda.Atendimento, Origem=“IndicadoresModoAtendimento”, Idioma=ClienteEmpresa.IdiomaOficial
firstTimebooleanAgenda.PrimeiraConsulta = 'S'’S’ = sim, ‘N’ = não
delayMinutesintNow(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
elapsedMinutesintDATEDIFF(MINUTE, Agenda.DhAtendimentoIniUTC, SYSDATETIMEOFFSET()) quando DhAtendimentoIniUTC não é nulo e DhAtendimentoFimUTC é nulo (consulta em atendimento)NULL nos demais estados (D-CM-017)
overtimebooleanelapsedMinutes > Agenda.Tempo (duração prevista da agenda, em minutos)false quando elapsedMinutes é nulo ou Agenda.Tempo é nulo; sem tolerância (D-CM-017)
patient.idintAgenda.IdPaciente
patient.preferredNamestringPaciente.NomeSocialse existir, usar este como nome principal
patient.legalNamestringPaciente.Nomese NomeSocial não existir, usar este como nome
patient.photourlPacienteFoto.NomeArquivo, busca IdPaciente e Padrao = ‘S’, se multiplos, retorna o mais recenteurl gerada pelo MinIO
patient.diagnosisarray de stringPEPDiagnostico.Diagnostico para Tipo = ‘O’ e PEP.IdPacienteretorna 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
tagsarray 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:

OrdemStatus retornadoCondição
1canceled (Cancelado)Agenda.Situacao IN (‘C’,‘D’,‘F’,‘I’,‘M’,‘O’,‘T’)
2finished (Finalizado)Agenda.Situacao = ‘V’ AND DhAtendimentoFimUTC IS NOT NULL
3consultation (Em atendimento)Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NOT NULL AND DhAtendimentoFimUTC IS NULL
4checked (Recepcionado)Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NULL
5waiting (Aguardando recepção)Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NOT NULL
6scheduled (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:

ValorSignificado
CConsulta
QQuimioterapia
RRadioterapia
SReserva de sala para assuntos não assistenciais

ModoAtendimento (domínio de Agenda.Atendimento) na tabela Indicadores:

ValorSignificado
PPadrão (Presencial)
TTeleatendimento
CCustomizado
RReservado

SituacaoAgenda (domínio de Agenda.Situacao) na tabela Indicadores:

ValorSignificado
AAberta
VConfirmada (check-in realizado)
CCancelada pelo usuário
DCancelada pelo paciente
MCancelada pelo médico
FFalta
ICancelado por internação
OCancelada por óbito
TTransferido (cancelado)

TipoDiagnostico (domínio de Diagnostico.Tipo):

ValorSignificado
CComorbidade
ODoenç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):

BitValorTela habilitada
11Cabeçalho do prontuário
22Cadastro do paciente
34Recepção (telas de Quimioterapia e de Consulta)
48Central do Médico
516Confirmaçã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
632Agendas (de quimio e de consultas) — usado pelos dois endpoints deste documento (ver nota abaixo)
764sem função definida até esta versão
8128sem 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:

DataInicioDataFimExibida quando
NULLNULLsempre (sem restrição de vigência)
preenchidaNULLhoje >= DataInicio
NULLpreenchidahoje <= DataFim
preenchidapreenchidaDataInicio <= 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 campo CriadoEm da 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)

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 consulta
  • Paciente.Paciente <> 'B' (via Agenda.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 em blocks (RN-AGM-019); esta funcionalidade só os exclui
  • Agenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica) — apenas consultas do dia atual
  • Agenda.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 (campo tags, acima) às habilitadas para agendas (RN-CM-025); não se aplica à tag vip (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 à tag vip; distinto do filtro de vigência da atribuição ao paciente (ProgramaApoioPaciente, já aplicado na origem do campo tags).

4.2 Endpoint: GET /api/v1/cockpit/doctor/kpis/appointments-today

Retornar o indicador de Consultas Hoje

Tabelas envolvidas

TabelaBancoFunção no endpoint
AgendaGescomClienteAlfaTabela principal — dados da agenda
PacienteGescomClienteAlfaSó para o filtro que exclui registros de bloqueio (Paciente.Paciente <> 'B', RN-CM-030)

Mapa de campos

CampoTipoBanco
totalintcount(Agenda.Situacao IN (‘A’, ‘V’))
finishedintcount(Agenda.Situacao=‘V’, Agenda.DhAtendimentoFimUTC IS NOT NULL)
pendingintcount(Agenda.Situacao IN (‘A’, ‘V’), Agenda.DhAtendimentoFimUTC IS NULL)
delayedintcount(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 consulta
  • Paciente.Paciente <> 'B' (via Agenda.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.1
  • Agenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica) — apenas consultas do dia atual
  • Agenda.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

TabelaBancoFunção no endpoint
AgendaGescomClienteAlfaTabela principal — dados da agenda
PacienteGescomClienteAlfaDados do paciente (nome, nome social)
PacienteFotoGescomClienteAlfaFoto do paciente
PrescricaoGescomClienteAlfaPrescrição do procedimento (IdAgenda): código, médico e TempoAplicacao (base do progress)
PEP / PEPProgramaApoioPaciente / ProgramaApoio / ProgramaApoioPacienteGescomClienteAlfaTags do paciente (campo tags), como em 4.1
TermoTraducaoIpTerminologiaTradução do modo de atendimento e do nome do status (status.name)
DomEstadoAgendaProcedimentoIpTerminologiaCores de cada status do procedimento nos temas claro e escuro (status.colors)
ChaveGescomClienteAlfaNome curto da clínica (campo clinic; Chave.Descricao da Agenda.IdChClinica)
ClienteEmpresaIpSegurancaIdioma e fuso horário (IANA) da clínica

Mapa de campos

CampoTipoBancoObservação
idintPrescricao.IdPrescricao
clinicstring | nullPrescricao.IdAgenda → Agenda.IdChClinica → Chave.DescricaoNome 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)
prescriptionCodestringPrescricao.Identificacao
locationstringPrescricao.IdAgenda->Agenda.IdUAtendimento->UnidadeAtendimento.Descricao + Agenda.IdChRecurso->Chave.DescricaoIdUAtendimento pode ser NULL
startTimehoráriose 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
firstTimebooleanAgenda.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.domainstringcalculadovide ProcedureStatus(), avaliado em ordem; valores scheduled, waiting, checked, preparation, administering, administered, finished, canceled (D-CM-030, D-CM-074)
status.namestringTermoTraducao.TermoValorTermo = 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 / .textchar(7)DomEstadoAgendaProcedimento.CorClaroFundo / CorClaroTextoPela mesma chave CodEstado. Base global: iguais para todas as clínicas (DT-016)
status.colors.dark.background / .textchar(7)DomEstadoAgendaProcedimento.CorEscuroFundo / CorEscuroTextoIdem. 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)
progressintCAST(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)
minebooleanPrescricao.IdChProfissionalMed={IdChProfissional do médico logado}
patient.idintPrescricao.IdPaciente
patient.preferredNamestringPaciente.NomeSocialse existir, usar este como nome principal
patient.legalNamestringPaciente.Nomese NomeSocial não existir, usar este como nome
patient.photourlPacienteFoto.NomeArquivo, busca IdPaciente e Padrao = ‘S’, se multiplos, retorna o mais recenteurl gerada pelo MinIO
tagsarray 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):

OrdemStatus retornadoCondição
1canceled (Cancelado)Agenda.Situacao IN (‘C’,‘D’,‘F’,‘I’,‘M’,‘O’,‘T’)
2finished (Finalizado)Agenda.Situacao = ‘V’ AND DhAtendimentoFimUTC IS NOT NULL
3administered (Completo)Agenda.Situacao = ‘V’ AND DhInfusaoFimUTC IS NOT NULL AND DhAtendimentoFimUTC IS NULL
4administering (Em aplicação)Agenda.Situacao = ‘V’ AND DhInfusaoIniUTC IS NOT NULL AND DhInfusaoFimUTC IS NULL
5preparation (Em preparo)Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NOT NULL AND DhInfusaoIniUTC IS NULL
6checked (Recepcionado)Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NULL
7waiting (Aguardando recepção)Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NOT NULL
8scheduled (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:

ValorSignificado
CConsulta
QQuimioterapia
RRadioterapia
SReserva de sala para assuntos não assistenciais

SituacaoAgenda (domínio de Agenda.Situacao) na tabela Indicadores:

ValorSignificado
AAberta
VConfirmada (check-in realizado)
CCancelada pelo usuário
DCancelada pelo paciente
MCancelada pelo médico
FFalta
ICancelado por internação
OCancelada por óbito
TTransferido (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 campo CriadoEm da 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)

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, radio
  • Agenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica) — apenas procedimentos do dia atual
  • Agenda.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) = 32 e o filtro de vigência de ProgramaApoio.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

TabelaBancoFunção no endpoint
AgendaGescomClienteAlfaTabela principal — dados da agenda
PacienteGescomClienteAlfaDados do paciente (nome, nome social)
PacienteFotoGescomClienteAlfaFoto do paciente
PrescricaoGescomClienteAlfaDiagnóstico oncológico do paciente
TermoTraducaoIpTerminologiaTradução do modo de atendimento
ClienteEmpresaIpSegurancaIdioma e fuso horário da clínica

Mapa de campos

CampoTipoBanco
totalintcount(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
inProgressintcount(ProcedureStatus()=administering)
waitingintcount(ProcedureStatus()=waiting OR checked OR preparation)
scheduledintcount(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):

OrdemStatus retornadoCondição
1canceled (Cancelado)Agenda.Situacao IN (‘C’,‘D’,‘F’,‘I’,‘M’,‘O’,‘T’)
2finished (Finalizado)Agenda.Situacao = ‘V’ AND DhAtendimentoFimUTC IS NOT NULL
3administered (Completo)Agenda.Situacao = ‘V’ AND DhInfusaoFimUTC IS NOT NULL AND DhAtendimentoFimUTC IS NULL
4administering (Em aplicação)Agenda.Situacao = ‘V’ AND DhInfusaoIniUTC IS NOT NULL AND DhInfusaoFimUTC IS NULL
5preparation (Em preparo)Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NOT NULL AND DhInfusaoIniUTC IS NULL
6checked (Recepcionado)Agenda.Situacao = ‘V’ AND DhAtendimentoIniUTC IS NULL
7waiting (Aguardando recepção)Agenda.Situacao = ‘A’ AND DhChegadaUTC IS NOT NULL
8scheduled (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:

ValorSignificado
CConsulta
QQuimioterapia
RRadioterapia
SReserva de sala para assuntos não assistenciais

SituacaoAgenda (domínio de Agenda.Situacao) na tabela Indicadores:

ValorSignificado
AAberta
VConfirmada (check-in realizado)
CCancelada pelo usuário
DCancelada pelo paciente
MCancelada pelo médico
FFalta
ICancelado por internação
OCancelada por óbito
TTransferido (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)

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, radio
  • Agenda.DhAgendaIniUTC(no fuso da clínica) = Hoje(no fuso da clinica) — apenas procedimentos do dia atual
  • Agenda.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

TabelaBancoFunção no endpoint
AgendaGescomClienteAlfaAgendamento real do C1D1 (Agenda.DhAgendaIniUTC, via Prescricao.IdAgenda) — condição 1
PacienteGescomClienteAlfaDados do paciente (nome, nome social)
PrescricaoGescomClienteAlfaDiagnóstico oncológico do paciente; data real de cada prescrição vinculada a protocolo
PrescricaoProtocoloGescomClienteAlfaVínculo entre cada prescrição real e o protocolo/ciclo/sessão aplicados (Ciclo, Sessao) — base das condições 2 e 3 de TreatmentPlanAdherenceCount()
ProtocoloGescomClienteAlfaToleranciaEntreSessoes/ToleranciaEntreCiclos (margens de tolerância, ver função abaixo)
ProtocoloGrupoGescomClienteAlfaSessoesSugerido — 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)
PEPGescomClienteAlfaVínculo prontuário↔paciente (IdPaciente) — usado só para localizar o plano terapêutico do paciente (condição 1)
PEPProjetoTerapeuticoGescomClienteAlfaPlano terapêutico do paciente, quando existe — condição 1 só se aplica se houver um para o mesmo protocolo
PEPProjetoTerapeuticoProtocoloGescomClienteAlfaVínculo entre o plano terapêutico e o protocolo (IdProtocolo) — usado para checar se existe plano para o protocolo da prescrição real
PEPProjetoTerapeuticoProtocoloProgramacaoGescomClienteAlfaDataEstimada do C1D1 planejado (Ciclo=1/Sessao=1) — comparada ao C1D1 real na condição 1
TermoTraducaoIpTerminologiaTradução do modo de atendimento
IpParametroGescomClienteAlfaDefinição dos parâmetros TempoPacienteAtivoAgenda/TempoPacienteAtivoPrescricao (janela de atividade, em dias) — PatientInTreatmentCount()
IpParametroChaveGescomClienteAlfaValor de cada parâmetro por clínica (IdChave = Clinica.IdChClinica, Valor em dias) — PatientInTreatmentCount()

Mapa de campos

CampoTipoBanco
inTreatmentintPatientInTreatmentCount()
nonAdherentintTreatmentPlanAdherenceCount()

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)
  • Nas agendas obter as agendas com:
    • Situação ‘V’ e Agenda.RemovidoEm IS NULL; paciente com Paciente.RemovidoEm IS NULL (nas duas partes da consulta)
    • DhAgendaIniUTC > Hoje()-IpParametroChave.Valor (onde IpParametro=TempoPacienteAtivoAgenda)
  • 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 dias

    Clínica dos parâmetros (D-CM-063): {IdClinica} é o Clinica.IdChClinica da 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 PEPProjetoTerapeuticoProtocolo cujo IdProtocolo bate com o IdProtocolo de PrescricaoProtocolo e cujo IdPEP pertence ao PEP do 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, via Prescricao.IdAgenda do C1D1 de PrescricaoProtocolo) com a data estimada do C1D1 do plano (PEPProjetoTerapeuticoProtocoloProgramacao.DataEstimada na linha Ciclo=1/Sessao=1 daquele PEPProjetoTerapeuticoProtocolo); diferença maior que Protocolo.ToleranciaEntreSessoes conta como não aderente.

  • Condição 2 — prescrição esperada não realizada: para qualquer linha de PrescricaoProtocolo do paciente cuja Prescricao.Data já passou e cuja Prescricao.Situacao está 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, C entrava 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 PrescricaoProtocolo seja 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 de Sessao da própria linha (o dia bruto de SessoesSugerido daquela sessão): se ABS(diasDecorridos − Sessao) for maior que Protocolo.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 a Protocolo.IntervaloCiclosEmDias: se ABS(diasDecorridos − IntervaloCiclosEmDias) for maior que Protocolo.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 com ToleranciaEntreCiclos. Ciclo 2/Sessao 8 (3a) realizada em 31/01: diasDecorridos (vs. âncora do Ciclo 2 = 23/01) = 8, ABS(8−8) = 0 → aderente.

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 de ProtocoloGrupo.SessoesSugerido (ex.: N=2 em "1,8,15" → valor 8) e grava esse valor bruto em PrescricaoProtocolo.Sessao (e X em Ciclo) — por isso Sessao reinicia 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): ToleranciaEntreSessoes e ToleranciaEntreCiclos (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 no EsquemaGemed21.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çãoNomeDescrição
PConfirma PrescriçãoPrecede 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.
GGeradaSituaçã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.
AAdmitidaA 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).
QConfirmada/FinalizadaInformada 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”).
FFaturadaQuando o faturamento termina de lançar gastos e ajustes na fatura (fatura marcada como “Fecha Fatura”).
OAguardando OrçamentoDisparada pelo botão de solicitar orçamento no prontuário; prescrições nesta situação entram no processo de Orçamento para o faturamento.
EAtendimento ExternoSubstitui 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).
CCanceladaCancelá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

TabelaBancoFunção no endpoint
PrescricaoGescomClienteAlfaTabela principal — prescrições em Situacao P/G/A/O (RN-CM-020), médico prescritor
PrescricaoAssinaturaGescomClienteAlfaHistórico de assinaturas/revisões — usada para determinar se a prescrição está revisada
AgendaGescomClienteAlfaData/hora agendada da aplicação (via Prescricao.IdAgenda)
PacienteGescomClienteAlfaMédico assistente (IdChProfissional) e exclusão lógica
IpParametroGescomClienteAlfaDefinição dos parâmetros NumeroDiasRevisaoPrescricoes (já existente no sistema atual) e PrescricaoTempoAssinatura (novo), ambos em dias
IpParametroChaveGescomClienteAlfaValor de cada parâmetro por clínica (IdChave = Clinica.IdChClinica)
ClinicaGescomClienteAlfaUma linha por clínica; as de {ClinicasDoMedico} (D-CM-066) são a base de {LimitesPorClinica} (E-CM-032); Agenda.IdChClinica aponta para ela
ClienteEmpresaIpSegurancaFuso (FusoHorarioOficial, IANA) da clínica em que o usuário está logado (D-CM-062)

Mapa de campos

CampoTipoBancoObservação
urgentintPrescriptionUrgentCount()
toReviewintPrescriptionToReviewCount()
toSignNext7DaysintPrescriptionToSignNext7DaysCount()nome mantido por compatibilidade; conta dentro da janela da clínica
toSignWindowDaysintCOALESCE((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) — PrescricaoAssinatura com TipoAssinatura = 'A' (fonte moderna), ou o par legado Prescricao.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; ver PrescriptionToSignNext7DaysCount() 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. Reaproveita PrescricaoAssinatura de novo — um registro com TipoAssinatura = '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 registro R para 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 de PrescriptionToSignNext7DaysCount()), 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 (PrescricaoAssinatura com TipoAssinatura = 'A', ou Prescricao.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 é datetime sem 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 (ver PrescriptionToSignNext7DaysCount()).
  • Pré-requisito — Prescricao.Situacao “em andamento”: só entram no cálculo prescrições com Situacao em P/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) ou F (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):

CampoValor
IdParametroPrescricaoTempoAssinatura
DescricaoDias de calendário a partir de hoje em que prescrição nunca assinada aparece em "a assinar"
DominioNULL
UsuarioControlaS
TipoN

IpParametroChave (linha nova, valor por clínica — exemplo com o padrão-sugerido de 7 dias, correspondente à regra da Seção 1):

CampoValor
IdParametroPrescricaoTempoAssinatura
IdChave{Id da Clínica}
Valor7
IdChave2NULL

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) para toReview e a parcela de revisão de urgent; o mesmo critério (prescritor OU médico assistente) vale para toSignNext7Days e para a parcela de assinatura de urgent, 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

TabelaBancoFunção no endpoint
PrescricaoGescomClienteAlfaTabela principal — versão ativa (Situacao <> 'C'); Identificacao já traz protocolo + ciclo/sessão formatados
PrescricaoAssinaturaGescomClienteAlfaDetermina se a prescrição está assinada e/ou revisada (ver 4.6)
PacienteGescomClienteAlfaNome social/civil do paciente e médico assistente
AgendaGescomClienteAlfaData/hora agendada da aplicação e clínica (IdChClinica)
ChaveGescomClienteAlfaNome curto da clínica (campo clinic)

Domínio — PrescricaoAssinatura.TipoAssinatura

ValorSignificado
AAssinatura do médico (assinatura original da prescrição ou de uma nova versão gerada por edição)
RConfirmaçã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) e Prescricao.IdChProfissionalAssinou (o profissional) formam um par — o mesmo evento legado de assinatura, não duas fontes independentes; juntos, valem como se fosse um registro TipoAssinatura = 'A' em PrescricaoAssinatura, mas nenhum dos dois gera uma linha real ali — são lidos diretamente de Prescricao nas 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

CampoTipoBancoObservação
idintPrescricao.IdPrescricaoidentifica diretamente a versão ativa — não há campo de número de versão a considerar à parte
clinicstring | nullPrescricao.IdAgenda → Agenda.IdChClinica → Chave.DescricaoNome 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.idintPrescricao.IdPaciente
patient.preferredNamestringPaciente.NomeSocialmesmo padrão de appointments (4.1) e procedures (4.3) — enviado sempre, mesmo vazio, para o front sinalizar nome social ao médico
patient.legalNamestringPaciente.Nomeenviado sempre, junto com preferredName
prescriptionCodestringPrescricao.Identificacaosubstitui os antigos protocol/cycle — já vem formatado do banco (ex: “CARBO-TAXOL C3D1”), sem necessidade de montar a string a partir de Protocolo/PrescricaoProtocolo
scheduleDatedatetimeAgenda.DhAgendaIniUTC, via Prescricao.IdAgendaconvertida para o fuso da clínica na exibição
hoursRemainingintcalculado: 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 11menor 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)
minutesRemainingintcalculado: 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)
typestringcalculadoto_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)
isPreferredReviewerboolcalculadotrue 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 de PrescriptionToSignNext7DaysCount() (Seção 4.6 — RN-CM-020 Precedência 1: nunca assinada, 2 fontes de RN-CM-029) AND Agenda.DhAgendaIniUTC < lc.LimiteAssinaturaUTC — até o fim do dia (hoje + PrescricaoTempoAssinatura da 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 de PrescriptionToReviewCount() (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 de IpParametro.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 de PrescriptionToReviewCount().
  • 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 a to_sign quanto a to_review
    • reviewScope = 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 por minutesRemaining ascendente, 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, por id (RN-CM-011, D-CM-047, E-CM-027; hoursRemaining é truncado e não distingue -40 min de +20 min); reviewScope aplicado às duas partes da união, conforme acima
  • Agenda.RemovidoEm IS NULL (agenda da prescrição, via Prescricao.IdAgenda) e Paciente.RemovidoEm IS NULL — exclusão lógica, nos dois tipos
  • Prescricao.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 JOIN com {LimitesPorClinica} (uma linha por clínica de {ClinicasDoMedico}; 4.6) faz o filtro, tanto em reviewScope = mine quanto em all; a clínica de cada uma vem de Agenda.IdChClinica (campo clinic); as janelas de “a assinar” e “a revisar” usam os parâmetros PrescricaoTempoAssinatura e NumeroDiasRevisaoPrescricoes da 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 via PrescricaoVersao, 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

TabelaBancoFunção no endpoint
ConversaGescomClienteAlfaTabela principal — thread, assunto, status, prazo, origem, paciente relacionado, criação (desempate da ordem)
ConversaDestinatarioGescomClienteAlfaSnapshot de quem recebeu a conversa — usada para filtrar pelo médico logado e para saber se há outros participantes (autoenvio, readByOthers)
ConversaLeituraGescomClienteAlfaDetermina se a conversa está lida para o médico logado e se a última mensagem dele foi lida pelos outros participantes (readByOthers)
MensagemGescomClienteAlfaConteúdo e autor da última mensagem da thread (preview do card)
Indicadores, TermoTraducaoIpTerminologiaNome do grau de urgência (Dominio = GrauUrgencia), traduzido para o idioma da clínica [PROPOSTA] (D-CM-088)
EquipeGescomClienteAlfaNome de exibição da equipe (Nome) — usado no sufixo “(Equipe)” do autor quando aplicável (ver “Resolução do nome da equipe” abaixo)
EquipeMembroGescomClienteAlfaDetermina se o autor da mensagem é membro da equipe destino da conversa (Conversa.EquipeId) — decide se o sufixo de equipe aparece
SegUsuarioGescomClienteAlfaPonte legada entre o identificador local (int) e o GUID do IPSeguranca (ver resolução de nome abaixo)
PacienteGescomClienteAlfaNome social/civil do paciente relacionado, quando Conversa.IdPaciente existe
ClinicaGescomClienteAlfaClínica de origem da conversa: Clinica.IdEmpresa = Conversa.IdEmpresa (E-CM-033; confirmado em D-CM-069) → IdChClinica
ChaveGescomClienteAlfaNome 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.IdUsuario e EquipeMembro.IdUsuario são todos int, não GUID — o mesmo tipo de identificador legado local já usado em Profissional.IdUsuario/Prescricao.IdUsuarioAssinatura. O DDL real desmente a suposição de que esses campos armazenam diretamente o GUID de IPSeguranca.dbo.Usuario.Id. A triangulação correta é: IdUsuarioAutor (int) = SegUsuario.IdUsuario (smallint, PK — join dentro do próprio GescomClienteAlfa) → 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 em IPSeguranca.dbo.Usuario.Apelido (mesmo GUID). A mesma triangulação vale para IdUsuarioRemetente, IdUsuarioDestino e ConversaDestinatario.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 em EquipeMembro com EquipeId = Conversa.EquipeId, IdUsuario igual ao SegUsuario.IdUsuario do 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

CampoTipoBancoObservação
iduuidConversa.Id
subjectstringConversa.Assuntonvarchar(200), obrigatório no banco (Mapeamento da Mensageria, 4.1)
sourceTypestringcalculado a partir de Conversa.OrigemTipoSystem se OrigemTipo = 'System'; User se OrigemTipo = 'User' (D-CM-042)
authorNamestringIPSeguranca.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
lastMessagestringMensagem.Conteudo (maior Sequencia da Conversa)
lastMessageAtdatetimeMensagem.CriadoEmUtc (mesma linha)
deadlinedatetimeConversa.PrazoEmUtcpode ser nulo
urgencyLevelobject|nullConversa.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)
statusstringConversa.Statusmapeado para sent/read/responded (ver 2.9; D-CM-087)
unreadboolcalculado: Conversa.UltimaSequencia > ConversaLeitura.UltimaSequenciaLida (ou sem ConversaLeitura)usado para destaque visual e camada de prioridade (RN-CM-015); não filtra o resultado
authorIsMeboolcalculado: Mensagem.IdUsuarioAutor (maior Sequencia) = SegUsuario.IdUsuario do médico logadofalse em alerta do sistema (autor nulo)
readByOthersbool | nullcalculado [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 0Junções com IdEmpresa e ConversaId, como as demais tabelas de mensageria
patientobjectnullPaciente, via Conversa.IdPaciente
clinicstring | nullConversa.IdEmpresa → Clinica.IdEmpresa → Clinica.IdChClinica → Chave.IdChave → Chave.DescricaoNome 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, Equipe e EquipeMembro têm IdEmpresa NOT NULL e chaves estrangeiras compostas (por exemplo Id + IdEmpresa): as junções entre essas tabelas devem usar as duas colunas, e o filtro de IdEmpresa sai só da lista, não das junções. O card mostra a clínica de origem (D-CM-064, campo clinic)
  • Conversa.Status IN ('Sent', 'Read', 'Responded') — exclui 'Resolved' e 'Dismissed'
  • Conversa.UltimaSequencia > ConversaLeitura.UltimaSequenciaLida, OU não existe ConversaLeitura para o médico logado — calcula o campo unread, 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): unread descendente (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 a Ordem de Indicadores; nulo vale 0); depois a chave CASE WHEN Conversa.PrazoEmUtc > lastMessageAt THEN Conversa.PrazoEmUtc ELSE lastMessageAt END descendente (com prazo nulo, vale lastMessageAt); empate: Conversa.CriadoEmUtc descendente; por fim Conversa.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

TabelaBancoFunção no endpoint
ConversaGescomClienteAlfaStatus atual, UltimaSequencia
MensagemGescomClienteAlfaThread completa (GET detalhe); nova linha inserida em POST /reply
ConversaLeituraGescomClienteAlfaAtualizada em POST /read
ConversaAcaoGescomClienteAlfaHistórico append-only — nova linha em toda ação (leitura, resposta, resolução, descarte)
OutboxEventoGescomClienteAlfaEvento 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 Mensagem da conversa ordenadas por Sequencia, mais os dados de Conversa (assunto, status, prazo, paciente); status no contrato usa responded para '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[].type tem 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 (chave ConversaId + IdUsuario) com UltimaSequenciaLida = Conversa.UltimaSequencia; insere uma linha em ConversaAcao (Tipo = Read); se Conversa.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, Conteudo do request, Tipo = 'Response'); atualiza Conversa.UltimaSequencia; insere ou atualiza ConversaLeitura do autor com UltimaSequenciaLida = a nova Sequencia (a própria resposta conta como leitura, Especificação 2.5; sem isso, a conversa ficaria não lida para quem respondeu); atualiza Conversa.Status para 'Responded'; insere uma linha em ConversaAcao (Tipo = 'Response'; MensagemId da nova mensagem); grava OutboxEvento (TipoEvento=ConversaRespondida). O valor 'Reply', antes um segundo valor válido para Mensagem.Tipo/ConversaAcao.Tipo no mesmo CHECK, 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). O CHECK de Mensagem.Tipo deve 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.Status para 'Resolved'; insere uma linha em ConversaAcao (Tipo = 'Resolve'); grava OutboxEvento (TipoEvento=ConversaResolvida). Não altera nem exclui Mensagem.
  • PATCH /discard: atualiza Conversa.Status para 'Dismissed'; insere uma linha em ConversaAcao (Tipo = 'Dismiss'); grava OutboxEvento (TipoEvento=ConversaDescartada). Mesma observação — nada é excluído fisicamente. O estado fica em Conversa, não em ConversaDestinatario: 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 por Conversa.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

TabelaBancoFunção no endpoint
PacienteGescomClienteAlfaTabela única consultada — todos os campos de busca e resposta vêm dela

Mapa de campos

CampoTipoBancoObservação
idintPaciente.IdPaciente
namestringPaciente.Nomesegue o mesmo padrão de preferredName/legalName dos demais endpoints quando Paciente.NomeSocial existir
medicalRecordNumberstringPaciente.NumProntuario
gendercharPaciente.Sexodomínio ‘M’/‘F’
birthDatedataPaciente.Nascimentocampo de busca quando a entrada começa com dígito (RN-CM-004)
motherNamestringPaciente.NomeMaecampo de busca quando a entrada começa com letra (RN-CM-004)
cpfstringPaciente.CPFcampo 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

TabelaCampoTipoFinalidadeDefinição completa
ClienteEmpresa (IpSeguranca)FusoHorarioOficialvarchar(64), NOT NULL depois de preencher as clínicas existentesFuso 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 fusoAgenda 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).

SeedTabela(s)Por cliente ou global?StatusDetalhe 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 clientesParâ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 2Seçã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 assimSeção 4.6, “Parâmetro de configuração — PrescricaoTempoAssinatura”
Cores dos status de consulta (6) e de procedimento (8) nos dois temasDomEstadoAgendaConsulta e DomEstadoAgendaProcedimento (IpTerminologia)GlobalTabelas criadas; conferir os valores contra o Design System, seção 44.1 e 4.3, campo status.colors
Nome dos status de consulta e de procedimento em pt-BR, en-US e es-419TermoTraducao (IpTerminologia), Origem = nome da tabela de estadoGlobalExistentes nos 3 idiomas — conferir4.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:
    1. Homologação do serviço de atualização automática.
    2. Teste de carga para múltiplos médicos acessando simultaneamente.
    3. Validação da assinatura digital em ambiente de sandbox.
    4. Definir ícones definitivos para os KPI cards — feito no Protótipo v3.14 (biblioteca Lucide, via lucide.js).
    5. Substituir ícones placeholder de comunicação por SVGs da biblioteca Lucide — feito no Protótipo v3.14 (bell para alertas de sistema, user para conversas com pessoa).
    6. 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.
    7. Testar usabilidade do título como link com seta no hover com médicos.
    8. Validar touchpoints de workflow com médicos em ambiente real (shadowing).
    9. Mapear touchpoints de workflows ainda não documentados (ex: workflow de alta, workflow de intercorrência).
    10. 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 em Para 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 urgency a urgencyLevel (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.GrauUrgencia e Indicadores/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), authorIsMe e readByOthers (calculado, sem coluna nova, [PROPOSTA] como na Mensageria); status com responded; nova ordenação (não lidas; depois o maior entre a última mensagem e o prazo, decrescente; empate por Conversa.CriadoEmUtc), D-CM-087. 4.9: o detalhe da conversa traz o assunto; POST /reply grava a leitura do autor (a resposta conta como leitura), que o cálculo de unread e de readByOthers usa. Desempate final da ordem por Conversa.Id. Revisão por crítico técnico (subagente) aplicada antes de fechar. Até a v5.17, o valor de 'Responded' era replied.

  • 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 EstadoAgendaConsulta será descontinuado depois da implementação nova (D-CM-081). (2) nomes de status como cadastrados em TermoTraducao — “Em atendimento”, “Em preparo” e “Em aplicação” (antes “Em Atendimento”, “Preparo” e “Em administração”; D-CM-082), nas tabelas de ProcedureStatus(). (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 status vira objeto — status.domain (calculado), status.name (TermoTraducao, Termo = CodEstado, Origem = nome da tabela) e status.colors (tabelas IpTerminologia.DomEstadoAgendaConsulta e DomEstadoAgendaProcedimento; 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 a administered (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.IdChClinica não é usado pela Central (D-CM-070). (2) Nome do campo de SegEmpresa fixado no do DDL, SegurancaClienteEmpresaId (D-CM-071); sai o aviso de dois nomes. (3) Clinica.FusoHorario registrada 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.IdChClinica e RecursoHorario são da marcação de agendas) e “Perda de acesso” (D-CM-068). (2) Conversa.IdEmpresa = SegEmpresa.IdEmpresa confirmado (D-CM-069); a troca por IdChClinica ficou adiada (P-CM-052). (3) Fonte do fuso confirmada: ClienteEmpresa.FusoHorarioOficial; nenhuma consulta lê Clinica.FusoHorario (D-CM-069). (4) Nome do campo de SegEmpresa: 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 de ClinicVisible() da Agenda) e da cadeia de D-CM-065 — [PROPOSTA] E-CM-034, a confirmar. (2) 4.1, 4.3 e 4.4: filtro Agenda.IdChClinica IN essa tabela no lugar de “sem filtro de clínica”; clinic nulo 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 o INNER JOIN vira também o filtro (vale para “Meus” e “Todos”). (4) 4.8: filtro Conversa.IdEmpresa IN e 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 por Clinica do banco do cliente (sem FusoWindows; o fuso é o da clínica logada), o que também encerra o risco de o INNER JOIN perder prescrição; {FusoWindowsLogin} no lugar de lc.FusoWindows na exceção (a). (3) 4.5 e 4.6: {IdClinica} e toSignWindowDays são da clínica logada, sem “interino” (D-CM-063). (4) 4.8: novo campo clinic na lista de conversas, com Clinica e Chave nas tabelas (D-CM-064, E-CM-033). (5) 4.1: contagem das clínicas do cliente por Clinica ligada a SegEmpresa. (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: clinic nulo 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); o toSignWindowDays e o “Em Tratamento” (4.5) usam a clínica de entrada, interino em P-CM-048. (4) 4.8: sem filtro por Conversa.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 (de Agenda.IdChClinica, null com 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, por id (D-CM-047, E-CM-027). (3) 4.9: o CHECK de Mensagem.Tipo passa 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.Termo passa a varchar(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); administered vira completed; firstTime (Agenda.PrimeiraConsulta = 'S') em procedures (D-CM-029); startTime em “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: sourceType User | System e messages[].type = Response (D-CM-042). (4) Revisão por Dois Críticos: type de 4.7 com as exceções (a) e (b); {InicioJanelaRevisaoLocal} marcado como valor por linha; texto do KPI urgent alinhado ao SQL; tabela Paciente listada 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: elapsedMinutes e overtime (D-CM-017); tags retorna 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 sem IdAgenda ficam 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 COALESCE de NumeroDiasRevisaoPrescricoes (com TRY_CONVERT), seeds e textos; o sistema atual assume 2; toSignWindowDays com SQL executável; SQL de referência de PrescriptionToSignNext7DaysCount() incluído; Paciente.RemovidoEm no SQL de “a revisar”; texto de escopo alinhado à v4.46 (prescritor ou médico assistente nas três métricas). (2) 4.7: hoursRemaining negativo, inteiro truncado em direção a zero, classificação sobre minutos (E-CM-015); type com 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): DataFim igual 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: delayed passa a exigir DhAtendimentoIniUTC nulo — consulta em atendimento é pendente, não atrasada (D-CM-008). (2) 4.1: patient.diagnosis só retorna diagnóstico cujo PEP.DataInicioUTC é até o fim de hoje no fuso da clínica (D-CM-010); PEP.DataInicio/DataFim não são lidos, só os campos UTC (D-CM-009). (3) 4.6 e Seeds: PrescricaoTempoRevisao (proposto, nunca aplicado) substituído por NumeroDiasRevisaoPrescricoes, 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 na Conversa, 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.Descricao do seed de PrescricaoTempoAssinatura reduzida para caber em varchar(100); descrição de Prescricao na 4.6 alinhada ao filtro P/G/A/O; TRY_CONVERT(int, ...) na leitura de NumeroDiasRevisaoPrescricoes; 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): tags passa de lista de nomes para lista de objetos code/description/color, como na Agenda (o Mapeamento já dizia que cor e descrição vêm de ProgramaApoio); entra a origem do prontuário, PEPProgramaApoioPaciente → PEP, com a vigência de PEP.DataInicioUTC/DataFimUTC (campos datetimeoffset NULL confirmados no catalog.json da 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 de ProgramaApoioPaciente e Paciente.PacienteVip deixa de ser lido, seguindo a decisão do solicitante registrada na Agenda do Médico (Mapeamento v1.6: “desconsidere o campo Paciente.PacienteVip, por enquanto”) — o achado sobre a origem de VIP, que estava [A DEFINIR], fica encerrado também aqui; tabelas PEP, PEPProgramaApoioPaciente, ProgramaApoio e ProgramaApoioPaciente entram 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 NULL nas tabelas que têm o campo, conferidas na Biblioteca de Schema — Agenda, Paciente, PEP, PEPDiagnostico, ProgramaApoio, ProgramaApoioPaciente; Prescricao, PacienteFoto e PEPProgramaApoioPaciente não têm) e filtro explícito em 4.1 a 4.5, 4.6 (consulta de revisão) e 4.7; patient.diagnosis ignora PEP e PEPDiagnostico excluídos; também em PatientInTreatmentCount(), TreatmentPlanAdherenceCount(), PrescriptionToSignNext7DaysCount(), 4.8 (paciente da conversa) e 4.10 (busca de pacientes). O Status A/I do legado não é usado como critério de ativo. (4) Fuso: ClienteEmpresa.FusoOficial (deslocamento) dá lugar a ClienteEmpresa.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 de Situacao = 'V' com fim preenchido e início vazio (vale finished). (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: firstTime passa a boolean (Agenda.PrimeiraConsulta = 'S'), como na Especificação e na Agenda; prefferedName corrigido para preferredName; ids de procedures e prescriptions (4.3, 4.7) passam a int (Prescricao.IdPrescricao/IdPaciente são int no DDL; o exemplo de 4.3 trazia uuid); DhAtendimentoFim (coluna inexistente) corrigido para DhAtendimentoFimUTC em ProcedureStatus(); Conversa.PacienteId corrigido para Conversa.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 endpoints GET /appointments (4.1) e GET /kpis/appointments-today (4.2), com Paciente incluí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 por TipoAgenda sozinho 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 com Situacao = '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á a Situacao gravada no bloqueio; (2) campo type de 4.1 renomeado para attendanceMode (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/DataAssinaturaPrescricao sã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 de PrescriptionToReviewCount(), PrescriptionUrgentCount(), PrescriptionToSignNext7DaysCount(), comentários da SQL, Nota de compatibilidade legada, mapa de campos e filtro to_sign do endpoint). A SQL não muda (o OR das 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)” no authorName passa a checar EquipeMembro.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_sign corrigido: até esta versão, PrescriptionToSignNext7DaysCount() e o filtro to_sign do endpoint (4.7) restringiam a assinatura ao próprio prescritor (IdChProfissionalMed = médico logado, citando RN-CM-012) e nunca eram afetados por reviewScope — o solicitante esclareceu que isso está errado: qualquer médico pode assinar uma prescrição. to_sign passa a usar o mesmo critério “mine”/“all” de to_review (reviewScope): mine = IdChProfissionalMed = médico logado OU Paciente.IdChProfissional = médico logado; all = sem restrição. Campo isPreferredReviewer (4.7), antes presente só em type = to_review, passa a ser calculado também para type = 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ía Situacao = '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. Lista Situacao IN ('P','G','A','C') corrigida para IN ('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() e PrescriptionToSignNext7DaysCount() (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 registro TipoAssinatura = 'R'. Isso resolve, por tabela, a ambiguidade [A DEFINIR] aberta desde a v4.28 sobre Prescricao.IdChProfissionalAssinou sem data própria (sem vencimento a calcular, essa fonte passa a valer como as demais). Parâmetro PrescricaoValidadeAssinatura (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âmetro PrescricaoTempoAssinatura [PROPOSTA] — mesmo padrão IpParametro/IpParametroChave de PrescricaoTempoRevisao, 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”). Nome PrescricaoTempoAssinatura é uma decisão do Claude nesta versão (convenção “Tempo” + conceito, espelhando PrescricaoTempoRevisao), não um nome pedido pelo solicitante — sujeito a ajuste. Novo filtro de Prescricao.Situacao (RN-CM-020), também pedido pelo solicitante nesta rodada: PrescriptionToReviewCount(), PrescriptionToSignNext7DaysCount() e o endpoint /prescriptions passam a exigir Situacao IN ('P','G','A','O') — motivado por um achado ao conferir a nova regra contra CargaCMZero.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 registro TipoAssinatura = '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 de PrescriptionToSignNext7DaysCount() (Seção 4.6) ao do filtro to_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 para PrescriptionToReviewCount(); (2) mantida a formulação anterior do filtro to_sign (nunca afetado por reviewScope). 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 de to_sign ao 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 de Situacao = 'C' na Condição 2 de TreatmentPlanAdherenceCount() (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 classificou Paciente.PacienteVip como um conceito legado, de uso futuro incerto — não uma confirmação de que a associação vip↔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 entre Paciente.PacienteVip e ProgramaApoioPaciente/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 assumindo Paciente.PacienteVip como fonte).

  • v4.43 (28/09/2026) — Correção pedida pelo solicitante: a cor da tag VIP é verde, #80FF38, conforme cadastrada em ProgramaApoio — confirmado contra CargaCMZero.xlsx (IdProgramaApoio=1, Nome=‘VIP’). Isso contradiz a nota da Seção 4.1 (campo tags) que, desde sempre neste documento, dizia que vip “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 de vip também vêm de ProgramaApoio (mesma fonte das outras 7 tags), mantendo intacta a exceção de vip aos filtros de MostrarEm e 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á tem vip associado a pacientes via ProgramaApoioPaciente (mesmo mecanismo das outras tags, não via Paciente.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-vip corrigido 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 quando TempoPacienteAtivoAgenda/TempoPacienteAtivoPrescricao não existirem para a clínica — implementado via COALESCE(..., 180) nas duas subconsultas, substituindo o [A DEFINIR]; (2) divergência de valor resolvida — o correto é 180 dias; o seed de Infra-estrutura/(BD-M) Dados incluídos obrigatórios.md (que gravava 120) foi corrigido, com a cópia anterior arquivada em Infra-estrutura/Histórico/; (3) janela de PrescricaoTempoRevisao confirmada 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 usava dateadd(day,-180, ...) fixo — passa a ler TempoPacienteAtivoAgenda e TempoPacienteAtivoPrescricao de IpParametroChave (mesmo padrão de 4.6); unidade dos dois parâmetros definida como dias; corrigido o erro de digitação IpParametroTempoPacienteAtivoPrescricao → 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 de Infra-estrutura/(BD-M) Dados incluídos obrigatórios.md (120 dias) e o padrão de RN-CM-024 (180 dias). (2) PrescricaoTempoRevisao em dias (Seção 4.6, 4.7 e Seeds): unidade muda de horas para dias; DATEADD(HOUR, ..., 24) → DATEADD(DAY, ..., 1); seed Valor 24 → 1; Descricao do IpParametro ajustada; 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/IpParametroChave adicionadas à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 entre PrescricaoAssinatura.TipoAssinatura = 'A' e o campo legado Prescricao.DataAssinaturaPrescricao (RN-CM-029, via OUTER APPLY/UNION ALL, não mais um COALESCE simples); a existência de TipoAssinatura = 'R' dentro da mesma janela de validade agora é checada separadamente (Precedência 2, “já foi revisada”) em vez de estar misturada na mesma cláusula NOT EXISTS que também comparava TipoAssinatura = '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 de PrescriptionToReviewCount() com o sinal invertido. (3) PrescriptionUrgentCount() atualizada para reaproveitar PrescriptionToSignNext7DaysCount() em vez de duplicar sua própria checagem de “não assinada” desatualizada. (4) Domínio de PrescricaoAssinatura.TipoAssinatura (4.7) ganhou nota explicando que Prescricao.DataAssinaturaPrescricao/IdChProfissionalAssinou não geram linha real na tabela — são lidos diretamente de Prescricao. (5) Campo type e filtros to_sign/to_review do 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 NULL como 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 em Cenários de Teste, só a 70 muda de classificação (sai de “a assinar” — via RN-CM-029, sua assinatura mais recente, DataAssinaturaPrescricao de 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 registro TipoAssinatura = '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 usava COALESCE simples entre a subquery de PrescricaoAssinatura e DataAssinaturaPrescricao, o que escolhe o primeiro valor não nulo em vez do mais recente; corrigido para UNION 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: DhAtendimentoIniUTC marca 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ó em ProcedureStatus()) marcam início/fim do primeiro medicamento do protocolo, que ocorre depois desse preparo. Confirma que startTime (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 de finished em ProcedureStatus()), o campo passa a trazer Agenda.DhAtendimentoFimUTC em vez de DhAtendimentoIniUTC. Observação adicionada sinalizando que o campo continua se chamando startTime por 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 MostrarEm dos 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 exemplo MostrarEm = 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 a ProgramaApoioPaciente.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 (campo tags) e Filtros do endpoint, Seção 4.1; Seção 4.3 referencia 4.1, sem alteração própria. Sem mudança em MostrarEm nem 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 com MostrarEm nem o caso DataInicio+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 (ambos datetime 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 como hoje >= 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 e ProgramaApoioPaciente (DataFim exclusivo 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 de MostrarEm já existente; não se aplica à tag vip. 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.PacienteVip UNION ProgramaApoioPaciente/ProgramaApoio) sem checar em quais telas cada tag foi habilitada. Adicionado o filtro (ProgramaApoio.MostrarEm & 8) = 8 aos dois endpoints (bit 4 do domínio — Central do Médico), à tabela “Mapa de campos” (campo tags) 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ínio ProgramaApoio.MostrarEm deste 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) = 8 não é aplicado à tag vip (correto, vip não vem de ProgramaApoio); 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 como PrescricaoProtocolo.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 de ProtocoloGrupo.SessoesSugerido para Sessao (e Y para Ciclo); Sessao portanto 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 de Ciclo > 1: comparar diasDecorridos (contado desde o C1D1 global, sem limite) direto contra Sessao (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 de PrescricaoProtocolo daquele ciclo com o menor Sessao, isto é, a 1ª sessão do ciclo); a condição 3 passa a ter duas partes — 3a) sessão comum do ciclo: diasDecorridos contado desde a âncora do MESMO ciclo, comparado a Sessao com ToleranciaEntreSessoes; 3b) início de um novo ciclo (a própria âncora, exceto a do Ciclo 1): diasDecorridos entre a âncora do ciclo atual e a do ciclo anterior, comparado a Protocolo.IntervaloCiclosEmDias com ToleranciaEntreCiclos. Isso também dá finalmente um uso concreto e coerente para ToleranciaEntreCiclos, 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 de ProtocoloGrupo.SessoesSugerido corrigida (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, PEPProjetoTerapeuticoProtocolo e PEPProjetoTerapeuticoProtocoloProgramacao voltam à tabela “Tabelas envolvidas”, agora só para esta condição. (2) A condição 3 estava mais complicada do que deveria: Sessao, em PrescricaoProtocolo, 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 + Sessao que a v4.31 usava (removida); a escolha entre ToleranciaEntreSessoes/ToleranciaEntreCiclos pelo 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 com PEPProjetoTerapeuticoProtocoloProgramacao.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 (PrescricaoProtocolo com Ciclo=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 de Sessao (que já armazena dias corridos desde o C1D1, não um índice ordinal — esclarecido pelo solicitante), somado a (Ciclo−1) × IntervaloCiclosEmDias quando a sessão está em outro ciclo. Duas tolerâncias distintas substituem a proposta anterior de uma única ToleranciaDiasAdesao: Protocolo.ToleranciaEntreSessoes (desvio dentro do mesmo ciclo) e Protocolo.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 em Agenda) marcada como interpretação não confirmada nesta rodada, sinalizada no corpo do documento. Tabela “Tabelas envolvidas” da Seção 4.5 atualizada: PEPProjetoTerapeutico, PEPProjetoTerapeuticoProtocolo e PEPProjetoTerapeuticoProtocoloProgramacao removidas (não são mais usadas por este endpoint); PrescricaoProtocolo e ProtocoloGrupo adicionadas. 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 a Protocolo.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 com PEPProjetoTerapeuticoProtocoloProgramacao.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 de ProtocoloGrupo.SessoesSugerido. Tabela “Tabelas envolvidas” da Seção 4.5 atualizada — Protocolo, PEPProjetoTerapeutico, PEPProjetoTerapeuticoProtocolo e PEPProjetoTerapeuticoProtocoloProgramacao já eram usadas na função mas não apareciam listadas ali. (2) Criado o parâmetro IpParametro.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 um DATEADD(DAY, -7, ...) fixo no SQL de PrescriptionToReviewCount() — mesmo padrão de PrescricaoTempoRevisao; 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 coluna ToleranciaDiasAdesao, 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.md em 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 em Histó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âmetro IpParametro.PrescricaoTempoRevisao → IpParametroChave.Valor na query de PrescriptionToReviewCount(), substituindo o DATEADD(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/IpParametroChave já existem. Filtro type = to_review do 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 quando IpParametro/IpParametroChave de PrescricaoTempoRevisao não existir para a clínica — default de 24h, confirmado pelo solicitante — implementado na query de PrescriptionToReviewCount() (Seção 4.6) via COALESCE(..., 24) em vez do SELECT direto; 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 tem CHECK explí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.TipoAssinatura para 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 de PrescriptionToReviewCount(), 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 de PrescricaoAssinaturaEnfermagem.TipoAssinatura = 'E' (tabela distinta, confirmada na Biblioteca de Schema/DDL) — apenas o 'M'→'A' de PrescricaoAssinatura estava incorreto. Nenhuma outra seção deste conjunto de documentos (01, 02, 03) referenciava esse campo — correção isolada à Seção 4.