Épico 5 — Menu Lateral — Mapeamento de Banco de Dados (v1.5)

Documentos deste épico: 01 - Definição (v1.7) · 02 - Especificação (v1.5) · 03 - Protótipo (v1.6, código executável em 03 - Protótipo v1.6.html) · 04 - Mapeamento de Banco de Dados (v1.5). Este épico faz parte do documento guarda-chuva Check-in de Usuários.


SEÇÃO 4 — MAPEAMENTO DE BANCO DE DADOS

4.1 Endpoint: GET /api/v1/menu

Retorna, para o usuário autenticado, a árvore de grupos e itens de menu já filtrada pelo perfil de acesso vigente na clínica atual, com a marcação de quais itens estão favoritados (02 - Especificação, “Integração com Backend”).

Tabelas envolvidas

TabelaBancoFunção no endpoint
ClienteProcessoIpSegurancaHabilitação de cada Processo para o ClienteBD (tenant) do usuário — só processos habilitados entram na consulta
ClientePerfilAcessoUsuarioIpSegurancaResolve o perfil de acesso vigente do usuário na clínica atual (RemovidoEm nulo)
ClientePerfilAcessoIpSegurancaPerfil de acesso resolvido a partir de ClientePerfilAcessoUsuario
ClientePerfilAcessoProcessoIpSegurancaLiga o perfil de acesso a um ClienteProcesso; ExibeMenu e Ordem decidem quais itens aparecem e em que posição (RN-CIU-027)
ProcessoIpSegurancaNome, ícone e rota de cada item de menu
ProcessoGrupoIpSegurancaNome do grupo a que um item pertence, quando existe
ClienteUsuarioMenuFavoritoIpSegurancaMarca quais itens estão favoritados para este usuário/perfil/clínica (RN-CIU-028)
ClienteEmpresaIpSegurancaNome/logo da clínica atual — campo clinicaAtual da resposta

Mapa de campos

CampoTipoBancoObservação
clinicaAtual.clienteEmpresaIduuidClienteEmpresa.Id (uniqueidentifier)
clinicaAtual.nomestringClienteEmpresa.Nome (varchar(50))
clinicaAtual.caminhoLogostringClienteEmpresa.CaminhoLogo (varchar(100), nullable)
grupos[].processoGrupoIduuidProcessoGrupo.Id (uniqueidentifier)
grupos[].nomestringProcessoGrupo.Nome (varchar(20))
grupos[].itens[].clientePerfilAcessoProcessoIduuidClientePerfilAcessoProcesso.Id (uniqueidentifier)identifica o item já resolvido para o perfil vigente — é o id usado depois pelos endpoints de favoritar (4.2/4.3)
grupos[].itens[].processoIduuidProcesso.Id (uniqueidentifier)
grupos[].itens[].nomestringProcesso.Nome (varchar(50))
grupos[].itens[].iconestringProcesso.Icone (varchar(40), nullable)nome de ícone de lucide.dev/icons ou react-icons.github.io, nunca um arquivo próprio
grupos[].itens[].rotastringProcesso.Rota (varchar(128), nullable)
grupos[].itens[].favoritoboolcalculadoexiste linha ativa (RemovidoEm nulo) em ClienteUsuarioMenuFavorito para o par (ClientePerfilAcessoUsuarioId do usuário/clínica atual, ClientePerfilAcessoProcessoId do item)
itensSemGrupo[]mesmos 5 campos de grupos[].itens[] acimaProcesso.ProcessoGrupoId IS NULLmesma origem, apenas sem o agrupamento
favoritos[]mesmos 5 campos, sem favorito (a própria presença na lista já é o favorito)ClienteUsuarioMenuFavorito filtrado por ClientePerfilAcessoUsuarioId do usuário/clínica atual, RemovidoEm nuloordenado por Processo.Nome (RN-CIU-028)

Domínios

ExibeMenu (domínio de ClientePerfilAcessoProcesso.ExibeMenu, char(1), default 'S'):

ValorSignificado
SItem aparece no menu para este perfil de acesso
NItem habilitado para o cliente (ClienteProcesso) mas oculto do menu para este perfil especificamente

Filtros do endpoint

  • ClienteProcesso.ClienteBDId = {ClienteBD do usuário autenticado} AND ClienteProcesso.RemovidoEm IS NULL — apenas processos habilitados para o tenant
  • ClientePerfilAcessoUsuario referente ao (usuário logado, ClienteEmpresa atual da sessão), RemovidoEm IS NULL — resolve o ClientePerfilAcessoId vigente
  • ClientePerfilAcessoProcesso.ClientePerfilAcessoId = {perfil resolvido} AND ExibeMenu = 'S' AND RemovidoEm IS NULL — só os itens liberados para exibição no menu (RN-CIU-027)
  • Ordenação dos itens dentro de cada grupo (ou da lista sem grupo): ClientePerfilAcessoProcesso.Ordem ascendente
  • favoritos: ClienteUsuarioMenuFavorito.ClientePerfilAcessoUsuarioId = {vínculo usuário/perfil/clínica atual} AND RemovidoEm IS NULL, ordenado por Processo.Nome (RN-CIU-028)

4.2 Endpoint: POST /api/v1/menu/items/{clientePerfilAcessoProcessoId}/favorite

Favorita um item do menu para o usuário autenticado, na clínica atual (02 - Especificação, “Integração com Backend”).

Tabelas envolvidas

TabelaBancoFunção no endpoint
ClientePerfilAcessoProcessoIpSegurancaValida que o item existe, pertence ao perfil de acesso vigente e está com ExibeMenu = 'S' — senão 404
ClienteUsuarioMenuFavoritoIpSegurancaInsere (ou reativa, se já existia com RemovidoEm preenchido — RN-CIU-005) a linha do par usuário/item

Mapa de campos

CampoTipoBancoObservação
clientePerfilAcessoProcessoId (path)uuidClienteUsuarioMenuFavorito.ClientePerfilAcessoProcessoId (uniqueidentifier)metade da PK composta
——ClienteUsuarioMenuFavorito.ClientePerfilAcessoUsuarioId (uniqueidentifier)outra metade da PK composta — resolvido do usuário/clínica atual da sessão, não vem no request
favorito (response)boolfixo true

Filtros do endpoint

  • Valida que clientePerfilAcessoProcessoId pertence ao perfil de acesso vigente do usuário na clínica atual, com ExibeMenu = 'S' (mesmo filtro do GET, 4.1) — senão 404
  • Exclusão lógica (RN-CIU-005, transversal): se já existe uma linha para o par com RemovidoEm preenchido, o INSERT vira UPDATE limpando RemovidoEm, em vez de criar uma segunda linha — a PK composta (ClientePerfilAcessoUsuarioId, ClientePerfilAcessoProcessoId) não permite duplicidade

4.3 Endpoint: DELETE /api/v1/menu/items/{clientePerfilAcessoProcessoId}/favorite

Desfavorita um item do menu para o usuário autenticado, na clínica atual (02 - Especificação, “Integração com Backend”).

Tabelas envolvidas

TabelaBancoFunção no endpoint
ClienteUsuarioMenuFavoritoIpSegurancaExclusão lógica (RemovidoEm) da linha do par usuário/item

Mapa de campos

CampoTipoBancoObservação
clientePerfilAcessoProcessoId (path)uuidClienteUsuarioMenuFavorito.ClientePerfilAcessoProcessoId (uniqueidentifier)junto de ClientePerfilAcessoUsuarioId (resolvido da sessão), identifica a linha a remover
favorito (response)boolfixo false

Filtros do endpoint

  • ClienteUsuarioMenuFavorito.ClientePerfilAcessoUsuarioId = {vínculo usuário/perfil/clínica atual} AND ClientePerfilAcessoProcessoId = {path} AND RemovidoEm IS NULL — 404 se não existia favoritado
  • Exclusão lógica (RN-CIU-005, transversal): marca RemovidoEm, nunca remove a linha fisicamente

Tabelas existentes utilizadas (consolidado)

Consolidado por tabela, como referência rápida — o detalhamento de campos e uso já está nas seções de endpoint acima (4.1 a 4.3), não repetido aqui (Lição #10 da Skill Designer).

TabelaBancoEndpoints que usam
ProcessoIpSeguranca4.1
ProcessoGrupoIpSeguranca4.1
ClienteProcessoIpSeguranca4.1
ClientePerfilAcessoIpSeguranca4.1
ClientePerfilAcessoUsuarioIpSeguranca4.1
ClientePerfilAcessoProcessoIpSeguranca4.1, 4.2
ClienteUsuarioMenuFavoritoIpSeguranca4.1, 4.2, 4.3
ClienteEmpresaIpSeguranca4.1

Nenhuma tabela nova. Toda a estrutura necessária — itens de menu, agrupamento, habilitação por cliente, liberação e ordem por perfil de acesso, favoritos, e a identificação da clínica no cabeçalho do menu — já existe em produção no banco IpSeguranca. Tipos e nullability confirmados na Biblioteca de Schema (DDL), IpSeguranca.sql, nesta versão (16/09/2026).

Separação de bancos: todas as tabelas utilizadas por este épico pertencem ao banco IpSeguranca.

Schema legado identificado e descartado

O banco de template GescomZeradoPadronizacao (mesmo arquivo de origem da Biblioteca de Schema) tem uma estrutura equivalente e mais antiga para menu: SegMenu, SegPastaMenu, SegMenuGrupo e SegMenuDetalhe — esta última com um campo PaginaInicial que corresponde, na estrutura legada, ao mesmo papel do campo ProcessoAbertura de ClienteUsuarioMenuFavorito na estrutura atual — correspondência que ajudou a localizar o campo, com o significado hoje confirmado na Seção 1 (RN-CIU-028).

Essa estrutura legada foi identificada e descartada em favor do schema moderno acima: pertence ao banco de template pré-Clean-Architecture, chaveado por identificadores numéricos locais (smallint) em vez de uniqueidentifier, e não tem nenhum dos conceitos centrais da arquitetura atual — não existe Cliente, ClienteBD (banco por tenant) nem ClienteEmpresa (clínica) na cadeia de chaves de SegMenuDetalhe, apenas um IdUsuario local. Não é uma base compatível com o modelo multi-tenant deste projeto.

Campo novo proposto: ClientePerfilAcessoUsuario.CodProfissional

A Seção 1 (RN-CIU-028) documenta que, na ausência de uma escolha manual de tela inicial, a tela inicial padrão do usuário é seu próprio cockpit, quando seu perfil de acesso tiver um indicado. Esse indicador não existe hoje em nenhuma base consultada (Biblioteca de Schema (DDL) nem EsquemaGemed21.csv — checado em 15/09/2026, reconfirmado em 16/09/2026) — confirmado pelo solicitante como campo novo a criar:

CampoTabelaTipoObrigatoriedadeValor padrãoDescrição
CodProfissionalClientePerfilAcessoUsuario (IpSeguranca)char(3)Nullable — confirmado pelo solicitante; ausência de código é o que produz “sem tela inicial” (RN-CIU-028) quando também não há escolha manualSem valor padrão (NULL)Código do tipo de cockpit/central padrão do usuário nessa combinação perfil × clínica — determina qual cockpit abre como tela inicial na ausência de uma escolha manual de tela inicial (RN-CIU-028). Nome, tabela, tipo, nullability e domínio de valores confirmados pelo solicitante. Domínio: MED, ENF, FAR, REC, ADM, BKO — cada valor aponta para a central (cockpit) correspondente; MED/ENF/FAR/BKO correspondem aos fluxos por profissional já documentados no projeto (médico, enfermagem, farmácia, backoffice), REC/ADM apontam para centrais ainda não especificadas em nenhum épico consultado até aqui.

Migração (estrutura confirmada pelo solicitante; execução real no banco ainda pendente): ALTER TABLE IPSeguranca.dbo.ClientePerfilAcessoUsuario ADD CodProfissional char(3) NULL — pendente de execução real no banco e de registro na Biblioteca de Schema (DDL) depois de aplicada. Ver Log de Mudanças Estruturais do Banco de Dados, entrada de 15/09/2026.

Nota: este campo não é consultado por nenhum dos 3 endpoints deste épico (4.1 a 4.3) — a resolução de tela inicial por CodProfissional acontece no roteamento pós-login (E1), não na montagem do menu em si. Permanece documentado aqui, e não numa seção de endpoint, por ser um achado de estrutura do épico como um todo.

Seeds da Funcionalidade

SeedTabela(s)Por cliente ou global?StatusDetalhe completo
Item de menu “Suporte Gemed” (link externo à aplicação de suporte técnico da Interprocess TI)Processo (mais ClienteProcesso e ClientePerfilAcessoProcesso, por cliente/perfil, para habilitá-lo)Global o cadastro do Processo; a habilitação por cliente e perfil de acesso é individual[PROPOSTA] — item de exemplo, existência e nome exatos a confirmar contra o mockup original do menu, hoje indisponível01 - Definição, “Lista consolidada de itens [PROPOSTA]”, item 2
Árvore completa de grupos e itens do menu (quais Processo existem, em quais ProcessoGrupo, com quais ícones e rotas)Processo, ProcessoGrupo, ClienteProcesso, ClientePerfilAcessoProcessoProcesso/ProcessoGrupo globais; ClienteProcesso e ClientePerfilAcessoProcesso por cliente/perfil[PROPOSTA] — pendente de um levantamento de produto que substitua o mockup perdido; sem essa árvore, nenhum cliente novo tem menu funcional além dos módulos já especificados individualmente (Central do Médico/Cockpit, Agenda do Médico)01 - Definição, “Lista consolidada de itens [PROPOSTA]”, item 1

Nenhum parâmetro de configuração (IpParametro/IpParametroChave ou equivalente) é necessário para esta funcionalidade — o comportamento do menu (filtragem, favoritos, busca, responsividade) não depende de nenhum valor configurável por cliente além da própria estrutura de Processo/ClientePerfilAcessoProcesso já listada acima.


Histórico de Versões

  • v1.0 (15/09/2026) — versão inicial do épico. Estrutura de dados localizada por completo na Biblioteca de Schema (DDL), banco IpSeguranca — nenhuma tabela nova. Schema legado equivalente (GescomZeradoPadronizacao.dbo.SegMenu/SegPastaMenu/SegMenuGrupo/SegMenuDetalhe) identificado e descartado, com a correspondência de SegMenuDetalhe.PaginaInicial registrada como base da interpretação [PROPOSTA] de ClienteUsuarioMenuFavorito.ProcessoAbertura. Dois seeds registrados como [PROPOSTA] — item “Suporte Gemed” e a árvore completa de grupos/itens do menu, ambos pendentes do mockup original perdido.
  • v1.1 (15/09/2026) — ClienteUsuarioMenuFavorito.ProcessoAbertura deixa de ser [PROPOSTA]: confirmado como o indicador da escolha do usuário de tela inicial do sistema (RN-CIU-028), sobrepondo o cockpit padrão quando presente. Novo achado: o campo que identifica o cockpit padrão do usuário em ClientePerfilAcessoUsuario, citado pelo solicitante, não foi localizado na Biblioteca de Schema (DDL) nem no EsquemaGemed21.csv — registrado como pendência técnica nesta seção e no Log de Mudanças Estruturais do Banco de Dados.
  • v1.2 (15/09/2026) — confirmada pelo solicitante a criação de ClientePerfilAcessoUsuario.CodProfissional, char(3) — a pendência técnica anterior (campo não localizado) vira proposta de estrutura: nova subseção “Campo novo proposto” substitui “Pendência técnica: campo do cockpit padrão”, com a migração sugerida. Nullability e domínio de valores do campo seguem [PROPOSTA], não confirmados pelo solicitante. Log de Mudanças Estruturais do Banco de Dados atualizado.
  • v1.3 (15/09/2026) — confirmados pelo solicitante os dois atributos de CodProfissional que seguiam [PROPOSTA]: nullable; domínio MED, ENF, FAR, REC, ADM, BKO (cada código aponta para a central/cockpit correspondente). Tabela de especificação do campo e migração sugerida atualizadas para refletir a estrutura confirmada — só a execução real da migração no banco segue pendente. Log de Mudanças Estruturais do Banco de Dados atualizado.
  • v1.4 (15/09/2026) — pedido do solicitante ao revisar o protótipo: ClienteEmpresa passa de “não consultada para montar o menu” para efetivamente consultada — Nome e CaminhoLogo alimentam o novo campo clinicaAtual ([PROPOSTA]) da resposta de GET /api/v1/menu, para o cabeçalho do menu exibir o nome da clínica atual (Seção 2, “Cabeçalho do Menu”). Mesmos campos de ClienteEmpresa já usados por E3/E6 para nome/logo de clínica — nenhuma estrutura nova, nenhuma tabela nova.
  • v1.5 (16/09/2026) — Reestruturação da Seção 4, a pedido do solicitante: a antiga tabela única “Tabelas existentes utilizadas” foi substituída por 3 subseções por endpoint (4.1 GET /api/v1/menu, 4.2 POST .../favorite, 4.3 DELETE .../favorite), cada uma com Tabelas envolvidas, Mapa de campos, Domínios (quando aplicável) e Filtros do endpoint — mesmo padrão (mais detalhado) já usado em Central do Médico (Cockpit) e Agenda do Médico, escolhido pelo solicitante em vez do padrão mais leve usado até então neste próprio épico e no E6 (uma linha “Tabelas envolvidas” dentro do endpoint, na Seção 2). Tipos de campo (uniqueidentifier, varchar(N), char(1), tinyint) confirmados na Biblioteca de Schema (DDL), IpSeguranca.sql, nesta versão. A tabela consolidada por tabela foi mantida, ao final, como referência rápida, sem repetir o detalhamento já dado por endpoint (Lição #10). “Schema legado identificado e descartado”, “Campo novo proposto: CodProfissional” e “Seeds da Funcionalidade” preservados sem alteração de conteúdo. Nenhuma tabela nova, nenhuma mudança de estrutura de dados — reorganização documental. Em consequência, a Seção 2 (02 - Especificação, v1.5) teve as linhas inline “Tabelas envolvidas: …” de cada endpoint removidas, substituídas por uma nota única apontando para esta Seção 4 — mesma convenção de Central do Médico/Agenda do Médico, evitando repetir a mesma informação em dois lugares (Lição #10).