Skip to content

feat(services): consultar pessoa atendida por ID e validators sem extensão (#167, backend) - #172

Merged
evertonschuster merged 4 commits into
mainfrom
feat/backend-consultar-pessoa-por-id
Oct 7, 2026
Merged

evertonschuster merged 4 commits into
mainfrom
feat/backend-consultar-pessoa-por-id

Conversation

@evertonschuster

Copy link
Copy Markdown
Owner

Resumo

Parte backend de #167: GET /api/v1/clients/{id} carrega uma pessoa atendida com seus contatos vinculados. Este PR reúne as duas linhas de trabalho que estavam em #170 (a consulta por id) e #171 (validators de clientes sem ClientRuleBuilderExtensions).

A tela de detalhe e os estados de carregando, erro e não encontrado são do frontend e não estão aqui. Por isso a descrição usa Refs, não Closes.

1. Consulta por id (ADR 0060)

Usa o mesmo ClientResponse que POST e PUT já devolvem, sem DTO novo.

  • 200: dados cadastrais, status (active ou inactive), guardians e referenceContacts com purposes.
  • 404 Client.NotFound: id inexistente, de outro tenant ou de cadastro excluído, sempre com o mesmo corpo. Os filtros de tenant e de exclusão lógica já escondem a linha e o handler não faz checagem própria.
  • 400 Client.IdRequired: id vazio (00000000-...).
  • Tenant só do token, como no resto do serviço.

Decisões registradas no ADR 0060:

  • Idade fora do contrato. A resposta traz birthDate e o frontend calcula.
  • CPF completo para qualquer usuário autenticado do tenant, o da pessoa e o dos responsáveis. O projeto não tem papéis (ARCHITECTURE §12), e o formulário de edição (Atualizar pessoa atendida e contatos vinculados #156) precisa do CPF dos responsáveis para reenviá-lo.
  • Contatos ordenados por nome e, no desempate, por id, em GetByIdAsync. Sem isso o banco devolve em ordem arbitrária, e o PUT recria todos os contatos com ids novos.

Efeito a conhecer: POST e PUT respondem os contatos na ordem em que a requisição os listou, e só a leitura ordena. GetByIdAsync é compartilhado com o update, que passa a carregar os contatos já ordenados; ele os substitui todos, então não há efeito.

Também entram:

  • Clients/GetClientById/ (query, validator e handler) e ClientsController.GetById.
  • services-api.d.ts regenerado: o diff é só o bloco get de /clients/{id}.
  • Linha "Read by id" no §10 do ARCHITECTURE.

2. Validators sem extensão (ADR 0061)

ClientRuleBuilderExtensions foi apagada. Cada validator de clientes (Create e Update, e os aninhados de responsável e de pessoa de referência) escreve suas próprias regras, com os mesmos códigos e as mesmas mensagens de antes.

  • O código ganha 102 linhas e perde 98 nos validators e na classe apagada: a repetição quase se paga na remoção.
  • O ADR 0061 substitui o item 3 do ADR 0049. ARCHITECTURE §2, §4, §10 e §12, a skill agenza-backend-slice (references/use-case.md) e o índice de ADRs acompanham.
  • Risco aceito: uma regra compartilhada agora é alterada em cada validator que a tem. Uma cópia mudada só em um lugar é pega quando os testes do outro validator afirmam a regra. Os testes dos validators de Create e Update afirmam código e mensagem de cada regra, e nenhum foi alterado.

Verificação

  • dotnet build backend/AdminBackend.slnx -c Release: 0 avisos, 0 erros.
  • dotnet test backend/AdminBackend.slnx -c Release: 738 testes verdes (ServicesService.Tests 399, ServicesService.PersistenceTests 56, Admin.SharedKernel.Tests 228, Admin.Logging.Tests 36, IdentityService.Tests 19), com o gate de cobertura passando.
    • Unit: encontrado com todos os campos, CPF completo da pessoa e dos responsáveis, finalidades, sem data de nascimento, inativo, id desconhecido, leitura sem escrita; validator com id vazio.
    • Persistência: inativo com contatos, outro tenant, excluído e desconhecido, ordem por nome e desempate por id.
  • npx tsc --noEmit no admin-frontend com os tipos novos: sem erros.
  • À mão, em PostgreSQL descartável (ARCHITECTURE §9), com a árvore do feat(services): consultar pessoa atendida por ID (#167, backend) #170, ou seja, antes da troca dos validators: postgres:18 inicializado por infra/postgres/init, com identity e services em portas privadas (5180/5181/5433), sem tocar na stack Aspire e no volume agenza-postgres-data. 32 verificações com token real (PKCE) passaram:
    • 200 para ativa, inativa e sem nascimento nem contatos; CPF inteiro; sem campo age.
    • Contatos ordenados por nome, inclusive depois de um PUT que os substitui; os antigos continuam só com DeletedAt na tabela e não aparecem.
    • 404 Client.NotFound para id desconhecido, de outro tenant (a linha existe na tabela) e excluído, com corpos idênticos fora do correlationId.
    • 400 Client.IdRequired sob clientId para id vazio, 401 sem token e 403 Tenant.ContextMismatch com X-Tenant-Id diferente do token.
    • A troca dos validators não toca persistência nem a rota; ela é coberta pelos testes de validator, que seguem verdes sem alteração.

Fora deste PR

  • Tela de detalhe no admin-frontend, com idade calculada a partir de birthDate e as mensagens de carregando, erro e não encontrado.
  • Mascaramento de CPF na listagem, que é de Listar e buscar pessoas atendidas #155.

Refs #167

🤖 Generated with Claude Code

evertonschuster and others added 4 commits October 7, 2026 19:07
Expõe GET /api/v1/clients/{id}, que devolve o mesmo ClientResponse de
POST e PUT: dados cadastrais, situação, responsáveis e pessoas de
referência com suas finalidades.

- Pessoa ativa ou inativa é devolvida; excluída, de outro tenant ou
  inexistente respondem o mesmo 404 Client.NotFound. Id vazio é 400
  Client.IdRequired, regra compartilhada com o validator do PUT.
- O CPF vem completo para qualquer usuário autenticado do tenant.
- A idade não vai no contrato: a resposta traz birthDate e o frontend
  calcula.
- GetByIdAsync carrega responsáveis e pessoas de referência ordenados
  por nome e, no desempate, por id.
- Tipos do frontend regenerados (services-api.d.ts).
- ADR 0060 e linha "Read by id" no §10 do ARCHITECTURE.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ensão (#167, backend)

A regra de id vazio são três linhas. Virar método de
ClientRuleBuilderExtensions trocava uma repetição curta por uma
indireção e obrigava a alterar o UpdateClientCommandValidator, fora do
escopo da issue. Os testes de cada validator já protegem o código
Client.IdRequired contra divergência.

- GetClientByIdQueryValidator escreve a regra inline, na forma que o
  validator do PUT já tinha.
- ClientRuleBuilderExtensions e UpdateClientCommandValidator voltam ao
  estado da main.
- Linha "Read by id" do §10 do ARCHITECTURE deixa de citar a extensão.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ras (ADR 0061)

Apaga ClientRuleBuilderExtensions e escreve inline, em cada validator,
as regras que Create e Update de clientes compartilhavam: limites de
responsáveis e de pessoas de referência, "menor exige responsável", nome
e vínculo do contato e finalidades.

- Códigos e mensagens são os mesmos de antes; o fio não muda e os
  testes dos validators passam sem alteração.
- Os literais Client.GuardianMissing e Client.ReferenceContactMissing
  passam a ser escritos no validator.
- ADR 0061 substitui o item 3 do ADR 0049 (a extensão como casa de uma
  regra compartilhada). ARCHITECTURE §2, §4, §10 e §12, a skill
  agenza-backend-slice (use-case.md) e o índice de ADRs acompanham.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ors-own-their-rules' into feat/backend-consultar-pessoa-por-id

# Conflicts:
#	docs/adr/README.md
@coderabbitai

coderabbitai Bot commented Oct 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 57 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 25d8ba3d-7f62-42ee-89d2-10fbdbe8d911
📥 Commits

Reviewing files that changed from the base of the PR and between a0d2038 and b58deff.

⛔ Files ignored due to path filters (1)
  • apps/admin-frontend/src/shared/api/generated/services-api.d.ts is excluded by !**/generated/**
📒 Files selected for processing (17)
  • .claude/skills/agenza-backend-slice/references/use-case.md
  • backend/docs/ARCHITECTURE.md
  • backend/services/services-service/ServicesService.Api/Controllers/ClientsController.cs
  • backend/services/services-service/ServicesService.Application/Clients/ClientRuleBuilderExtensions.cs
  • backend/services/services-service/ServicesService.Application/Clients/CreateClient/CreateClientCommandValidator.cs
  • backend/services/services-service/ServicesService.Application/Clients/GetClientById/GetClientByIdQuery.cs
  • backend/services/services-service/ServicesService.Application/Clients/GetClientById/GetClientByIdQueryHandler.cs
  • backend/services/services-service/ServicesService.Application/Clients/GetClientById/GetClientByIdQueryValidator.cs
  • backend/services/services-service/ServicesService.Application/Clients/UpdateClient/UpdateClientCommandValidator.cs
  • backend/services/services-service/ServicesService.Infrastructure/Repositories/ClientRepository.cs
  • backend/services/services-service/ServicesService.PersistenceTests/ClientPersistenceTests.cs
  • backend/services/services-service/ServicesService.Tests/Clients/GetClientById/GetClientByIdQueryHandlerTests.cs
  • backend/services/services-service/ServicesService.Tests/Clients/GetClientById/GetClientByIdQueryValidatorTests.cs
  • docs/adr/0049-conventions-for-new-backend-slices.md
  • docs/adr/0060-clients-read-by-id-contract.md
  • docs/adr/0061-validators-write-their-own-rules.md
  • docs/adr/README.md
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@evertonschuster
evertonschuster merged commit 952f7f4 into main Oct 7, 2026
17 checks passed
@evertonschuster
evertonschuster deleted the feat/backend-consultar-pessoa-por-id branch October 7, 2026 22:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant