Agenda do Médico — Mapeamento de Banco de Dados (v1.0)
Documentos desta funcionalidade: 01 - Definição (v1.11) · 02 - Especificação (v1.13) · 03 - Protótipo (v1.11, código executável em 03 - Protótipo v1.11.html) · 04 - Mapeamento de Banco de Dados (v1.0)
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 e nenhum campo novo: tudo o que a tela exibe já existe e é preenchido pelo Agendamento (Recepção).
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
| Tabela | Banco | Função no endpoint |
|---|---|---|
| Agenda | GescomClienteAlfa | Tabela principal — uma linha por consulta |
| Paciente | GescomClienteAlfa | Nome, nome social e o indicador de paciente reservado (filtro) |
| PacienteFoto | GescomClienteAlfa | Foto do paciente |
| PEP / PEPDiagnostico | GescomClienteAlfa | Diagnósticos oncológicos do paciente |
| ProgramaApoio / ProgramaApoioPaciente | GescomClienteAlfa | Tags do paciente (RN-AGM-006) |
| Chave | GescomClienteAlfa | Nome curto da clínica e do convênio (RN-AGM-017) |
| Clinica | GescomClienteAlfa | Fuso horário da clínica de cada consulta [PROPOSTA] (ver “Referência de tempo”) |
| UnidadeAtendimento | GescomClienteAlfa | Nome da unidade e contagem de unidades ativas para consultas (RN-AGM-017, b) |
| AgendaClassificacao / AgendaSubClassificacao | GescomClienteAlfa | Classificação e subclassificação (RN-AGM-008) |
| TermoTraducao | IpTerminologia | Rótulo traduzido do modo de atendimento |
| ClienteEmpresa | IpSeguranca | Idioma e fuso da clínica em que o usuário entrou; contagem de clínicas acessíveis |
| ClientePerfilAcessoUsuario / UsuarioCliente | IpSeguranca | Clí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.
| Campo | Tipo | Origem | Observação |
|---|---|---|---|
date | data | parâmetro date | Eco do dia pedido |
serverNow | data/hora | relógio do servidor, no fuso de ClienteEmpresa.FusoOficial da clínica em que o usuário entrou | Referência de tempo da tela (Especificação, “Referência de tempo”) |
appointments[].id | int | Agenda.IdAgenda | |
startTime | horário | Agenda.DhAgendaIniUTC (NULL possível na DDL) | No fuso de “Referência de tempo”. Consulta com DhAgendaIniUTC NULL não entra na lista (não tem dia nem posição) |
endTime | horário | Agenda.DhAgendaFimUTC (NULL possível na DDL) | No fuso de “Referência de tempo”. [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) |
status | string | calculado — 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.code | char | Agenda.Atendimento | Domínio ModoAtendimento (Central do Médico, 4.1, “Domínios”) |
attendanceMode.label | string | Agenda.Atendimento → TermoTraducao.TermoValor | Mesma 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 |
delayMinutes | int | calculado | Minutos entre agora e DhAgendaIniUTC, calculados em UTC (a diferença não depende de fuso). Positivo só quando date é hoje, o horário já passou, Agenda.Situacao IN ('A','V') e DhAtendimentoIniUTC IS NULL; em qualquer outro caso, 0 — inclusive canceladas, que esta tela exibe e a Central não |
firstTime | boolean | Agenda.PrimeiraConsulta = 'S' | Domínio S/N |
tags | array | Paciente.PacienteVip + ProgramaApoioPaciente/ProgramaApoio | Origem, filtro (MostrarEm & 32) = 32, vigências e exceção VIP: Central do Médico, 4.1 (RN-CM-025). Na Agenda, “hoje” das vigências é o dia exibido (date) [PROPOSTA]. Cor, descrição e o achado em aberto sobre a origem do VIP: ver “Pendências”, item 3 |
complement | string | null | Agenda.Complemento (varchar(128), NULL) | |
patient.id | int | Agenda.IdPaciente | |
patient.preferredName / legalName | string | Paciente.NomeSocial / Paciente.Nome | Central do Médico, 4.1 (lá grafado prefferedName) |
patient.photo | url | null | PacienteFoto (Padrao = 'S', a mais recente) | Central do Médico, 4.1 e “Infraestrutura de apoio” (MinIO) |
patient.diagnosis | array | PEPDiagnostico.Diagnostico, Tipo = 'O' | Central do Médico, 4.1 — todos os diagnósticos oncológicos ativos (critério de “ativo” herdado da Central) |
clinic | string | null | Agenda.IdChClinica → Chave.IdChave → Chave.Descricao | Nome 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 esteja inativa hoje (Chave.Status) — a consulta aconteceu ou acontecerá ali |
unit | string | null | Agenda.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 específica esteja inativa hoje |
insurance | string | Agenda.IdChConvenio (NOT NULL) → Chave.IdChave → Chave.Descricao | Nome 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. [PROPOSTA] Exibido mesmo que o convênio esteja inativo hoje (Chave.Status). O plano (Agenda.Plano, Agenda.IdPlano → ConvenioPlano) não é usado (RN-AGM-017, c) |
classification | objeto | null | — | null quando Agenda.IdAgendaClassificacao é NULL (RN-AGM-008) |
classification.name | string | Agenda.IdAgendaClassificacao → AgendaClassificacao.Descricao (varchar(20)) | [PROPOSTA] Exibida mesmo que a classificação esteja inativa hoje (AgendaClassificacao.Status) |
classification.subName | string | null | Agenda.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).
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 de canceled para scheduled (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 — ela 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.
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 [PROPOSTA]
AND uc.RemovidoEm IS NULL
AND cpau.RemovidoEm IS NULL
AND ce.RemovidoEm IS NULL;O filtro por ClienteBDId é [PROPOSTA]: “clínicas do cliente” interpretado como as ClienteEmpresa do mesmo banco de cliente — a massa de teste (CargaCMZero.xlsx) tem duas ClienteEmpresa (“Clinica A” e “Clínica B”) no mesmo ClienteBD. Mesmo critério de “clínica acessível” do Check-in de Usuários (RN-CIU-009, Épico 1), restrito ao banco atual. Ver “Pendências”, item 6, sobre o caso de consulta numa clínica a que o médico não tem acesso.
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 -- sem RemovidoEm na DDL
WHERE IdClinica = @IdChClinica
AND StConsulta = 'S'
AND Status = @StatusAtivo; -- [A DEFINIR] valor de "ativa" em UnidadeAtendimento.StatusReferência de tempo — [PROPOSTA]
A agenda reúne clínicas que podem estar em fusos diferentes — a massa de teste tem “Clinica A” (FusoOficial = -4) e “Clínica B” (-3) no mesmo banco de cliente. A proposta:
serverNowe o que é “hoje”: fuso da clínica em que o usuário entrou (ClienteEmpresa.FusoOficial), como na Central do Médico.- Horários e dia de cada consulta: fuso da clínica da consulta,
Clinica.FusoHorario(varchar(35) NOT NULL, GescomClienteAlfa) — o horário mostrado é o horário local onde o paciente será atendido. Formato do campo (nome IANA, nome de fuso do Windows ou deslocamento): [A DEFINIR] — decide se a conversão pode ser feita no banco (AT TIME ZONEdo SQL Server aceita só nomes do Windows) ou precisa ser feita na aplicação.
Esta proposta muda o contrato da Especificação, que hoje define startTime/endTime como HH:MM “no fuso da clínica”, no singular, e usa serverNow para a linha “AGORA”, a rolagem inicial e o “Hoje”: com dois fusos na mesma lista, comparar serverNow com startTime deslocaria esses elementos. Se aceita, a Especificação passa a mandar também o início e o fim de cada consulta em ISO 8601 com deslocamento (para o front comparar com serverNow em UTC) e a mostrar, quando os fusos diferem, a qual fuso o horário se refere.
Alternativa, se a proposta não for aceita: tudo no fuso da clínica do login (comportamento da Central, contrato atual), aceitando que as consultas de uma clínica em outro fuso apareçam com o horário convertido para o fuso do login.
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:
| Campo | Valor | Significado | Fonte |
|---|---|---|---|
UnidadeAtendimento.StConsulta | S / N | Unidade atende (ou não) consultas | Solicitante; massa de teste (CargaCMZero.xlsx) |
UnidadeAtendimento.Status | [A DEFINIR] | Unidade ativa / inativa | — |
Convenio.Convenio | T | Convênio “Particular” | Solicitante; massa de teste |
Convenio.Convenio | B | Convênio reservado (na massa de teste, usado junto com o paciente reservado) | Massa de teste |
Convenio.Convenio | NULL | Convênio comum | Massa de teste — [A DEFINIR] se há outros valores em produção |
Paciente.Paciente | B | Paciente reservado, que não representa consulta (char(1) NOT NULL) | Central do Médico, RN-CM-030; demais valores não mapeados aqui |
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'(viaAgenda.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 (o campo existe emAgendana DDL). [A DEFINIR] se a Central também deve aplicar este filtro (o Mapeamento dela não o cita).Agenda.Situacao IN ('A','V','C','D','F','I','M','O','T')— todo o domínioSituacaoAgenda; canceladas (inclusive falta) entram, comstatus = canceled(RN-AGM-009/010).Agenda.DhAgendaIniUTC IS NOT NULLe dia deDhAgendaIniUTC, no fuso de “Referência de tempo”, igual adate. Para usar índice, a consulta filtra primeiro uma faixa UTC ampla (DhAgendaIniUTC >= @dataInicioUtc - 14h AND DhAgendaIniUTC < @dataFimUtc + 14h, folga do maior deslocamento de fuso) e aplica o dia exato no fuso como filtro residual.- Tags: filtros de
MostrarEme de vigência da Central (4.1), avaliados no diadate. - Ordenação:
Agenda.DhAgendaIniUTCcrescente.
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).
Tabelas envolvidas
Agenda, Paciente (filtro), Clinica (fuso da consulta, se a proposta de “Referência de tempo” for aceita) — mesmas de 4.1.
Consulta
-- @fromUtc/@toUtc: início de @from e fim de @to, com folga de 14h para cada lado.
-- LocalDate(): data de DhAgendaIniUTC no fuso de "Referência de tempo" (4.1) —
-- no banco, se Clinica.FusoHorario for nome de fuso do Windows; senão, na aplicação.
SELECT DISTINCT LocalDate(a.DhAgendaIniUTC, c.FusoHorario) AS Data
FROM Agenda a
JOIN Paciente p ON p.IdPaciente = a.IdPaciente
JOIN Clinica c ON c.IdChClinica = a.IdChClinica
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
AND LocalDate(a.DhAgendaIniUTC, c.FusoHorario) BETWEEN @from AND @to -- filtro residual
ORDER BY Data;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: a primeira consulta depois do fim de @from (com folga de fuso); previous: o inverso, com DESC.
SELECT TOP 1 LocalDate(a.DhAgendaIniUTC, c.FusoHorario) AS Data
FROM Agenda a
JOIN Paciente p ON p.IdPaciente = a.IdPaciente
JOIN Clinica c ON c.IdChClinica = a.IdChClinica
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 >= @fromFimUtc - 14h -- faixa usa o índice
AND LocalDate(a.DhAgendaIniUTC, c.FusoHorario) > @from -- filtro residual
ORDER BY a.DhAgendaIniUTC ASC;Sem a proposta de fuso por clínica, LocalDate() usa o fuso da clínica do login e o JOIN Clinica sai.
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).
Índices
Índices existentes em Agenda (Biblioteca de Schema — DDL, GescomClienteAlfa) 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 e o de FK FK_Agenda_IdChRecurso. Todos os compostos começam por IdChClinica e usam a data legada Agenda.Data, não DhAgendaIniUTC. Como esta tela não filtra por clínica (RN-AGM-002) e usa DhAgendaIniUTC, nenhum deles cobre as três consultas.
[PROPOSTA] índice não único IX_Agenda_IdChRecurso_TipoAgenda_DhAgendaIniUTC (IdChRecurso, TipoAgenda, DhAgendaIniUTC) INCLUDE (Situacao, IdPaciente, IdChClinica, DhAgendaFimUTC, RemovidoEm) — atende a faixa de GET /day, days-with-appointments e o TOP 1 de next-appointment-date; IdChClinica no INCLUDE evita ir à tabela base para achar o fuso. A confirmar com o time de banco antes de criar, 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 8.
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
| Seed | Tabela(s) | Por cliente ou global? | Status | Detalhe completo |
|---|---|---|---|---|
Traduções do domínio ModoAtendimento (Presencial, Teleatendimento, Customizado) nos idiomas pt-BR, en-US e es-419 | TermoTraducao (IpTerminologia) | Global | Já usado pela Central do Médico — conferir que as três línguas existem | 4.1, campo attendanceMode.label |
| Nome curto de cada clínica e de cada convênio, inclusive “Particular” | Chave.Descricao (GescomClienteAlfa) | Por cliente | Já em produção (cadastro de clínica e convênio) | 4.1, campos clinic e insurance |
Nenhum parâmetro novo (IpParametro/IpParametroChave): a tela não tem limiar configurável próprio.
Pendências
- [A DEFINIR] Valor de “ativa” em
UnidadeAtendimento.Status(usado emUnitVisible()); a massa de teste não preenche o campo. - [PROPOSTA] Referência de tempo com várias clínicas: horários e dia de cada consulta no fuso da clínica da consulta (
Clinica.FusoHorario) — muda o contrato da Especificação (início/fim em ISO 8601 por consulta). [A DEFINIR] o formato deClinica.FusoHorario. - [PROPOSTA] Contrato de
tagscom cor e descrição — a Especificação definetagscomo lista de códigos, mas a cor vem do cadastro (ProgramaApoio.Cor/Descricao, Central 4.1). Proposta:tags: [{ "code", "label", "color", "description" }], comcode=ProgramaApoio.IdProgramaApoio,label=ProgramaApoio.Nome; quando o VIP chegar pelos dois caminhos (Paciente.PacienteVipeProgramaApoioPaciente), aparece uma vez só. Depende do achado em aberto da Central (4.1, campotags) sobre a origem do VIP. Exige ajuste da Especificação. - [PROPOSTA] Vigência das tags avaliada no dia exibido (
date), não em “hoje”. - [PROPOSTA] “Clínicas do cliente” =
ClienteEmpresado mesmoClienteBDda sessão (emClinicVisible()). Não há campo que ligueClienteEmpresa(IpSeguranca) aClinica(GescomClienteAlfa) — a regra não precisa dessa ligação, mas qualquer funcionalidade futura que precise saber “qualClinicaé estaClienteEmpresa” vai precisar. - Risco a decidir: se o médico tem acesso a uma única clínica, mas a Recepção o agendou também em outra, a lista mistura as duas e
clinicvem vazio em todas (RN-AGM-017, a, fala em “acesso”). Alternativa: mostrar a clínica quando as consultas do dia vierem de mais de uma clínica. - [PROPOSTA] Precedência de
AppointmentStatus()(casoVcom fim sem início =finished) — a sobreposição é herdada da Central e deve ser corrigida lá também. - Trilha de auditoria (NGS1.07.03, estágio 1) — mecanismo transversal, não mapeado aqui; precisa existir para a conformidade.
- Divergência de tipo registrada:
Agenda.IdAgendaClassificacaoéinte não tem FK, enquanto a PK deAgendaClassificacaoésmallint(Agenda.IdAgendaSubClassificacao, por sua vez, tem FK). O join funciona; o risco é de integridade (classificação apagada sem erro). Registrado no Log de Mudanças Estruturais do Banco de Dados como descoberta. - [PROPOSTA] Índice novo em
Agenda(ver “Índices”). - [A DEFINIR] Filtro
Agenda.RemovidoEm IS NULLna Central do Médico (aplicado aqui; não citado no Mapeamento da Central).
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 deRemovidoEme índices deAgenda— e valores de exemplo na massa de testeCargaCMZero.xlsx(nomes curtos emChave,Convenio.Convenio=T/B/NULL,UnidadeAtendimento.StConsulta, duasClienteEmpresano mesmoClienteBDcom 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 emChave.Descricao; status também emChave.Status; plano escrito emAgenda.Plano(não usado); acesso a mais de uma clínica porClientePerfilAcessoUsuario; unidade ativa para consultas porUnidadeAtendimento.StConsulta = 'S'; particular comConvenio.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.IdChClinicaeConvenio.IdChConveniochegam aChaveviaPortador(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” comparamserverNowcomstartTime) — registrado em “Referência de tempo” e na pendência 2; (2)delayMinutespositivo para canceladas — passa a exigirSituacao 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, eTOP 1em 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.RemovidoEme cache deClinicVisible(); (6) exclusão lógica — conferido na DDL:Agenda,Paciente,ProgramaApoioeProgramaApoioPacientetêmRemovidoEm;UnidadeAtendimento,Chave,Clinica,Convenioe as tabelas de classificação não têm — filtroAgenda.RemovidoEm IS NULLacrescentado; (7) tipo dos identificadores: a Especificação davauuid, o mapeamentoint— Especificação corrigida paraint(v1.13); (8)Situacaofora do domínio e sobreposição dechecked/finishedemAppointmentStatus()— filtro pelo domínio e precedência (pendência 7); (9) índice proposto ganhouIdChClinica,DhAgendaFimUTCeRemovidoEmno INCLUDE;UnitVisible()por clínica distinta; (10)endTimecomDhAgendaFimUTCNULL (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ênioB, NULL comum, valorRdo modo de atendimento, clínica/convênio/classificação inativos); (12) pendências completadas: auditoria, origem do VIP e docodedas 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.nameexplicitado. Não aplicado (verificado como não procedente): risco dePaciente.PacienteNULL descartar pacientes comuns no filtro<> 'B'— a DDL definePaciente.Pacientecomochar(1) NOT NULL.