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?
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?
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();
    }
}
        Na sua classe Consulta o atributo se chama motivo, então na query da interface MedicoRepository você deve ajustar.
Funcionou obrgado professor!!