CRUD de anotações do cliente para o terapeuta
TLDR:
/api/v1/me/clients/:client_id/commentspassa de sóindexparaindex,create,updateedestroy, permitindo ao terapeuta registrar anotações do cliente sem depender de uma sessão e listando apenas as próprias anotações.
Contexto
A aba “Anotações” dos detalhes do cliente (trgclub-web) vai ser reformulada conforme o Figma “Meus Clientes / Anotações” (seção Terapeuta PRO). O ticket pede que o terapeuta consulte, crie, edite e exclua anotações de um cliente a qualquer momento, sem depender de uma sessão em andamento, com formatação de texto preservada.
Hoje:
Commenté polimórfico (commentable). SóMeetingeUserincluemCommentable.GET /api/v1/me/clients/:client_id/comments(API::V1::ClientsCommentsController#index) devolve os comentários de todas asMeetingdo paciente em que o terapeuta participa, sem filtrar por autor: comentários de outro participante (ex.: o paciente, viaPOST /meetings/:id/comments) aparecem para o terapeuta.- Anotações só podem ser criadas por
POST /api/v1/meetings/:meeting_id/comments. Um cliente sem sessões nunca pode ter anotação.
A spec do front que consome este contrato fica em trgclub-web/.project/docs/specs/ na branch feat/client-annotations.
Objetivos
- Permitir criar anotação vinculada à relação terapeuta–cliente (
UserClient), sem sessão. - Permitir editar e excluir, pela rota do cliente, qualquer anotação do terapeuta para aquele cliente — tanto as do
UserClientquanto as criadas em sessões (Meeting). - Listar só as anotações cujo autor é o terapeuta logado.
- Aceitar
contentem HTML (gerado pelo editor do front), sem alterar como as anotações de sessão são gravadas.
Fora de escopo
- Busca no backend: a busca por termo é feita no front sobre a lista completa.
- Paginação do
index. - Checagem de plano PRO nas rotas: segue o padrão atual de
/me/clients, protegido apenas pela posse do cliente (current_clients_query) e pela autoria da anotação. - Mudanças em
/meetings/:meeting_id/comments,/me/commentse no modelComment. - Sanitização de HTML na API: o conteúdo é gravado como recebido e o front sanitiza na exibição (DOMPurify), o que também cobre as anotações antigas.
- Migrations: nenhuma mudança de schema.
Mudanças
app/models/user_client.rb
include Commentable→has_many :comments, as: :commentable, dependent: :destroy.
config/routes.rb
ruby
resources :comments, only: [:index, :create, :update, :destroy], controller: "clients_comments", on: :member
E atualização do bloco de rotas comentado no fim do arquivo.
app/controllers/api/v1/clients_comments_controller.rb
set_user_client:current_clients_query.find(params[:client_id]); 404 comAlerts::NotFound::Female.call(UserClient)se não existir (comportamento atual).- Escopo de anotações do terapeuta para o cliente:
Comment.where(commentable: [user_client, *Meeting.by_user(patient).with_participant(current_user)], user: current_user). index: o escopo acima,order(created_at: :desc),render json:(mantémCommentSerializer, comlocale_format_display).create:user_client.comments.new(content:, user: current_user). Resposta igual aAPI::V1::CommentsController#create:201com{ comment: {...} }, ou422comerrors.update: busca porpiddentro do escopo;404se não encontrar (inclui anotação de outro autor ou de outro cliente). Atualiza sócontent. Resposta200com{ comment: {...} }, ou422.destroy: mesma busca;200em sucesso.- Parâmetros:
params.expect(comment: [:content]), igual aoCommentsController.
Contrato resultante
| Método | Rota | Corpo | Sucesso | Erros |
|---|---|---|---|---|
| GET | /api/v1/me/clients/:client_id/comments |
— | 200 lista |
404 cliente |
| POST | /api/v1/me/clients/:client_id/comments |
{ comment: { content } } |
201 { comment } |
404 cliente, 422 |
| PATCH | /api/v1/me/clients/:client_id/comments/:pid |
{ comment: { content } } |
200 { comment } |
404 cliente/anotação, 422 |
| DELETE | /api/v1/me/clients/:client_id/comments/:pid |
— | 200 |
404 cliente/anotação |
Como verificar
Request specs em spec/requests/api/v1/:
clients_comments_index_spec.rb(existente, ajustar):- o caso “with meetings and comments” usa comentário do paciente → passa a esperar
[]; - novo caso: comentário do terapeuta em
Meetingaparece; - novo caso: comentário do terapeuta no
UserClientaparece; - novo caso: comentário do terapeuta para outro cliente não aparece;
- ordenação por
created_atdesc.
- o caso “with meetings and comments” usa comentário do paciente → passa a esperar
clients_comments_create_spec.rb: cria noUserClientcom autorcurrent_user; cliente inexistente → 404;contentvazio → 422.clients_comments_update_spec.rb: atualiza anotação doUserCliente deMeeting; anotação de outro autor → 404; de outro cliente → 404; conteúdo vazio → 422.clients_comments_destroy_spec.rb: exclui anotação doUserCliente deMeeting; outro autor → 404.
Rodar bundle exec rspec nos arquivos acima e bundle exec rubocop.
Documentação
- Criar
.project/docs/rules/clients/client_annotations.mdcom as regras: anotação vinculada aoUserClientou àMeeting, listagem só do autor, edição/exclusão só do autor. Registrar como R-006 em.project/docs/RULES.md. - Adicionar a spec e a regra ao índice
.project/docs/README.md.