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

[Dúvida] Delete no controller

Oi professor, a minha duvida é em relaçaõa a criacao de um delete no controller da consulta como tnha no medico ou paciente controller por exemplo. Eu fiz desse jeito mas voce acha que é mais simples do jeito como a esta a resposta?

8 respostas

Oi!

Acho que faltou o seu código na mensagem.

package med.absolut.api.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import med.absolut.api.consulta.AgendaConsulta;
import med.absolut.api.consulta.CancelamentoConsulta;
import med.absolut.api.consulta.ConsultaRepository;
import med.absolut.api.consulta.DadosAgendamento;
import med.absolut.api.consulta.DadosCancelamento;

@RestController
@RequestMapping("/consultas")
public class ConsultaController {

    @Autowired 
    private AgendaConsulta agendaConsulta; 
    
    @Autowired
    private CancelamentoConsulta cancelamentoConsulta;
    
    @PostMapping
    @Transactional
    public ResponseEntity agendar(@RequestBody @Valid DadosAgendamento dados) {
        var dto = agendaConsulta.agendar(dados);
        return ResponseEntity.ok(dto);
    }
    
    @DeleteMapping("/{id}")
    @Transactional
    public ResponseEntity cancelar(DadosCancelamento dados) {
        var c = cancelamentoConsulta.cancelar(dados.idConsulta());
        return ResponseEntity.noContent().build();
    }
}
package med.absolut.api.consulta;

import jakarta.validation.constraints.NotNull;

public record DadosCancelamento(
        
        @NotNull
        Long idConsulta, 
        
        @NotNull
        MotivoCancelamento motivo
        
        ) {

    public boolean existsById(@NotNull Long idConsulta) {
        return false;
    }
}
package med.absolut.api.consulta;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import med.absolut.api.consulta.validacoes.cancelamento.ValidadorCancelamento;
import med.absolut.api.infra.exception.ValidacaoException;

@Service
public class CancelamentoConsulta {
    
    @Autowired
    private ConsultaRepository consultaRepository;
    
    @Autowired
    private List<ValidadorCancelamento> validadoresCancelamento;
    
    public void cancelar(DadosCancelamento cancelamento) {

        if (!cancelamento.existsById(cancelamento.idConsulta())) {
            throw new ValidacaoException("Consulta já está cancelada");
        }

        validadoresCancelamento.forEach(v -> v.validar(cancelamento));
        
        var c = consultaRepository.getReferenceById(cancelamento.idConsulta());
    }
}
package med.absolut.api.consulta.validacoes.cancelamento;

import java.time.Duration;
import java.time.LocalDateTime;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import med.absolut.api.consulta.ConsultaRepository;
import med.absolut.api.consulta.DadosCancelamento;
import med.absolut.api.infra.exception.ValidacaoException;

@Component
public class ValidadorHorarioAtecidencaCancelamento implements ValidadorCancelamento {

    @Autowired
    private ConsultaRepository repository;
    
    @Override
    public void validar(DadosCancelamento dados) {

        var consulta = repository.getReferenceById(dados.idConsulta());
        var agora = LocalDateTime.now();
        var diferencaEmHoras = Duration.between(agora, consulta.getData()).toHours();
    
        if(diferencaEmHoras < 24){
        throw new ValidacaoException("Consulta somente pode ser cancelada com antecedência mínima de 24h!");
    }
  }
}
package med.absolut.api.consulta.validacoes.cancelamento;

import med.absolut.api.consulta.DadosCancelamento;

public interface ValidadorCancelamento {

    void validar(DadosCancelamento dados);
}

Assim está ocodigo mas estou tndo um problema no controller em relação ao metodo cancelar, esta é a menssagem: "The method cancelar(DadosCancelamento) in the type CancelamentoConsulta is not applicable for the arguments (Long)"

O problema é no seu método cancelar do controller, que está passando como parâmetro apenas o id da consulta ao invés do objeto dados:

@DeleteMapping("/{id}")
@Transactional
public ResponseEntity cancelar(DadosCancelamento dados) {
    var c = cancelamentoConsulta.cancelar(dados.idConsulta());
    return ResponseEntity.noContent().build();
}

Altere para:

@DeleteMapping("/{id}")
@Transactional
public ResponseEntity cancelar(DadosCancelamento dados) {
    cancelamentoConsulta.cancelar(dados);
    return ResponseEntity.noContent().build();
}

professor eu fiz isso e alguns ajustes, mas estou recebendo este erro:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'agendaConsulta': Unsatisfied dependency expressed through field 'medicoRepository': Error creating bean with name 'medicoRepository' defined in med.absolut.api.medico.MedicoRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract med.absolut.api.medico.Medico med.absolut.api.medico.MedicoRepository.escolherMedicoAleatoriamente(med.absolut.api.medico.Especialidades,java.time.LocalDateTime); Reason: Validation failed for query for method public abstract med.absolut.api.medico.Medico med.absolut.api.medico.MedicoRepository.escolherMedicoAleatoriamente(med.absolut.api.medico.Especialidades,java.time.LocalDateTime)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'medicoRepository' defined in med.absolut.api.medico.MedicoRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract med.absolut.api.medico.Medico med.absolut.api.medico.MedicoRepository.escolherMedicoAleatoriamente(med.absolut.api.medico.Especialidades,java.time.LocalDateTime); Reason: Validation failed for query for method public abstract med.absolut.api.medico.Medico med.absolut.api.medico.MedicoRepository.escolherMedicoAleatoriamente(med.absolut.api.medico.Especialidades,java.time.LocalDateTime)
Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract med.absolut.api.medico.Medico med.absolut.api.medico.MedicoRepository.escolherMedicoAleatoriamente(med.absolut.api.medico.Especialidades,java.time.LocalDateTime); Reason: Validation failed for query for method public abstract med.absolut.api.medico.Medico med.absolut.api.medico.MedicoRepository.escolherMedicoAleatoriamente(med.absolut.api.medico.Especialidades,java.time.LocalDateTime)
Caused by: java.lang.IllegalArgumentException: org.hibernate.query.sqm.UnknownPathException: Could not resolve attribute 'motivoCancelamento' of 'med.absolut.api.consulta.Consulta' [select m from Medico m where m.ativo = true and m.especialidade = :especialidade and m.id not in (
         select c.medico.id from Consulta c where c.data = :data and c.motivoCancelamento is null)
         order by rand()
]
Caused by: org.hibernate.query.sqm.UnknownPathException: Could not resolve attribute 'motivoCancelamento' of 'med.absolut.api.consulta.Consulta' [select m from Medico m where m.ativo = true and m.especialidade = :especialidade and m.id not in (
         select c.medico.id from Consulta c where c.data = :data and c.motivoCancelamento is null)
         order by rand()
]
Caused by: org.hibernate.query.sqm.PathElementException: Could not resolve attribute 'motivoCancelamento' of 'med.absolut.api.consulta.Consulta'

Está dando erro dizendo que na sua classe Consulta não tem o atributo motivoCancelamento

Professor eu fiz estas alterações porem ainda ets adando erro

package med.absolut.api.consulta;

import java.time.LocalDateTime;

import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import med.absolut.api.medico.Medico;
import med.absolut.api.paciente.Paciente;

@Table(name = "consultas")
@Entity(name = "Consulta")
@Getter
@NoArgsConstructor
@EqualsAndHashCode(of = "id")
public class Consulta {

    public Consulta(Long id, Medico medico, Paciente paciente, LocalDateTime data) {
        this.id = id;
        this.medico = medico;
        this.paciente = paciente;
        this.data = data;
    }

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "medico_id")
    private Medico medico;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "paciente_id")
    private Paciente paciente;
    
    private LocalDateTime data;
    
    @Enumerated(EnumType.STRING)
    private MotivoCancelamento motivo;
    
    public void cancelar(MotivoCancelamento motivoCancelamento) {
        this.motivo = motivoCancelamento;
    }


}
package med.absolut.api.consulta;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import med.absolut.api.consulta.validacoes.cancelamento.ValidadorCancelamento;
import med.absolut.api.infra.exception.ValidacaoException;

@Service
public class CancelamentoConsulta {
    
    @Autowired
    private ConsultaRepository consultaRepository;
    
    @Autowired
    private List<ValidadorCancelamento> validadoresCancelamento;
    
    public void cancelar(DadosCancelamento cancelamento) {

        if (!cancelamento.existsById(cancelamento.idConsulta())) {
            throw new ValidacaoException("Consulta já está cancelada");
        }

        validadoresCancelamento.forEach(v -> v.validar(cancelamento));
        
        var c = consultaRepository.getReferenceById(cancelamento.idConsulta());

        c.cancelar(cancelamento.motivo());
        consultaRepository.save(c);
    }
}
package med.absolut.api.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import med.absolut.api.consulta.AgendaConsulta;
import med.absolut.api.consulta.CancelamentoConsulta;
import med.absolut.api.consulta.DadosAgendamento;
import med.absolut.api.consulta.DadosCancelamento;

@RestController
@RequestMapping("/consultas")
public class ConsultaController {

    @Autowired 
    private AgendaConsulta agendaConsulta; 
    
    @Autowired
    private CancelamentoConsulta cancelamentoConsulta;
    
    @PostMapping
    @Transactional
    public ResponseEntity agendar(@RequestBody @Valid DadosAgendamento dados) {
        var dto = agendaConsulta.agendar(dados);
        return ResponseEntity.ok(dto);
    }
    
    @DeleteMapping("/{id}")
    @Transactional
    public ResponseEntity cancelar(@RequestBody @Valid DadosCancelamento dados) {
        cancelamentoConsulta.cancelar(dados);
        return ResponseEntity.noContent().build();
    }
}
solução!

Na sua classe Consulta o atributo se chama motivo, então na query da interface MedicoRepository você deve ajustar.

Funcionou obrgado professor!!