Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Nenhuma validação funciona

Ao testar o agendamento, todas as requisições são executadas, mesmo que não esteja de acordo com as validações, ou seja, as validações não estão funcionando.

@Service
public class AgendaDeConsultas {

    @Autowired
    private MedicoRepository medicoRepository;

    @Autowired
    private PacienteRepository pacienteRepository;

    @Autowired
    private ConsultaRepository consultaRepository;

    @Autowired
    private List<ValidadorAgendamentoDeConsulta> validadores;

    public DadosDetalhamentoConsulta agenda(DadosAgendamentoConsulta dados) throws ValidacaoException {

        if (!pacienteRepository.existsById(dados.idPaciente())) {
            throw new ValidacaoException("O ID do paciente informado não existe!");
        }

        if (dados.idMedico() != null && !medicoRepository.existsById(dados.idMedico())) {
            throw new ValidacaoException("O ID do médico informado não existe!");
        }

        validadores.forEach(validador -> {
            try {
                validador.valida(dados);
            } catch (ValidacaoException e) {
                e.printStackTrace();
            }
        });

        Medico medico = escolheMedico(dados);

        if (medico == null) {
            throw new ValidacaoException("Não existe médico disponível nessa data!");
        }

        Paciente paciente = pacienteRepository.getReferenceById(dados.idPaciente());
        Consulta consulta = new Consulta(null, medico, paciente, dados.data(), null);

        consultaRepository.save(consulta);

        return new DadosDetalhamentoConsulta(consulta);
    }
    
    private Medico escolheMedico(DadosAgendamentoConsulta dados) throws ValidacaoException {
        if (dados.idMedico() != null && medicoRepository.existsById(dados.idMedico())) {
            return medicoRepository.getReferenceById(dados.idMedico());
        }

        if (dados.especialidade() == null) {
            throw new ValidacaoException("É obrigatório inserir a especialidade quando o médio não for escolhido!");
        }

        return medicoRepository.escolheMedicoAleatorioLivreNaData(dados.especialidade(), dados.data());
    }

}
6 respostas
public interface ValidadorAgendamentoDeConsulta {

    void valida(DadosAgendamentoConsulta dados) throws ValidacaoException;

}
@Component
public class ValidadorHorarioAntecedencia implements ValidadorAgendamentoDeConsulta {

    public void valida(DadosAgendamentoConsulta dados) throws ValidacaoException {
        LocalDateTime dataConsulta = dados.data();
        LocalDateTime agora = LocalDateTime.now();
        Long diferencaEmMinutos = Duration.between(agora, dataConsulta).toMinutes();

        if (diferencaEmMinutos < 30) {
            throw new ValidacaoException("Consulta deve ser agendada com antecedência mínima de 30 minutos");
        }
    }
}
@Component
public class ValidadorHorarioFuncionamentoClinica implements ValidadorAgendamentoDeConsulta {

    public void valida(DadosAgendamentoConsulta dados) throws ValidacaoException {
        LocalDateTime dataConsulta = dados.data();
        boolean domingo = dataConsulta.getDayOfWeek().equals(DayOfWeek.SUNDAY);
        boolean antesDaAberturaDaClinica = dataConsulta.getHour() < 7;
        boolean depoisDoEncerramentoDaClinica = dataConsulta.getHour() > 18;

        if (domingo || antesDaAberturaDaClinica || depoisDoEncerramentoDaClinica) {
            throw new ValidacaoException("Consulta fora do horário de funcionamento da clínica");
        }
    }

}
@Component
public class ValidadorMedicoAtivo implements ValidadorAgendamentoDeConsulta {

    @Autowired
    private MedicoRepository repository;

    public void valida(DadosAgendamentoConsulta dados) throws ValidacaoException {
        if (dados.idMedico() == null) {
            return;
        }

        boolean medicoEstaAtivo = repository.findAtivoById(dados.idMedico());
        if (!medicoEstaAtivo) {
            throw new ValidacaoException("Consulta não pode ser agendada com médico excluído");
        }
    }

}
@Component
public class ValidadorMedicoComOutraConsultaNoMesmoHorario implements ValidadorAgendamentoDeConsulta {
    
    @Autowired
    private ConsultaRepository repository;

    public void valida(DadosAgendamentoConsulta dados) throws ValidacaoException {
        boolean medicoPossuiOutraConsultaNoMesmoHorario = repository.existsByMedicoIdAndData(dados.idMedico(),
                dados.data());

        if (medicoPossuiOutraConsultaNoMesmoHorario) {
            throw new ValidacaoException("Médico já possui outra consulta agendada nesse mesmo horário");
        }
    }

}
@Component
public class ValidadorPacienteAtivo implements ValidadorAgendamentoDeConsulta {

    @Autowired
    private PacienteRepository repository;

    public void valida(DadosAgendamentoConsulta dados) throws ValidacaoException {
        boolean pacienteEstaAtivo = repository.findAtivoById(dados.idPaciente());
        if (!pacienteEstaAtivo) {
            throw new ValidacaoException("Consulta não pode ser agendada com paciente excluído");
        }
    }

}
@Component
public class ValidadorPacienteSemOutraConsultaNoDia implements ValidadorAgendamentoDeConsulta {

    @Autowired
    private ConsultaRepository repository;

    public void valida(DadosAgendamentoConsulta dados) throws ValidacaoException {
        LocalDateTime primeiroHorario = dados.data().withHour(7);
        LocalDateTime ultimoHorario = dados.data().withHour(18);
        boolean pacientePossuiOutraConsultaNoDia = repository.existsByPacienteIdAndDataBetween(dados.idPaciente(),
                primeiroHorario, ultimoHorario);

        if (pacientePossuiOutraConsultaNoDia) {
            throw new ValidacaoException("Paciente já possui uma consulta agendada nesse dia");
        }
    }

}

Oi!

O try/catch que você colocou trata o erro e com isso a aplicação segue o fluxo normal após as validações serem executadas.

Se retiro o try/catch, aponta o erro 'Unhandled exception type ValidacaoException'.

solução!

Verifica se a sua classe ValidacaoException está herdando de RuntimeException

Estava herdando de Exception, então troquei pra RuntimeException e não apontou mais o erro. Poderia me explicar o motivo, por favor, Rodrigo?

Exception é checked e obriga um try/catch ou throws na assinatura do método. RuntimeException é unchecked e não precisa tratar. Mais detalhes: https://cursos.alura.com.br/course/java-consumindo-api-gravando-arquivos-lidando-erros/task/126931