Agenda do Médico — Mapeamento de Banco de Dados (v1.1)

Documentos desta funcionalidade: 01 - Definição (v1.12) · 02 - Especificação (v1.14) · 03 - Protótipo (v1.12, código executável em 03 - Protótipo v1.12.html) · 04 - Mapeamento de Banco de Dados (v1.1)


SEÇÃO 4 — MAPEAMENTO DE BANCO DE DADOS

Fonte da estrutura: Biblioteca de Schema (DDL), Para IA/Biblioteca de Schema (DDL)/catalog.json. Base de referência: GescomClienteAlfa (banco já adaptado à arquitetura do Gemed 2.1) e IpSeguranca/IpTerminologia. Nenhuma tabela nova. Campos novos: o fuso IANA da clínica (Clinica.FusoHorarioOficial) e o padrão de auditoria em UnidadeAtendimento — ver “Campos novos”.

Regras do sistema aplicadas aqui:

  • Exclusão lógica: um registro excluído tem RemovidoEm preenchido (com UsuarioIdRemovido); toda consulta ignora registros com RemovidoEm preenchido. O campo Status com A/I (ativo/inativo) 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.
  • Clínicas do cliente: as clínicas que estão no mesmo banco de cliente (ClienteBD).

Itens ainda não confirmados estão marcados [A DEFINIR] (falta um fato) ou [PROPOSTA] (decisão do Designer a confirmar); a lista consolidada está em “Pendências”, ao final.

4.1 Endpoint: GET /api/v1/agenda/doctor/day

Retorna as consultas do médico logado num dia (date), de qualquer status, de todas as clínicas do cliente (RN-AGM-002).

Tabelas envolvidas

TabelaBancoFunção no endpoint
AgendaGescomClienteAlfaTabela principal — uma linha por consulta
PacienteGescomClienteAlfaNome, nome social e o indicador de paciente reservado (filtro)
PacienteFotoGescomClienteAlfaFoto do paciente
PEP / PEPDiagnosticoGescomClienteAlfaDiagnósticos oncológicos do paciente
ProgramaApoio / ProgramaApoioPacienteGescomClienteAlfaTags do paciente (RN-AGM-006)
ChaveGescomClienteAlfaNome curto da clínica e do convênio (RN-AGM-017)
ClinicaGescomClienteAlfaFuso horário (IANA) da clínica em que o usuário entrou (RN-AGM-018)
UnidadeAtendimentoGescomClienteAlfaNome da unidade e contagem de unidades ativas para consultas (RN-AGM-017, b)
AgendaClassificacao / AgendaSubClassificacaoGescomClienteAlfaClassificação e subclassificação (RN-AGM-008)
TermoTraducaoIpTerminologiaRótulo traduzido do modo de atendimento
ClienteEmpresaIpSegurancaIdioma da clínica em que o usuário entrou; contagem de clínicas acessíveis
ClientePerfilAcessoUsuario / UsuarioClienteIpSegurancaClínicas do cliente a que o médico tem acesso (RN-AGM-017, a)

Mapa de campos

Os campos herdados da Central do Médico têm a mesma origem do endpoint GET /api/v1/cockpit/doctor/appointments (Central do Médico, Mapeamento de Banco de Dados, Seção 4.1) — referenciados, não repetidos.

CampoTipoOrigemObservação
datedataparâmetro dateEco do dia pedido
timeZonestring (IANA)Clinica.FusoHorarioOficial da clínica em que o usuário entrouCampo novo (ver “Campos novos”); ex.: America/Sao_Paulo. Como chegar da clínica do login à linha de Clinica: ver “Pendências”, item 2
serverNowdata/horarelógio do servidor, convertido para timeZoneISO 8601 com deslocamento
appointments[].idintAgenda.IdAgenda
startTimehorárioAgenda.DhAgendaIniUTC (NULL possível na DDL), convertido para timeZoneConsulta com DhAgendaIniUTC NULL não entra na lista (não tem dia nem posição)
endTimehorárioAgenda.DhAgendaFimUTC (NULL possível na DDL), convertido para timeZone[PROPOSTA] Se NULL, DhAgendaIniUTC + Agenda.Tempo minutos (Tempo, numeric(4,0) NOT NULL, é a duração gravada pela Recepção); se o fim cai no dia seguinte, "24:00" (o item termina no fim do dia exibido)
statusstringcalculado — AppointmentStatus()Central do Médico, 4.1 (“Funções de cálculo”): scheduled, waiting, checked, consultation, finished, canceled. Ver “Funções de cálculo”, abaixo, sobre precedência
attendanceMode.codecharAgenda.AtendimentoDomínio ModoAtendimento (Central do Médico, 4.1, “Domínios”)
attendanceMode.labelstringAgenda.Atendimento → TermoTraducao.TermoValorMesma tradução da Central: Termo = Agenda.Atendimento, Origem = Indicadores|ModoAtendimento, Idioma = ClienteEmpresa.IdiomaOficial. [PROPOSTA] Sem tradução no idioma da clínica, usar a de pt-BR
delayMinutesintcalculadoMinutos entre agora e DhAgendaIniUTC, calculados em UTC. Positivo só quando date é hoje (em timeZone), o horário já passou, Agenda.Situacao IN ('A','V') e DhAtendimentoIniUTC IS NULL; em qualquer outro caso, 0 — inclusive canceladas
firstTimebooleanAgenda.PrimeiraConsulta = 'S'Domínio S/N
tags[].codestringProgramaApoio.SiglaTexto do chip
tags[].descriptionstringProgramaApoio.DescricaoDica e rótulo acessível
tags[].colorstringProgramaApoio.CorHexadecimal, fundo do chip (padrão .chip-tag)
tags (seleção)—ProgramaApoioPaciente (por IdPaciente) → ProgramaApoioFiltros de RN-CM-025 (Central do Médico, 4.1): (MostrarEm & 32) = 32, vigência da tag (ProgramaApoio.DataInicio/DataFim) e da atribuição (ProgramaApoioPaciente.DataInicio/DataFim), avaliadas no dia date (RN-AGM-006), e RemovidoEm IS NULL nas duas tabelas. Tag VIP: origem [A DEFINIR] — ver “Pendências”, item 1
complementstring | nullAgenda.Complemento (varchar(128), NULL)
patient.idintAgenda.IdPaciente
patient.preferredName / legalNamestringPaciente.NomeSocial / Paciente.NomeCentral do Médico, 4.1 (lá grafado prefferedName)
patient.photourl | nullPacienteFoto (Padrao = 'S', a mais recente)Central do Médico, 4.1 e “Infraestrutura de apoio” (MinIO)
patient.diagnosisarrayPEPDiagnostico.Diagnostico, Tipo = 'O'Central do Médico, 4.1 — todos os diagnósticos oncológicos ativos (critério de “ativo” herdado da Central)
clinicstring | nullAgenda.IdChClinica → Chave.IdChave → Chave.DescricaoNome curto da clínica (Clinica.IdChClinica é FK para Portador, que é FK para Chave). null quando ClinicVisible() é falso (RN-AGM-017, a). [PROPOSTA] O nome aparece mesmo que a clínica tenha sido excluída logicamente depois — a consulta aconteceu ou acontecerá ali
unitstring | nullAgenda.IdUAtendimento (NULL possível) → UnidadeAtendimento.Descricao (varchar(30))null quando Agenda.IdUAtendimento é NULL ou quando UnitVisible(Agenda.IdChClinica) é falso (RN-AGM-017, b). [PROPOSTA] Quando aparece, o nome é exibido mesmo que aquela unidade tenha sido excluída depois
insurancestringAgenda.IdChConvenio (NOT NULL) → Chave.IdChave → Chave.DescricaoNome curto do convênio (Convenio.IdChConvenio é FK para Portador → Chave). Sempre preenchido; o particular é um registro de Convenio com Convenio.Convenio = 'T' e aparece pelo nome curto cadastrado. O plano (Agenda.Plano, Agenda.IdPlano → ConvenioPlano) não é usado (RN-AGM-017, c)
classificationobjeto | null—null quando Agenda.IdAgendaClassificacao é NULL (RN-AGM-008)
classification.namestringAgenda.IdAgendaClassificacao → AgendaClassificacao.Descricao (varchar(20))Exibida mesmo que a classificação tenha sido excluída depois (mesmo raciocínio de clinic)
classification.subNamestring | nullAgenda.IdAgendaSubClassificacao (FK) → AgendaSubClassificacao.Descricao (varchar(30))null quando não há subclassificação

Campos de Agenda que existem e não são usados: TipoConsulta (char(1) NOT NULL, significado não confirmado), Plano, IdPlano, IdChClinicaFat (clínica de faturamento — a tela mostra a clínica do atendimento, IdChClinica), Data/HoraIni/HoraFim (data e horário legados; a tela usa DhAgendaIniUTC/DhAgendaFimUTC, como a Central). Clinica.FusoHorario (deslocamento, legado) também não é usado — substituído por Clinica.FusoHorarioOficial.

Funções de cálculo

AppointmentStatus() — a da Central do Médico (4.1). Precedência adotada aqui [PROPOSTA], porque as condições da Central se sobrepõem num caso: Situacao = 'V' com DhAtendimentoFimUTC preenchido e DhAtendimentoIniUTC NULL casa com checked e com finished — vale finished. As condições são avaliadas nesta ordem: canceled, finished, consultation, checked, waiting, scheduled. Agenda.Situacao é NOT NULL; um código fora do domínio SituacaoAgenda não entra na lista (filtro abaixo).

ClinicVisible() — o médico tem acesso a mais de uma clínica do cliente (RN-AGM-017, a). Calculada uma vez por sessão (pode ficar em cache — consulta outro banco e não precisa ser refeita a cada atualização automática):

-- Verdadeiro quando há mais de uma clínica (ClienteEmpresa) acessível ao usuário
-- no mesmo banco do cliente (ClienteBD) da sessão — "clínicas do cliente".
SELECT CASE WHEN COUNT(DISTINCT cpau.ClienteEmpresaId) > 1 THEN 1 ELSE 0 END
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;

Mesmo critério de “clínica acessível” do Check-in de Usuários (RN-CIU-009, Épico 1), restrito ao banco atual. Não há caso de consulta do médico numa clínica a que ele não tem acesso: o profissional só tem horário (e, portanto, agenda) nas clínicas a que está vinculado.

UnitVisible(IdChClinica) — a clínica da consulta tem mais de uma unidade ativa para consultas (RN-AGM-017, b). Calculada uma vez por clínica presente no resultado, não por consulta:

SELECT CASE WHEN COUNT(*) > 1 THEN 1 ELSE 0 END
FROM UnidadeAtendimento
WHERE IdClinica  = @IdChClinica
  AND StConsulta = 'S'
  AND RemovidoEm IS NULL;     -- campo novo nesta tabela (ver "Campos novos")

Referência de tempo (RN-AGM-018)

Tudo no fuso da clínica em que o usuário entrou: serverNow, o que é “hoje”, o dia de cada consulta (filtro de date) e os horários startTime/endTime — inclusive das consultas de outras clínicas do cliente. O fuso vem de Clinica.FusoHorarioOficial (identificador IANA, ex.: America/Sao_Paulo) e é devolvido em timeZone, para a tela informar qual fuso está exibindo. A conversão de DhAgendaIniUTC/DhAgendaFimUTC é feita na aplicação (o AT TIME ZONE do SQL Server não aceita nomes IANA). Como há um só fuso por requisição, os limites do dia viram uma faixa UTC exata: @inicioUtc = 00:00 de date em timeZone, convertido para UTC; @fimUtc = 00:00 do dia seguinte, convertido.

Domínios

SituacaoAgenda (Agenda.Situacao), ModoAtendimento (Agenda.Atendimento), TipoAgenda (Agenda.TipoAgenda), TipoDiagnostico e MostrarEm: definidos uma única vez em Central do Médico, Mapeamento de Banco de Dados, 4.1 (“Domínios”) — não repetidos aqui.

Domínios usados só por esta funcionalidade:

CampoValorSignificadoFonte
UnidadeAtendimento.StConsultaS / NUnidade atende (ou não) consultasSolicitante; massa de teste (CargaCMZero.xlsx)
Convenio.ConvenioTConvênio “Particular”Solicitante; massa de teste
Convenio.ConvenioBConvênio reservado (na massa de teste, usado junto com o paciente reservado)Massa de teste
Convenio.ConvenioNULLConvênio comumMassa de teste — [A DEFINIR] se há outros valores em produção
Paciente.PacienteBPaciente reservado, que não representa consulta (char(1) NOT NULL)Central do Médico, RN-CM-030; demais valores não mapeados aqui
Clinica.FusoHorarioOficialidentificador IANAFuso da clínica (ex.: America/Sao_Paulo)Solicitante — campo novo

Filtros do endpoint

Mesmo critério de seleção do endpoint de consultas da Central do Médico (4.1), sem o filtro de “hoje” e sem o filtro de situação:

  • Agenda.IdChRecurso = {IdChProfissional do médico logado} — mesmo critério da Central; sem filtro por clínica (RN-AGM-002).
  • Agenda.TipoAgenda = 'C' — agendas de consulta.
  • Paciente.Paciente <> 'B' (via Agenda.IdPaciente; Paciente.Paciente é NOT NULL, então o filtro não descarta pacientes comuns) — exclui registros de agenda com o paciente reservado, que não representam consulta (mesmo filtro da Central, RN-CM-030).
  • Agenda.RemovidoEm IS NULL — exclusão lógica, regra de todo o sistema (a Central também deve aplicá-la — ver “Pendências”, item 5).
  • Agenda.Situacao IN ('A','V','C','D','F','I','M','O','T') — todo o domínio SituacaoAgenda; canceladas (inclusive falta) entram, com status = canceled (RN-AGM-009/010).
  • Agenda.DhAgendaIniUTC >= @inicioUtc AND Agenda.DhAgendaIniUTC < @fimUtc (ver “Referência de tempo”).
  • Tags: filtros de MostrarEm, vigências (no dia date) e exclusão lógica (ver tags no mapa de campos).
  • Ordenação: Agenda.DhAgendaIniUTC crescente.

4.2 Endpoint: GET /api/v1/agenda/doctor/days-with-appointments

Retorna as datas, entre from e to (máximo de 62 dias), com ao menos uma consulta não cancelada do médico (marcador do calendário — RN-AGM-003).

-- @fromUtc = 00:00 de @from em timeZone, em UTC; @toUtc = 00:00 do dia seguinte a @to, em UTC.
-- A data local de cada consulta (no fuso timeZone) é calculada na aplicação a partir de DhAgendaIniUTC.
SELECT a.DhAgendaIniUTC
FROM Agenda a
JOIN Paciente p ON p.IdPaciente = a.IdPaciente
WHERE a.IdChRecurso = @IdChProfissional
  AND a.TipoAgenda  = 'C'
  AND p.Paciente   <> 'B'
  AND a.RemovidoEm IS NULL
  AND a.Situacao IN ('A', 'V')          -- não cancelada (domínio SituacaoAgenda)
  AND a.DhAgendaIniUTC >= @fromUtc AND a.DhAgendaIniUTC < @toUtc;
-- Resposta: datas distintas (no fuso timeZone), em ordem crescente.

4.3 Endpoint: GET /api/v1/agenda/doctor/next-appointment-date

Retorna a data da próxima (direction = next) ou anterior (previous) consulta não cancelada do médico, a partir de from (exclusive), sem limite de horizonte (RN-AGM-003). É chamada a cada carregamento de dia e a cada atualização automática, nas duas direções — precisa ser barata.

-- next: @limiteUtc = 00:00 do dia seguinte a @from (timeZone), em UTC.
SELECT TOP 1 a.DhAgendaIniUTC
FROM Agenda a
JOIN Paciente p ON p.IdPaciente = a.IdPaciente
WHERE a.IdChRecurso = @IdChProfissional
  AND a.TipoAgenda  = 'C'
  AND p.Paciente   <> 'B'
  AND a.RemovidoEm IS NULL
  AND a.Situacao IN ('A', 'V')
  AND a.DhAgendaIniUTC >= @limiteUtc
ORDER BY a.DhAgendaIniUTC ASC;
-- previous: @limiteUtc = 00:00 de @from, em UTC; condição DhAgendaIniUTC < @limiteUtc e ORDER BY DESC.
-- Resposta: a data local (timeZone) do resultado, ou null.

4.4 Endpoint: GET /api/v1/patients/search

Mapeamento da Central do Médico, Seção 4.10 — reutilizado sem mudança (RN-AGM-014).

Campos novos

Tabela (banco)CampoTipoObrigatoriedadeMotivoStatus
Clinica (GescomClienteAlfa)FusoHorarioOficialvarchar(64) [PROPOSTA] (os identificadores IANA têm até ~32 caracteres)[PROPOSTA] NOT NULL, depois de preencher as clínicas existentesFuso da clínica em convenção IANA (RN-AGM-018); substitui Clinica.FusoHorario (deslocamento)Decidido pelo solicitante; migração a criar (Log de Mudanças, 07/10/2026)
UnidadeAtendimento (GescomClienteAlfa)16 campos do padrão de auditoria do framework (CriadoEm … IpRemovido, inclusive RemovidoEm e UsuarioIdRemovido)conforme framework_pattern.md (Biblioteca de Schema)conforme o padrãoExclusão lógica no lugar de Status A/I (regra do sistema); usado por UnitVisible()Regra decidida pelo solicitante; migração a criar

Migração de dados [PROPOSTA]: FusoHorarioOficial preenchido a partir do cadastro de cada clínica (o deslocamento atual não identifica o fuso IANA de forma única — ex.: −03:00 serve a vários fusos —, então o valor é informado na implantação); em UnidadeAtendimento, registros com Status = 'I' recebem RemovidoEm = data da migração.

Índices

Os campos novos da arquitetura do Gemed 2.1 precisam de índices próprios — decisão do solicitante, registrada no Log de Mudanças Estruturais do Banco de Dados (07/10/2026). Em Agenda, os índices existentes (Biblioteca de Schema — DDL) que tocam o médico ou o tipo de agenda — IX_Agenda_IdChClinica_IdChRecurso_TipoAgenda_Data, IX_Agenda_IdChClinica_IdChRecurso_IdUAtendimento_Data_Situacao, IX_Agenda_IdChClinica_TipoAgenda_Situacao_Data, IX_Agenda_Situacao_TipoAgenda, IX_Agenda_TipoAgenda, FK_Agenda_IdChRecurso — usam a data legada Agenda.Data, não DhAgendaIniUTC, e os compostos começam por IdChClinica.

Para esta funcionalidade, [PROPOSTA] índice não único IX_Agenda_IdChRecurso_TipoAgenda_DhAgendaIniUTC (IdChRecurso, TipoAgenda, DhAgendaIniUTC) INCLUDE (Situacao, IdPaciente, DhAgendaFimUTC, RemovidoEm) — atende a faixa de GET /day, days-with-appointments e o TOP 1 de next-appointment-date. A confirmar com o time de banco, junto com o impacto em escrita (a Agenda é muito gravada pela Recepção).

Auditoria (NGS1.07.03 / NGS1.07.04)

A leitura da agenda de um dia (GET /day ao carregar um dia; o polling do mesmo dia não gera novo evento) e a abertura do PEP a partir dela geram evento de auditoria (Especificação, Conformidade SBIS). O mecanismo e a tabela da trilha de auditoria são transversais ao sistema e não estão mapeados neste documento — ver “Pendências”, item 4.

Tabelas novas

Nenhuma.

Nota sobre registros de paciente reservado

O filtro Paciente.Paciente <> 'B' vem da Central do Médico (RN-CM-030). Esta funcionalidade não cria nem altera esses registros, e não tem seed para eles. A Central (congelada) ainda remete a “mecanismo e seed a detalhar na Seção 4” da Agenda do Médico — remissão que fica sem objeto e deve ser retirada da Central quando ela for descongelada.

Seeds da Funcionalidade

SeedTabela(s)Por cliente ou global?StatusDetalhe completo
Traduções do domínio ModoAtendimento (Presencial, Teleatendimento, Customizado) nos idiomas pt-BR, en-US e es-419TermoTraducao (IpTerminologia)GlobalJá usado pela Central do Médico — conferir que as três línguas existem4.1, campo attendanceMode.label
Nome curto de cada clínica e de cada convênio, inclusive “Particular”Chave.Descricao (GescomClienteAlfa)Por clienteJá em produção (cadastro de clínica e convênio)4.1, campos clinic e insurance
Fuso IANA de cada clínicaClinica.FusoHorarioOficial (GescomClienteAlfa)Por cliente[PROPOSTA] — campo novo; preencher na implantação de cada clínica”Campos novos”
Sigla, descrição e cor de cada tag exibida em agendasProgramaApoio.Sigla/Descricao/Cor (GescomClienteAlfa)Por clienteCadastro existente — conferir que as tags com MostrarEm & 32 têm os três preenchidos4.1, campo tags

Nenhum parâmetro novo (IpParametro/IpParametroChave): a tela não tem limiar configurável próprio.

Pendências

  1. [A DEFINIR] Origem da tag VIP — Paciente.PacienteVip ou ProgramaApoioPaciente (achado em aberto na Central do Médico, 4.1, campo tags); também define se o VIP passa pelos filtros de MostrarEm e de vigência e como evitar que apareça duas vezes.
  2. [A DEFINIR] Como chegar da clínica em que o usuário entrou (ClienteEmpresa, IpSeguranca) à linha de Clinica (GescomClienteAlfa) que tem FusoHorarioOficial — não há campo que ligue as duas tabelas na DDL. Alternativa: guardar o fuso IANA também em ClienteEmpresa (que já tem FusoOficial, deslocamento).
  3. [PROPOSTA] Precedência de AppointmentStatus() (caso V com fim sem início = finished) — a sobreposição é herdada da Central e deve ser corrigida lá também.
  4. Trilha de auditoria (NGS1.07.03, estágio 1) — mecanismo transversal, não mapeado aqui; precisa existir para a conformidade.
  5. Central do Médico (congelada): aplicar Agenda.RemovidoEm IS NULL (e a exclusão lógica nas demais tabelas que consulta) quando for descongelada.
  6. Divergência de tipo registrada: Agenda.IdAgendaClassificacao é int e não tem FK, enquanto a PK de AgendaClassificacao é smallint. O join funciona; o risco é de integridade. Registrado no Log de Mudanças Estruturais do Banco de Dados (07/10/2026).
  7. [PROPOSTA] Tamanho e obrigatoriedade de Clinica.FusoHorarioOficial, migração dos dados (ver “Campos novos”) e índice novo em Agenda (ver “Índices”).

Histórico de Versões

  • v1.0 (07/10/2026) — Arquivo criado. Primeira versão da Seção 4, a pedido do solicitante (“podemos ir para a próxima seção”), sobre 01-Definição v1.11, 02-Especificação v1.13 e 03-Protótipo v1.11. Estrutura conferida na Biblioteca de Schema (DDL) — Agenda, Paciente, Chave, Portador, Clinica, Convenio, UnidadeAtendimento, AgendaClassificacao, AgendaSubClassificacao (GescomClienteAlfa); ClienteEmpresa, ClientePerfilAcessoUsuario, UsuarioCliente (IpSeguranca), incluindo nulabilidade, existência de RemovidoEm e índices de Agenda — e valores de exemplo na massa de teste CargaCMZero.xlsx (nomes curtos em Chave, Convenio.Convenio = T/B/NULL, UnidadeAtendimento.StConsulta, duas ClienteEmpresa no mesmo ClienteBD com fusos diferentes). Fatos dados pelo solicitante durante a Definição v1.9–v1.10 e usados aqui: nome curto da clínica e do convênio em Chave.Descricao; status também em Chave.Status; plano escrito em Agenda.Plano (não usado); acesso a mais de uma clínica por ClientePerfilAcessoUsuario; unidade ativa para consultas por UnidadeAtendimento.StConsulta = 'S'; particular com Convenio.Convenio = 'T'. Campos e regras herdados da Central do Médico referenciados ao Mapeamento dela (v4.48, Seção 4.1 e 4.10), sem repetição. Achado registrado: Clinica.IdChClinica e Convenio.IdChConvenio chegam a Chave via Portador (FKs da DDL) — é esse o caminho do nome curto.
  • v1.0 — Revisão por Dois Críticos (07/10/2026, mesma versão, antes da entrega ao solicitante) — Crítico técnico (subagente independente, DBA/back-end) sobre esta Seção 4 e o contrato da Especificação; 14 achados, cada um conferido contra a DDL antes de aplicar. Aplicados: (1) a proposta de fuso por clínica muda o contrato de GET /day (linha “AGORA”, rolagem e “Hoje” comparam serverNow com startTime) — registrado em “Referência de tempo” e na pendência 2; (2) delayMinutes positivo para canceladas — passa a exigir Situacao IN ('A','V') e sem início de atendimento, calculado em UTC; (3) SQLs de 4.2/4.3 sem a junção do fuso e sem uso de índice — reescritos com faixa UTC com folga e filtro residual, e TOP 1 em 4.3; (4) vigência das tags quando o dia exibido não é hoje — pendência 4; (5) clínica escondida quando o médico tem acesso a uma só clínica mas foi agendado em outra — pendência 6; uc.RemovidoEm e cache de ClinicVisible(); (6) exclusão lógica — conferido na DDL: Agenda, Paciente, ProgramaApoio e ProgramaApoioPaciente têm RemovidoEm; UnidadeAtendimento, Chave, Clinica, Convenio e as tabelas de classificação não têm — filtro Agenda.RemovidoEm IS NULL acrescentado; (7) tipo dos identificadores: a Especificação dava uuid, o mapeamento int — Especificação corrigida para int (v1.13); (8) Situacao fora do domínio e sobreposição de checked/finished em AppointmentStatus() — filtro pelo domínio e precedência (pendência 7); (9) índice proposto ganhou IdChClinica, DhAgendaFimUTC e RemovidoEm no INCLUDE; UnitVisible() por clínica distinta; (10) endTime com DhAgendaFimUTC NULL (a DDL permite) ou atravessando a meia-noite — regra proposta; (11) afirmações vindas só da massa de teste ou de decisão do Designer marcadas como tal (convênio B, NULL comum, valor R do modo de atendimento, clínica/convênio/classificação inativos); (12) pendências completadas: auditoria, origem do VIP e do code das tags, tradução ausente do modo; (13) remissão da Central ao “mecanismo e seed” na Seção 4 da Agenda tratada em nota própria; classification.name explicitado. Não aplicado (verificado como não procedente): risco de Paciente.Paciente NULL descartar pacientes comuns no filtro <> 'B' — a DDL define Paciente.Paciente como char(1) NOT NULL.
  • v1.1 (07/10/2026) — Respostas do solicitante às pendências da v1.0. (1) Exclusão lógica no lugar de Status: no legado, a maioria das tabelas usa Status A/I; a regra está sendo descontinuada e substituída por RemovidoEm/UsuarioIdRemovido, valendo para todo o sistema — UnitVisible() passa a usar RemovidoEm IS NULL, o que exige o padrão de auditoria em UnidadeAtendimento (que não o tem na DDL — nova subseção “Campos novos”); tags passam a filtrar RemovidoEm em ProgramaApoio e ProgramaApoioPaciente; a Central deve aplicar a regra quando descongelada; pendência do valor ativo de Status encerrada. (2) Fuso: tudo no fuso da clínica do login — a proposta de fuso por clínica da consulta foi recusada; campo novo Clinica.FusoHorarioOficial (IANA, ex.: America/Sao_Paulo), que o solicitante informou estar sendo criado para substituir Clinica.FusoHorario (deslocamento); GET /day devolve timeZone (RN-AGM-018) e a tela informa o fuso; SQLs de 4.2/4.3 simplificados para faixa UTC exata, com a conversão na aplicação. Nova pendência: ligação entre ClienteEmpresa (clínica do login) e Clinica. (3) Tags: code = sigla (ProgramaApoio.Sigla), description, color; vigências no dia exibido (confirmado); origem do VIP continua indefinida, por decisão do solicitante. (4) Clínicas do cliente = mesmo ClienteBD, confirmado. (5) Risco da clínica escondida retirado: o solicitante esclareceu que a Recepção não consegue agendar o médico numa clínica a que ele não está vinculado, porque ele só tem horários nas clínicas do seu vínculo. (6) Índices: registrado que os campos novos da arquitetura do Gemed 2.1 precisam de índices (Log de Mudanças, 07/10/2026). Acompanha 01-Definição v1.12, 02-Especificação v1.14 e 03-Protótipo v1.12.