3
respostas

[Dúvida] Validação do motivo de cancelamento da consulta

Qual a melhor estratégia de tratar o erro para retornar uma exceção personalizada quando nao é enviado um motivo válido?

Tentei comparar se o valor passado em dados.motivoCancelamento() faz parte do enum MotivoCancelamento()? no método cancelar() do service mas não encontrei um método do enum para isso. Teria que interar todo o enum para saber se o valor passado é válido?

Os erros gerados pelo bean validation são estes:

Enviando motivo vazio:

2023-03-14T21:47:50.446-03:00 WARN 4680 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot coerce empty String ("") tomed.voll.api.domain.consulta.MotivoCancelamentovalue (but could if coercion was enabled usingCoercionConfig)]

Enviando motivo que não consta no enum:

2023-03-14T21:48:35.880-03:00 WARN 4680 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of typemed.voll.api.domain.consulta.MotivoCancelamentofrom String "teste": not one of the values accepted for Enum class: [OUTROS, PACIENTE_DESISTIU, MEDICO_CANCELOU]]

3 respostas

Olá Uiratan, tudo bem?

Você pode criar uma exceção personalizada para lidar com o erro de validação do motivo de cancelamento e capturar o erro gerado pelo bean validation no controller para lançar essa exceção. Algo assim:

public void cancelar(DadosConsulta dados) {
    try {
        MotivoCancelamento.valueOf(dados.getMotivoCancelamento());
    } catch (IllegalArgumentException ex) {
        throw new MotivoCancelamentoInvalidoException();
    }
}

Fala Otávio, blz?

A validade do Enum é conferida logo no controller, quando é chamado o método cancelar(@RequestBody @Valid DadosCancelamentoConsulta dados). Se o valor passado nao é valido no Enum ele ja lança a exceção.

Logo, teria que ser uma exceção tratada dentro do DTO DadosCancelamentoConsulta.

Opa, tudo bem Uiratan?

Para validar se um valor enviado no DTO é um valor válido no Enum MotivoCancelamento você pode utilizar a anotação @javax.validation.constraints.Pattern. Com essa anotação, você pode especificar um regex que define quais são os valores aceitos pelo Enum. Algo assim:

    @NotNull
    @Pattern(regexp = "OUTROS|PACIENTE_DESISTIU|MEDICO_CANCELOU")
    private String motivoCancelamento;

Assim, quando um valor inválido for enviado no campo motivoCancelamento, o bean validation irá lançar a exceção ConstraintViolationException, que pode ser tratada no controller para retornar uma mensagem de erro mais adequada ao usuário. Algo assim:

@PostMapping("/cancelar")
public ResponseEntity cancelarConsulta(@Valid @RequestBody DadosCancelamentoConsulta dados) {
    try {
        // chama o service para cancelar a consulta
        consultaService.cancelar(dados);
        return ResponseEntity.ok().build();
    } catch (ConstraintViolationException ex) {
        List<String> erros = ex.getConstraintViolations().stream()
            .map(ConstraintViolation::getMessage)
            .collect(Collectors.toList());
        return ResponseEntity.badRequest().body(erros);
    }
}

Dessa forma, o usuário irá receber uma mensagem de erro informando que o motivo de cancelamento enviado não é válido