diff --git a/.github/workflows/ci-develop.yml b/.github/workflows/ci-develop.yml new file mode 100644 index 0000000..ba2f8ec --- /dev/null +++ b/.github/workflows/ci-develop.yml @@ -0,0 +1,26 @@ +name: CI Develop + +on: + push: + branches: [ "develop" ] + pull_request: + branches: [ "develop" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + - name: Run Maven verify (tests + Spotless + SpotBugs) + run: mvn spotless:apply && mvn -B clean verify + working-directory: ./VemProFutApi diff --git a/.github/workflows/cicd-main.yml b/.github/workflows/cicd-main.yml new file mode 100644 index 0000000..2d79829 --- /dev/null +++ b/.github/workflows/cicd-main.yml @@ -0,0 +1,47 @@ +name: CI/CD Main (Prod) + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + + - name: Run Maven verify (tests + Spotless + SpotBugs) + run: mvn spotless:apply && mvn -B clean verify + working-directory: ./VemProFutApi + + docker: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + + - name: Build Docker image + run: docker build -t vemprofut-api:latest ./VemProFutApi + + - name: Tag Docker image + run: docker tag vemprofut-api:latest ${{ secrets.DOCKER_USERNAME }}/vemprofut-api:latest + + - name: Push Docker image + run: docker push ${{ secrets.DOCKER_USERNAME }}/vemprofut-api:latest + + diff --git a/Diagramas/Fluxograma_BPMN/criarListPartida.png b/Diagramas/Fluxograma_BPMN/criarListPartida.png new file mode 100644 index 0000000..9a2f0f9 Binary files /dev/null and b/Diagramas/Fluxograma_BPMN/criarListPartida.png differ diff --git a/VemProFutApi/pom.xml b/VemProFutApi/pom.xml index 4b6561f..49ef2cb 100644 --- a/VemProFutApi/pom.xml +++ b/VemProFutApi/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.7 + 3.4.0 br.com.vemprofut @@ -85,6 +85,7 @@ org.flywaydb flyway-core + 10.20.0 diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/VemProFutApplication.java b/VemProFutApi/src/main/java/br/com/vemprofut/VemProFutApplication.java index 6ea00f4..31f9621 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/VemProFutApplication.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/VemProFutApplication.java @@ -4,8 +4,10 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication +@EnableAsync public class VemProFutApplication { private static final Logger log = LoggerFactory.getLogger(VemProFutApplication.class); diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/configs/AsyncConfig.java b/VemProFutApi/src/main/java/br/com/vemprofut/configs/AsyncConfig.java new file mode 100644 index 0000000..abd0c5b --- /dev/null +++ b/VemProFutApi/src/main/java/br/com/vemprofut/configs/AsyncConfig.java @@ -0,0 +1,22 @@ +package br.com.vemprofut.configs; + +import java.util.concurrent.Executor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +@EnableAsync +public class AsyncConfig { + @Bean(name = "defaultExecutor") + public Executor defaultExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(10); + executor.setMaxPoolSize(20); + executor.setQueueCapacity(100); + executor.setThreadNamePrefix("async-"); + executor.initialize(); + return executor; + } +} diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/configs/OAuth2LoginSuccessHandler.java b/VemProFutApi/src/main/java/br/com/vemprofut/configs/OAuth2LoginSuccessHandler.java index f4aa470..1d8adb2 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/configs/OAuth2LoginSuccessHandler.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/configs/OAuth2LoginSuccessHandler.java @@ -1,7 +1,6 @@ package br.com.vemprofut.configs; import br.com.vemprofut.mappers.IHistoricoPeladeiroMapper; -import br.com.vemprofut.models.DTOs.HistoricoPeladeiroDTO; import br.com.vemprofut.models.PeladeiroModel; import br.com.vemprofut.models.enuns.PeDominante; import br.com.vemprofut.repositories.PeladeiroRepository; @@ -56,20 +55,30 @@ public void onAuthenticationSuccess( if (usuario == null) { log.info("Usuario inesxistente, cadastrando novo usuario..."); - HistoricoPeladeiroDTO historicoPeladeiro = historicoPeladeiroService.create(); - usuario = new PeladeiroModel(); - usuario.setEmail(email); - usuario.setNome(name); - usuario.setApelido(name); - usuario.setDescricao("Usuário criado via OAuth2"); - usuario.setWhatsapp("000000000"); - usuario.setPeDominante(PeDominante.DESTRO); // escolha padrão - usuario.setAuthProvider(provider); - usuario.setFotoUrl(picture); - usuario.setHistoricoPeladeiro(historicoPeladeiroMapper.toModel(historicoPeladeiro)); - peladeiroRepository.save(usuario); - log.info("Usuário salvo no banco com ID {}", usuario.getId()); + historicoPeladeiroService + .create() + .thenAccept( + historicoPeladeiroDTO -> { + PeladeiroModel usuario2 = new PeladeiroModel(); + usuario2.setEmail(email); + usuario2.setNome(name); + usuario2.setApelido(name); + usuario2.setDescricao("Usuário criado via OAuth2"); + usuario2.setWhatsapp("000000000"); + usuario2.setPeDominante(PeDominante.DESTRO); // escolha padrão + usuario2.setAuthProvider(provider); + usuario2.setFotoUrl(picture); + usuario2.setHistoricoPeladeiro( + historicoPeladeiroMapper.toModel(historicoPeladeiroDTO)); + peladeiroRepository.save(usuario2); + log.info("Usuário salvo no banco com ID {}", usuario2.getId()); + }) + .exceptionally( + ex -> { + log.error("Erro ao criar histórico do peladeiro", ex); + return null; + }); } else { log.info("Usuario encontrado! ID: {}", usuario.getId()); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/controllers/FutController.java b/VemProFutApi/src/main/java/br/com/vemprofut/controllers/FutController.java index 59df0f1..4cc135f 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/controllers/FutController.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/controllers/FutController.java @@ -2,11 +2,11 @@ import br.com.vemprofut.controllers.request.*; import br.com.vemprofut.controllers.response.*; -import br.com.vemprofut.models.FutModel; import br.com.vemprofut.services.IFutService; import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.Valid; import java.util.List; +import java.util.concurrent.CompletableFuture; import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -26,37 +26,37 @@ public class FutController { @Operation( summary = "Cadastra um novo Fut", tags = {"FutController - CRUD Básico"}) - public ResponseEntity create( + public CompletableFuture> create( @Valid @RequestBody final SaveFutRequestDTO requestDTO) { - var response = futService.create(requestDTO); - return ResponseEntity.status(HttpStatus.CREATED).body(response); + return futService + .create(requestDTO) + .thenApply(obj -> ResponseEntity.status(HttpStatus.CREATED).body(obj)); } @GetMapping("{id}") @Operation( summary = "Busca um Fut pelo ID", tags = {"FutController - CRUD Básico"}) - public ResponseEntity findByFut(@PathVariable final Long id) { - return ResponseEntity.ok(futService.findById(id)); + public CompletableFuture> findByFut( + @PathVariable final Long id) { + return futService.findById(id).thenApply(v -> ResponseEntity.ok().build()); } @PutMapping("{id}") @Operation( summary = "Altera um Fut já cadastrado, informando o id", tags = {"FutController - CRUD Básico"}) - public ResponseEntity update( + public CompletableFuture> update( @PathVariable final Long id, UpdateFutRequestDTO dto) { - var obj = futService.update(id, dto); - return ResponseEntity.ok(obj); + return futService.update(id, dto).thenApply(obj -> ResponseEntity.ok(obj)); } @DeleteMapping("{id}") @Operation( summary = "Apaga um Fut por meio do id, cuidado! ", tags = {"FutController - CRUD Básico"}) - public ResponseEntity delete(@PathVariable final Long id) { - futService.delete(id); - return ResponseEntity.noContent().build(); + public CompletableFuture> delete(@PathVariable final Long id) { + return futService.delete(id).thenApply(v -> ResponseEntity.noContent().build()); } // =================== acoes partidas ======================= @@ -65,20 +65,26 @@ public ResponseEntity delete(@PathVariable final Long id) { @Operation( summary = "Criar uma nova partida...", tags = {"FutController - Ações Partidas"}) - public ResponseEntity criarPartida( + public CompletableFuture> criarPartida( @RequestBody SavePartidaRequestDTO requestDTO) { - FutModel futModel = futService.findByIdModel(requestDTO.futId()); - return ResponseEntity.status(HttpStatus.CREATED) - .body(futService.criarPartida(requestDTO, futModel)); + return futService + .findByIdModel(requestDTO.futId()) + .thenCompose( + futModel -> + futService + .criarPartida(requestDTO, futModel) + .thenApply(obj -> ResponseEntity.status(HttpStatus.CREATED).body(obj))); } @PostMapping("partidaslist") @Operation( summary = "Cria varias partidas de uma só vez, todas com resultados preenchidos", tags = {"FutController - Ações Partidas"}) - public ResponseEntity> criarPartidasLista( + public CompletableFuture>> criarPartidasLista( @RequestBody List requestDTO) { - return ResponseEntity.status(HttpStatus.CREATED).body(futService.criarPartidasList(requestDTO)); + return futService + .criarPartidasList(requestDTO) + .thenApply(obj -> ResponseEntity.status(HttpStatus.CREATED).body(obj)); } // ================ lista peladeiro ===================== @@ -87,19 +93,22 @@ public ResponseEntity> criarPartidasLista( @Operation( summary = "Adiciona um peladeiro a lista de peladeiros cadastrado no fut", tags = {"FutController - Lista de Peladeiros"}) - public ResponseEntity adicionarPeladeiroLista( + public CompletableFuture> adicionarPeladeiroLista( @RequestBody AddPeladeiroInFutListRequestDTO addPeladeiroRequestDTO) { - futService.addPeladeiro(addPeladeiroRequestDTO); - return ResponseEntity.noContent().build(); + return futService + .addPeladeiro(addPeladeiroRequestDTO) + .thenApply(v -> ResponseEntity.noContent().build()); } @GetMapping("lista-peladeiros/{idFut}") @Operation( summary = "busca a lista de todos peldadeiros cadastrados no fut", tags = {"FutController - Lista de Peladeiros"}) - public ResponseEntity> listarPeladeirosCadastrados( + public CompletableFuture>> listarPeladeirosCadastrados( @PathVariable final Long idFut) { - return ResponseEntity.ok().body(futService.listarPeladeiroCadastradosFut(idFut)); + return futService + .listarPeladeiroCadastradosFut(idFut) + .thenApply(obj -> ResponseEntity.ok().body(obj)); } // =============== lista Editores =========================== @@ -108,20 +117,20 @@ public ResponseEntity> listarPeladeirosCadastrados( @Operation( summary = "Adiciona um Editor a lista de editores de um fut em especifico", tags = {"FutController - Lista de Editores do Fut"}) - public ResponseEntity adicionarEditorLista( + public CompletableFuture> adicionarEditorLista( @RequestBody AddEditorInFutListResquestDTO editor) { - futService.addEditor(editor); - return ResponseEntity.noContent().build(); + return futService.addEditor(editor).thenApply(v -> ResponseEntity.noContent().build()); } @GetMapping("lista-editores/{idFut}") @Operation( summary = "busca a lista de editores de um fut em especifico", tags = {"FutController - Lista de Editores do Fut"}) - public ResponseEntity> listarEditoresFut( + public CompletableFuture>> listarEditoresFut( @PathVariable final Long idFut) { - - return ResponseEntity.ok().body(futService.listarEditoresCadastradosFut(idFut)); // TODO:testar + return futService + .listarEditoresCadastradosFut(idFut) + .thenApply(obj -> ResponseEntity.ok().body(obj)); } // ================= upload arquivos fotos ================== @@ -130,10 +139,11 @@ public ResponseEntity> listarEditoresFut( @Operation( summary = "Para enviar a foto de capa do Fut", tags = {"FutController - Upload de Imagens"}) - public ResponseEntity uploadFotoFut( + public CompletableFuture> uploadFotoFut( @PathVariable Long id, @RequestPart("file") MultipartFile file) { - futService.atualizarFotoCapa(id, file); - return ResponseEntity.ok("Foto de capa Salva!"); + return futService + .atualizarFotoCapa(id, file) + .thenApply(obj -> ResponseEntity.ok("Foto de capa Salva!")); } // ======================== Banimentos ======================= @@ -142,27 +152,28 @@ public ResponseEntity uploadFotoFut( @Operation( summary = "Adicionando um peladeiro da lista para o banimento", tags = {"FutController - Banimento no Fut"}) - public ResponseEntity adicionarBanimento(@RequestBody SaveBanimentoRequestDTO dto) { - futService.addBanimentoList(dto); - return ResponseEntity.noContent().build(); + public CompletableFuture> adicionarBanimento( + @RequestBody SaveBanimentoRequestDTO dto) { + return futService.addBanimentoList(dto).thenApply(v -> ResponseEntity.noContent().build()); } @GetMapping("lista-banidos/{idFut}") @Operation( summary = "Busca a lista de Banidos do Fut em questao", tags = {"FutController - Banimento no Fut"}) - public ResponseEntity> buscarListaBanidos( + public CompletableFuture>> buscarListaBanidos( @PathVariable Long idFut) { - return ResponseEntity.ok().body(futService.findAllBanidos(idFut)); + return futService.findAllBanidos(idFut).thenApply(obj -> ResponseEntity.ok().body(obj)); } @DeleteMapping("delete-banimento/{idFut}/{idPeladeiro}") @Operation( summary = "retira um peladeiro da lista de banidos", tags = {"FutController - Banimento no Fut"}) - public ResponseEntity retirandoBanimento( + public CompletableFuture> retirandoBanimento( @PathVariable Long idFut, @PathVariable Long idPeladeiro) { - futService.removeBanido(idPeladeiro, idFut); - return ResponseEntity.noContent().build(); + return futService + .removeBanido(idPeladeiro, idFut) + .thenApply(v -> ResponseEntity.noContent().build()); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/controllers/PeladeiroController.java b/VemProFutApi/src/main/java/br/com/vemprofut/controllers/PeladeiroController.java index 0e7e4f7..2d14343 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/controllers/PeladeiroController.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/controllers/PeladeiroController.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.Valid; import java.io.IOException; +import java.util.concurrent.CompletableFuture; import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -26,47 +27,48 @@ public class PeladeiroController { @Operation( summary = "Cadastra um novo peladeiro", tags = {"PeladeiroController"}) - public ResponseEntity create( + public CompletableFuture> create( @Valid @RequestBody final SavePeladeiroRequestDTO requestDTO) { - var obj = peladeiroService.create(requestDTO); - return ResponseEntity.status(HttpStatus.CREATED).body(obj); + + return peladeiroService + .create(requestDTO) + .thenApply(obj -> ResponseEntity.status(HttpStatus.CREATED).body(obj)); } @GetMapping("{id}") @Operation( summary = "Busca um Peladeiro pelo id", tags = {"PeladeiroController"}) - public ResponseEntity findById(@PathVariable final Long id) { - var obj = peladeiroService.findById(id); - return ResponseEntity.ok(obj); + public CompletableFuture> findById( + @PathVariable final Long id) { + return peladeiroService.findById(id).thenApply(ResponseEntity::ok); } @PutMapping("{id}") @Operation( summary = "Faz alteraçoes no Peladeiro cujo id é informado.", tags = {"PeladeiroController"}) - public ResponseEntity update( + public CompletableFuture> update( @PathVariable final Long id, @Valid @RequestBody UpdatePeladeiroRequestDTO dto) { - peladeiroService.update(id, dto); - return ResponseEntity.noContent().build(); + return peladeiroService.update(id, dto).thenApply(obj -> ResponseEntity.noContent().build()); } @DeleteMapping("{id}") @Operation( summary = "Deleta o peladeiro cujo id foi informado. Cuidado!", tags = {"PeladeiroController"}) - public ResponseEntity delete(@PathVariable final Long id) { - peladeiroService.delete(id); - return ResponseEntity.noContent().build(); + public CompletableFuture> delete(@PathVariable final Long id) { + return peladeiroService.delete(id).thenApply(obj -> ResponseEntity.noContent().build()); } @PostMapping(value = "uploadFoto/{id}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @Operation( summary = "Caso nao logado pelo gmail, enviar a foto do perfil", tags = {"PeladeiroController"}) - public ResponseEntity uploadFotoPeladeiro( + public CompletableFuture> uploadFotoPeladeiro( @PathVariable Long id, @RequestPart("file") MultipartFile file) throws IOException { - peladeiroService.atualizarFoto(id, file); - return ResponseEntity.ok("Foto salva!"); + return peladeiroService + .atualizarFoto(id, file) + .thenApply(obj -> ResponseEntity.ok("Foto salva!")); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/mappers/IMappersDefault.java b/VemProFutApi/src/main/java/br/com/vemprofut/mappers/IMappersDefault.java index b848a69..c0e268b 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/mappers/IMappersDefault.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/mappers/IMappersDefault.java @@ -87,7 +87,7 @@ default Long mapIdGols(EditorModel editor) { // Converte ID tipo Long para EditorModel default EditorModel mapEditor(Long id) { IEditorService service = new EditorService(); - return service.findByIdModel(id); + return service.findByIdModel(id).join(); } // ======================FUT====================== @@ -100,7 +100,7 @@ default Long mapIdFut(FutModel fut) { // Converte ID tipo Long para FutModel default FutModel mapFut(Long id) { IFutService service = new FutService(); - return service.findByIdModel(id); + return service.findByIdModel(id).join(); } // ===========================GOLS================= @@ -139,7 +139,7 @@ default Long mapIdHistoricoPeladeiro(HistoricoPeladeiroModel historico) { // Converte ID tipo Long para HistoricoPeladeiroModel default HistoricoPeladeiroModel mapHistoricoPeladeiro(Long id) { IHistoricoPeladeiroService service = new HistoricoPeladeiroService(); - return service.findByIdModel(id); + return service.findByIdModel(id).join(); } // ============================PARTIDAS=========================== @@ -152,7 +152,7 @@ default Long mapIdPartidas(PartidasModel partida) { // Converte ID tipo Long para PartidasModel default PartidasModel mapPartidas(Long id) { IPartidasService service = new PartidasService(); - return service.findByIdModel(id); + return service.findByIdModel(id).join(); } // =========================PELADEIRO========================= @@ -170,7 +170,7 @@ default Long mapIdPartidas(PeladeiroModel peladeiro) { // Converte ID tipo Long para PeladeiroModel default PeladeiroModel mapPeladeiro(Long id) { IPeladeiroService service = new PeladeiroService(); - return service.findByIdModel(id); + return service.findByIdModel(id).join(); } default PeladeiroResponseDTO mapModelToResponse(PeladeiroModel model) { diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/IBanimentoService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/IBanimentoService.java index b5d71cc..b988598 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/IBanimentoService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/IBanimentoService.java @@ -4,11 +4,12 @@ import br.com.vemprofut.controllers.response.BanimentoDetailsResponseDTO; import br.com.vemprofut.controllers.response.SaveBanimentoResponseDTO; import java.util.List; +import java.util.concurrent.CompletableFuture; public interface IBanimentoService { - SaveBanimentoResponseDTO create(SaveBanimentoRequestDTO dto); + CompletableFuture create(SaveBanimentoRequestDTO dto); - List findAll(Long idFut); + CompletableFuture> findAll(Long idFut); - void delete(Long idPeladeiro); + CompletableFuture delete(Long idPeladeiro); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/ICartoesService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/ICartoesService.java index 3b67133..1037680 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/ICartoesService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/ICartoesService.java @@ -4,24 +4,25 @@ import br.com.vemprofut.models.CartoesModel; import br.com.vemprofut.models.DTOs.CartoesDTO; import java.util.List; +import java.util.concurrent.CompletableFuture; public interface ICartoesService { - CartoesDTO create(CartoesDTO dto); + CompletableFuture create(CartoesDTO dto); - List findByPeladeiro(Long id); + CompletableFuture> findByPeladeiro(Long id); - List findByPartida(Long id); + CompletableFuture> findByPartida(Long id); - List findByFut(Long id); + CompletableFuture> findByFut(Long id); - List findAll(); + CompletableFuture> findAll(); - CartoesDTO findById(Long id); + CompletableFuture findById(Long id); - CartoesModel findByIdModel(Long id); + CompletableFuture findByIdModel(Long id); - CartoesResumoResponseDTO contarCartoesPeladeiro(Long peladeiroId); + CompletableFuture contarCartoesPeladeiro(Long peladeiroId); - CartoesResumoResponseDTO contarCartoesFut(Long futId); + CompletableFuture contarCartoesFut(Long futId); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/IEditorService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/IEditorService.java index ad8ad7f..121dcf5 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/IEditorService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/IEditorService.java @@ -4,16 +4,17 @@ import br.com.vemprofut.models.DTOs.FutDTO; import br.com.vemprofut.models.EditorModel; import java.util.List; +import java.util.concurrent.CompletableFuture; public interface IEditorService { - EditorModel create(EditorModel dto); + CompletableFuture create(EditorModel dto); - EditorDTO findById(Long id); + CompletableFuture findById(Long id); - EditorModel findByIdModel(Long id); + CompletableFuture findByIdModel(Long id); - List findAll(FutDTO futDTO); + CompletableFuture> findAll(FutDTO futDTO); - void delete(Long id); + CompletableFuture delete(Long id); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/IFutService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/IFutService.java index 6b8724d..2656bf5 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/IFutService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/IFutService.java @@ -5,41 +5,44 @@ import br.com.vemprofut.models.DTOs.FutDTO; import br.com.vemprofut.models.FutModel; import java.util.List; +import java.util.concurrent.CompletableFuture; import org.springframework.web.multipart.MultipartFile; public interface IFutService { - SaveFutResponseDTO create(SaveFutRequestDTO dto); + CompletableFuture create(SaveFutRequestDTO dto); - FutDetailsResponse findById(Long id); + CompletableFuture findById(Long id); - FutModel findByIdModel(Long id); + CompletableFuture findByIdModel(Long id); - FutDTO findByNome(String nome); + CompletableFuture findByNome(String nome); - List findAll(); + CompletableFuture> findAll(); - UpdateFutResponseDTO update(Long id, UpdateFutRequestDTO dto); + CompletableFuture update(Long id, UpdateFutRequestDTO dto); - void delete(Long id); + CompletableFuture delete(Long id); - SavePartidasResponseDTO criarPartida(SavePartidaRequestDTO requestDTO, FutModel futModel); + CompletableFuture criarPartida( + SavePartidaRequestDTO requestDTO, FutModel futModel); - void addPeladeiro(AddPeladeiroInFutListRequestDTO requestDTO); + CompletableFuture addPeladeiro(AddPeladeiroInFutListRequestDTO requestDTO); - List criarPartidasList(List requestDTOS); + CompletableFuture> criarPartidasList( + List requestDTOS); - List listarPeladeiroCadastradosFut(Long futId); + CompletableFuture> listarPeladeiroCadastradosFut(Long futId); - void addEditor(AddEditorInFutListResquestDTO resquestDTO); + CompletableFuture addEditor(AddEditorInFutListResquestDTO resquestDTO); - List listarEditoresCadastradosFut(Long idFut); + CompletableFuture> listarEditoresCadastradosFut(Long idFut); - void atualizarFotoCapa(Long id, MultipartFile file); + CompletableFuture atualizarFotoCapa(Long id, MultipartFile file); - SaveBanimentoResponseDTO addBanimentoList(SaveBanimentoRequestDTO dto); + CompletableFuture addBanimentoList(SaveBanimentoRequestDTO dto); - List findAllBanidos(Long idFut); + CompletableFuture> findAllBanidos(Long idFut); - void removeBanido(Long idPeladeiro, Long idFut); + CompletableFuture removeBanido(Long idPeladeiro, Long idFut); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/IHistoricoPeladeiroService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/IHistoricoPeladeiroService.java index 10150b8..3c0dd98 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/IHistoricoPeladeiroService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/IHistoricoPeladeiroService.java @@ -2,16 +2,17 @@ import br.com.vemprofut.models.DTOs.HistoricoPeladeiroDTO; import br.com.vemprofut.models.HistoricoPeladeiroModel; +import java.util.concurrent.CompletableFuture; public interface IHistoricoPeladeiroService { - HistoricoPeladeiroDTO create(); + CompletableFuture create(); - HistoricoPeladeiroDTO findById(Long id); + CompletableFuture findById(Long id); - HistoricoPeladeiroModel findByIdModel(Long id); + CompletableFuture findByIdModel(Long id); - HistoricoPeladeiroDTO update(Long id, HistoricoPeladeiroDTO dto); + CompletableFuture update(Long id, HistoricoPeladeiroDTO dto); - void delete(Long id); + CompletableFuture delete(Long id); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/IPartidasService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/IPartidasService.java index a7a7d5c..05523a5 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/IPartidasService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/IPartidasService.java @@ -6,18 +6,20 @@ import br.com.vemprofut.models.DTOs.PeladeiroDTO; import br.com.vemprofut.models.FutModel; import br.com.vemprofut.models.PartidasModel; +import java.util.concurrent.CompletableFuture; public interface IPartidasService { - SavePartidasResponseDTO create(SavePartidaRequestDTO requestDTO, FutModel futModel); + CompletableFuture create( + SavePartidaRequestDTO requestDTO, FutModel futModel); - PartidasDTO findById(Long id); + CompletableFuture findById(Long id); - PartidasModel findByIdModel(Long id); + CompletableFuture findByIdModel(Long id); - void addGols(PeladeiroDTO peladeiroDTO, PartidasDTO partidasDTO); + CompletableFuture addGols(PeladeiroDTO peladeiroDTO, PartidasDTO partidasDTO); - void addPeladeiros(Long peladeiroId, PartidasDTO partidasDTO); + CompletableFuture addPeladeiros(Long peladeiroId, PartidasDTO partidasDTO); - void addCartoes(Long cartaoId, PartidasDTO partidasDTO); + CompletableFuture addCartoes(Long cartaoId, PartidasDTO partidasDTO); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/IPeladeiroService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/IPeladeiroService.java index e1366f5..2307de4 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/IPeladeiroService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/IPeladeiroService.java @@ -6,21 +6,22 @@ import br.com.vemprofut.controllers.response.SavePeladeiroResponseDTO; import br.com.vemprofut.controllers.response.UpdatePeladeiroResponseDTO; import br.com.vemprofut.models.PeladeiroModel; +import java.util.concurrent.CompletableFuture; import org.springframework.web.multipart.MultipartFile; public interface IPeladeiroService { - SavePeladeiroResponseDTO create(SavePeladeiroRequestDTO dto); + CompletableFuture create(SavePeladeiroRequestDTO dto); - UpdatePeladeiroResponseDTO update(Long id, UpdatePeladeiroRequestDTO dto); + CompletableFuture update(Long id, UpdatePeladeiroRequestDTO dto); - PeladeiroDetailResponse findById(Long id); + CompletableFuture findById(Long id); - PeladeiroModel findByIdModel(Long id); + CompletableFuture findByIdModel(Long id); - // List findAll(); + // CompletableFuture> findAll(); - void delete(Long id); + CompletableFuture delete(Long id); - void atualizarFoto(Long id, MultipartFile file); + CompletableFuture atualizarFoto(Long id, MultipartFile file); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/BanimentoService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/BanimentoService.java index 3dbbf95..76d3f99 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/BanimentoService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/BanimentoService.java @@ -13,7 +13,9 @@ import br.com.vemprofut.services.IBanimentoService; import br.com.vemprofut.services.query.IBanimentoQueryService; import java.util.List; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service @@ -29,7 +31,7 @@ public class BanimentoService implements IBanimentoService { @Autowired private FutRepository futRepository; - public SaveBanimentoResponseDTO create(SaveBanimentoRequestDTO dto) { + public CompletableFuture create(SaveBanimentoRequestDTO dto) { banimentoQueryService.verifyPeladeiroBanidoExist(dto.fut(), dto.peladeiro()); // Já foi verificado em FutService se Fut e Peladeiro existem... entao é só buscar @@ -43,16 +45,20 @@ public SaveBanimentoResponseDTO create(SaveBanimentoRequestDTO dto) { banimentoModel.setDataBanimento(dto.dataBaninimento()); banimentoModel.setDataFimBanimento(dto.dataFimBanimento()); - return banimentoMapper.toSaveResponse(repository.save(banimentoModel)); + return CompletableFuture.completedFuture( + banimentoMapper.toSaveResponse(repository.save(banimentoModel))); } @Override - public List findAll(Long idFut) { - return banimentoQueryService.verifyExistListBanido(idFut); + @Async + public CompletableFuture> findAll(Long idFut) { + return CompletableFuture.completedFuture(banimentoQueryService.verifyExistListBanido(idFut)); } @Override - public void delete(Long idPeladeiro) { + public CompletableFuture delete(Long idPeladeiro) { + repository.deleteById(idPeladeiro); + return CompletableFuture.completedFuture(null); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/CartoesService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/CartoesService.java index 12e16e6..43845bb 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/CartoesService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/CartoesService.java @@ -7,9 +7,6 @@ import br.com.vemprofut.models.CartoesModel; import br.com.vemprofut.models.DTOs.CartaoCountProjection; import br.com.vemprofut.models.DTOs.CartoesDTO; -import br.com.vemprofut.models.FutModel; -import br.com.vemprofut.models.PartidasModel; -import br.com.vemprofut.models.PeladeiroModel; import br.com.vemprofut.repositories.CartoesRepository; import br.com.vemprofut.services.ICartoesService; import br.com.vemprofut.services.IFutService; @@ -17,7 +14,10 @@ import br.com.vemprofut.services.query.IPartidasQueryService; import br.com.vemprofut.services.query.IPeladeiroQueryService; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,65 +40,109 @@ public class CartoesService implements ICartoesService { @Autowired @Lazy private IFutService futService; + @Autowired + @Qualifier("defaultExecutor") + Executor executor; + + /* + Executor = uma forma diferente de tornar async + em vez de usar @Async("defaultExecutor"). + */ + @Override @Transactional - public CartoesDTO create(CartoesDTO dto) { - queryService.verifyEntitiesExist(dto); - - CartoesModel model = mapper.toModel(dto); - CartoesModel saved = repository.save(model); - return mapper.toDTO(saved); + public CompletableFuture create(CartoesDTO dto) { + return CompletableFuture.supplyAsync( + () -> { + queryService.verifyEntitiesExist(dto); + CartoesModel model = mapper.toModel(dto); + CartoesModel saved = repository.save(model); + return mapper.toDTO(saved); + }, + executor); } @Override @Transactional(readOnly = true) - public List findAll() { - return repository.findAll().stream().map(mapper::toDTO).toList(); + public CompletableFuture> findAll() { + return CompletableFuture.supplyAsync( + () -> { + return repository.findAll().stream().map(mapper::toDTO).toList(); + }, + executor); } @Override @Transactional(readOnly = true) - public CartoesDTO findById(Long id) { - - return mapper.toDTO(queryService.verityCartoesExist(id)); + public CompletableFuture findById(Long id) { + + return CompletableFuture.supplyAsync( + () -> { + var cartao = queryService.verityCartoesExist(id); + return mapper.toDTO(cartao); + }, + executor); } @Override @Transactional(readOnly = true) - public CartoesModel findByIdModel(Long id) { - - return queryService.verityCartoesExist(id); + public CompletableFuture findByIdModel(Long id) { + return CompletableFuture.supplyAsync( + () -> { + return queryService.verityCartoesExist(id); + }, + executor); } @Override @Transactional(readOnly = true) - public List findByPeladeiro(Long id) { - PeladeiroModel peladeiroModel = peladeiroQueryService.verifyPeladeiroExist(id); - return repository.findByPeladeiro(peladeiroModel).stream().map(mapper::toDTO).toList(); + public CompletableFuture> findByPeladeiro(Long id) { + /* PeladeiroModel peladeiroModel = peladeiroQueryService.verifyPeladeiroExist(id); + return CompletableFuture.completedFuture( <--- sincrono + repository.findByPeladeiro(peladeiroModel).stream().map(mapper::toDTO).toList()); + */ + // async + return peladeiroQueryService + .verifyPeladeiroExist(id) + .thenApply( + peladeiroModel -> + repository.findByPeladeiro(peladeiroModel).stream().map(mapper::toDTO).toList()); } @Override @Transactional(readOnly = true) - public List findByPartida(Long id) { - PartidasModel partidasModel = partidasQueryService.verifyPartidaExistWithRetorn(id); - return repository.findByPartida(partidasModel).stream().map(mapper::toDTO).toList(); + public CompletableFuture> findByPartida(Long id) { + return partidasQueryService + .verifyPartidaExistWithRetorn(id) + .thenApply( + partidasModel -> + repository.findByPartida(partidasModel).stream().map(mapper::toDTO).toList()); } @Override @Transactional(readOnly = true) - public List findByFut(Long id) { - FutModel futModel = futService.findByIdModel(id); - return repository.findByFut(futModel).stream().map(mapper::toDTO).toList(); + public CompletableFuture> findByFut(Long id) { + return futService + .findByIdModel(id) + .thenApply(futModel -> repository.findByFut(futModel).stream().map(mapper::toDTO).toList()); } - public CartoesResumoResponseDTO contarCartoesPeladeiro(Long peladeiroId) { - List resultados = repository.countByTipoAndPeladeiro(peladeiroId); - return montarResumo(resultados); + public CompletableFuture contarCartoesPeladeiro(Long peladeiroId) { + + return CompletableFuture.supplyAsync( + () -> { + List resultados = repository.countByTipoAndPeladeiro(peladeiroId); + return montarResumo(resultados); + }); } - public CartoesResumoResponseDTO contarCartoesFut(Long futId) { - List resultados = repository.countByTipoAndFut(futId); - return montarResumo(resultados); + public CompletableFuture contarCartoesFut(Long futId) { + + return CompletableFuture.supplyAsync( + () -> { + List resultados = repository.countByTipoAndFut(futId); + return montarResumo(resultados); + }); } private CartoesResumoResponseDTO montarResumo(List resultados) { @@ -111,7 +155,6 @@ private CartoesResumoResponseDTO montarResumo(List result case VERMELHO -> dto.setVermelho(proj.getQuantidade().intValue()); } } - return dto; } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/EditorService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/EditorService.java index 6869013..2bcc778 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/EditorService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/EditorService.java @@ -8,7 +8,9 @@ import br.com.vemprofut.services.IEditorService; import br.com.vemprofut.services.query.IEditorQueryService; import java.util.List; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -22,34 +24,54 @@ public class EditorService implements IEditorService { @Autowired private EditorRepository repository; @Override - public EditorModel create(EditorModel model) { - queryService.verityEditorExist(model); - return repository.save(model); + @Async("defaultExecutor") + @Transactional + public CompletableFuture create(EditorModel model) { + // queryService.verityEditorExist(model); ---> nao async + // return CompletableFuture.completedFuture(repository.save(model)); + + // Async + return CompletableFuture.supplyAsync( + () -> { + queryService.verityEditorExist(model); + return repository.save(model); + }); } @Override + @Async("defaultExecutor") @Transactional(readOnly = true) - public EditorDTO findById(Long id) { - return mapper.toDTO(queryService.verityEditorIdExistReturn(id)); + public CompletableFuture findById(Long id) { + return CompletableFuture.supplyAsync( + () -> mapper.toDTO(queryService.verityEditorIdExistReturn(id))); } @Override + @Async("defaultExecutor") @Transactional(readOnly = true) - public EditorModel findByIdModel(Long id) { - return queryService.verityEditorIdExistReturn(id); + public CompletableFuture findByIdModel(Long id) { + return CompletableFuture.supplyAsync(() -> queryService.verityEditorIdExistReturn(id)); } @Override + @Async("defaultExecutor") @Transactional(readOnly = true) - public List findAll(FutDTO futDTO) { - queryService.verityFutExist(futDTO); - - return repository.findByFutId(futDTO.id()).stream().map(mapper::toDTO).toList(); + public CompletableFuture> findAll(FutDTO futDTO) { + queryService.verityFutExist(futDTO); // sincrono + var response = + repository + .findByFutId(futDTO.id()) // sincrono + .stream() + .map(mapper::toDTO) + .toList(); + return CompletableFuture.completedFuture(response); } @Override - public void delete(Long id) { + @Async("defaultExecutor") + public CompletableFuture delete(Long id) { queryService.verityEditorIdExist(id); repository.deleteById(id); + return CompletableFuture.completedFuture(null); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/FutService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/FutService.java index 3aa0c5f..54aea4b 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/FutService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/FutService.java @@ -14,8 +14,10 @@ import br.com.vemprofut.services.query.IPeladeiroQueryService; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -58,256 +60,347 @@ public class FutService implements IFutService { @Override @Transactional - public SaveFutResponseDTO create(SaveFutRequestDTO dto) { + @Async("defaultExecutor") + public CompletableFuture create(SaveFutRequestDTO dto) { queryService.verifyNomeFutExist(dto.nome()); - var peladeiro = peladeiroQueryService.verifyPeladeiroExist(dto.administradorPeladeiro()); - - FutModel saved = repository.save(mapper.saveRequestToModel(dto)); - - HistoricoFutModel historico = historicoFutService.create(); - saved.setHistoricoFutId(historico); - saved.setAdministradorPeladeiro(peladeiro); - return mapper.toSaveResponse(repository.save(saved)); + return peladeiroQueryService + .verifyPeladeiroExist(dto.administradorPeladeiro()) + .thenApply( + peladeiroModel -> { + FutModel saved = repository.save(mapper.saveRequestToModel(dto)); + + HistoricoFutModel historico = historicoFutService.create(); + saved.setHistoricoFutId(historico); + saved.setAdministradorPeladeiro(peladeiroModel); + return mapper.toSaveResponse(repository.save(saved)); + }); } @Override @Transactional(readOnly = true) - public FutDetailsResponse findById(Long id) { - var futModel = queryService.verifyFutExistRetorn(id); - return mapper.modelToDetailsResponse(futModel); + @Async("defaultExecutor") + public CompletableFuture findById(Long id) { + return queryService + .verifyFutExistRetorn(id) + .thenApply(futModel -> mapper.modelToDetailsResponse(futModel)); } @Override @Transactional(readOnly = true) - public FutModel findByIdModel(Long id) { + @Async("defaultExecutor") + public CompletableFuture findByIdModel(Long id) { return queryService.verifyFutExistRetorn(id); } @Override @Transactional(readOnly = true) - public FutDTO findByNome(String nome) { - var futModel = queryService.verifyNomeFutExistRetorn(nome); - return mapper.toDTO(futModel); + @Async("defaultExecutor") + public CompletableFuture findByNome(String nome) { + return queryService + .verifyNomeFutExistRetorn(nome) + .thenApply(futModel -> mapper.toDTO(futModel)); } @Override @Transactional(readOnly = true) - public List findAll() { - return repository.findAll().stream().map(mapper::toDTO).toList(); + @Async("defaultExecutor") + public CompletableFuture> findAll() { + return CompletableFuture.completedFuture( + repository.findAll().stream().map(mapper::toDTO).toList()); } @Override @Transactional - public UpdateFutResponseDTO update(Long id, UpdateFutRequestDTO dto) { - var retorno = queryService.verifyFutExistRetorn(id); - - retorno.setJogadoresPorTime(dto.jogadoresPorTime()); - retorno.setTempoMaxPartida(dto.tempoMaxPartida()); - retorno.setMaxGolsVitoria(dto.maxGolsVitoria()); - - return mapper.modelToUpdateResponse(repository.save(retorno)); + @Async("defaultExecutor") + public CompletableFuture update(Long id, UpdateFutRequestDTO dto) { + return queryService + .verifyFutExistRetorn(id) + .thenApply( + futModel -> { + futModel.setJogadoresPorTime(dto.jogadoresPorTime()); + futModel.setTempoMaxPartida(dto.tempoMaxPartida()); + futModel.setMaxGolsVitoria(dto.maxGolsVitoria()); + + return mapper.modelToUpdateResponse(repository.save(futModel)); + }); } @Override @Transactional - public void delete(Long id) { + @Async("defaultExecutor") + public CompletableFuture delete(Long id) { queryService.verifyFutExistRetorn(id); repository.deleteById(id); + return CompletableFuture.completedFuture(null); } // ======================== acoes partidas ========================== @Override @Transactional - public SavePartidasResponseDTO criarPartida(SavePartidaRequestDTO requestDTO, FutModel futModel) { + @Async("defaultExecutor") + public CompletableFuture criarPartida( + SavePartidaRequestDTO requestDTO, FutModel futModel) { return partidasService.create(requestDTO, futModel); } @Override - @Transactional - public List criarPartidasList(List requestDTOS) { - - List partidaList = new ArrayList<>(); - - for (SavePartidaRequestDTO dto : requestDTOS) { - // 1 - criando partida - log.info("criando Partida..."); - PartidasModel partida = new PartidasModel(); - FutModel futModel = queryService.verifyFutExistRetorn(dto.futId()); - partida.setReservas(dto.reservas()); - partida.setFutId(futModel); - - // salvando partida para pegar o id. - partidasRepository.save(partida); - log.info("Partida criada, adicionando Cartao..."); - - // 2 - criando cartoes - if (dto.cartoes() != null) { - for (CartoesRequestDTO c : dto.cartoes()) { - CartoesModel cartoesModel = new CartoesModel(); - cartoesModel.setFut(queryService.verifyFutExistRetorn(dto.futId())); - cartoesModel.setTipoCartao(c.tipoCartao()); - cartoesModel.setPeladeiro(peladeiroQueryService.verifyPeladeiroExist(c.peladeiroId())); - cartoesModel.setPartida(partida); - - cartoesRepository.save(cartoesModel); - partida.getCartoes().add(cartoesModel); // pegar a lista para adicionar nela. - log.info("Cartao adicionado, Adicionando Gol "); - } - } - - // 3 - criando Gols - if (dto.gols() != null) { - for (GolsPartidaRequestDTO g : dto.gols()) { - GolsPartidaModel golsPartida = new GolsPartidaModel(); - golsPartida.setPeladeiro(peladeiroQueryService.verifyPeladeiroExist(g.peladeiro())); - golsPartida.setPartida(partida); - - golsRepository.save(golsPartida); - partida.getGolsPartida().add(golsPartida); - log.info("Gol adicionado, Adicionando Peladeiro"); - } - } - - // 4 - criando peladeiro - if (dto.peladeiros() != null) { - for (PeladeiroRequestDTO p : dto.peladeiros()) { - PeladeiroModel peladeiroModel = peladeiroQueryService.verifyPeladeiroExist(p.id()); - - // Para sincronizar a tabela intermédiaria da relacao @ManyToMany. - partida.getPeladeiros().add(peladeiroModel); - peladeiroModel - .getPartidas() - .add(partida); // Esse adiciona pa tabela: "esta_peladeiro_partidas". - - // para garantir que vai ser salvo. - peladeiroRepository.save( - peladeiroModel); // Esse salva em PeladeiroModel (que é onde a table intermediaria foi - // criada) - - log.info("Peladeiro adicionado"); - } - } - partidaList.add(partida); - } - return partidasMapper.toResponseList(partidaList); + @Async("defaultExecutor") + public CompletableFuture> criarPartidasList( + List requestDTOS) { + // dispara cada DTO em paralelo + List> futeres = + requestDTOS.stream() + .map(this::criarPartidasAsync) // cada DTO vira um future de PartidasModel + .toList(); + + return CompletableFuture.allOf(futeres.toArray(new CompletableFuture[0])) + .thenApply( + v -> + futeres.stream() + .map(CompletableFuture::join) // pega cada PartidasModel + .map(partidasMapper::toResponse) // transforma em DTO + .toList()); + } + + private CompletableFuture criarPartidasAsync(SavePartidaRequestDTO dto) { + PartidasModel partida = new PartidasModel(); + + return queryService + .verifyFutExistRetorn(dto.futId()) // <-- precisa retornar aqui + .thenCompose( + futModel -> { + partida.setReservas(dto.reservas()); + partida.setFutId(futModel); + partidasRepository.save(partida); + + // Cartões async + CompletableFuture cartoesFuture = + CompletableFuture.allOf( + dto.cartoes() == null + ? new CompletableFuture[0] + : dto.cartoes().stream() + .map( + c -> + peladeiroQueryService + .verifyPeladeiroExist(c.peladeiroId()) + .thenAccept( + peladeiroModel -> { + CartoesModel cartoesModel = new CartoesModel(); + cartoesModel.setFut(futModel); + cartoesModel.setTipoCartao(c.tipoCartao()); + cartoesModel.setPeladeiro(peladeiroModel); + cartoesModel.setPartida(partida); + cartoesRepository.save(cartoesModel); + partida.getCartoes().add(cartoesModel); + })) + .toArray(CompletableFuture[]::new)); + + // Gols async + CompletableFuture golsFuture = + CompletableFuture.allOf( + dto.gols() == null + ? new CompletableFuture[0] + : dto.gols().stream() + .map( + g -> + peladeiroQueryService + .verifyPeladeiroExist(g.peladeiro()) + .thenAccept( + peladeiroModel -> { + GolsPartidaModel golsPartidaModel = + new GolsPartidaModel(); + golsPartidaModel.setPeladeiro(peladeiroModel); + golsPartidaModel.setPartida(partida); + golsRepository.save(golsPartidaModel); + partida.getGolsPartida().add(golsPartidaModel); + })) + .toArray(CompletableFuture[]::new)); + + // Peladeiros async + CompletableFuture peladeirosFuture = + CompletableFuture.allOf( + dto.peladeiros() == null + ? new CompletableFuture[0] + : dto.peladeiros().stream() + .map( + p -> + peladeiroQueryService + .verifyPeladeiroExist(p.id()) + .thenAccept( + peladeiroModel -> { + peladeiroModel.addPartida(partida); + peladeiroRepository.save(peladeiroModel); + })) + .toArray(CompletableFuture[]::new)); + + // Espera todos os subtarefas terminarem + return CompletableFuture.allOf(cartoesFuture, golsFuture, peladeirosFuture) + .thenApply(v -> partida); + }); } // ======================== lista peladeiro ======================== @Override @Transactional - public void addPeladeiro(AddPeladeiroInFutListRequestDTO requestDTO) { - PeladeiroModel peladeiroModel = - peladeiroQueryService.verifyPeladeiroExist(requestDTO.peladeiroId()); - FutModel futModel = queryService.verifyFutExistRetorn(requestDTO.futId()); - queryService.verityPeladeiroInList(futModel, peladeiroModel); - log.info("Verificacao do Peladeiro e do Fut realizadas com sucesso! Salvando dados..."); - - futModel - .getPeladeiros() - .add(peladeiroModel); // Esse adiciona a tabela: "participa_peladeiro_fut". - repository.save( - futModel); // Esse salva em FutModel (que é onde a table intermediaria foi criada) + @Async("defaultExecutor") + public CompletableFuture addPeladeiro(AddPeladeiroInFutListRequestDTO requestDTO) { + return peladeiroQueryService + .verifyPeladeiroExist(requestDTO.peladeiroId()) + .thenCompose( + peladeiroModel -> + queryService + .verifyFutExistRetorn(requestDTO.futId()) + .thenCompose( + futModel -> + queryService + .verityPeladeiroInList(futModel, peladeiroModel) + .thenRun( + () -> { + log.info( + "Verificacao do Peladeiro e do Fut realizadas com sucesso! Salvando dados..."); + + futModel + .getPeladeiros() + .add(peladeiroModel); // Esse adiciona a tabela: + // "participa_peladeiro_fut". + repository.save( + futModel); // Esse salva em FutModel (que é onde a table + // intermediaria foi criada) + }))); } @Override @Transactional - public List listarPeladeiroCadastradosFut(Long futId) { - FutModel futModel = queryService.verifyFutExistRetornListPeladeiro(futId); /* + @Async("defaultExecutor") + public CompletableFuture> listarPeladeiroCadastradosFut(Long futId) { + return queryService + .verifyFutExistRetornListPeladeiro(futId) /* Esse metodo retorna futModel já com peladeiros carregado... resolvendo o problema abaixo. @ManyToMany é LAZY, Ou seja: - O Hibernate carrega os objetos da lista somente quando necessário. - / - MAS… apenas carrega os campos que estão presentes na tabela Many-to-Many(id , nome, email...). + - MAS… apenas carrega os campos que estão presentes na tabela Many-to-Many(id , nome, email...). - A tabela intermediária NÃO contém o ID do Peladeiro (Ex. id: null nome: null ...). - Portanto o Hibernate cria um “proxy”(Pense em um proxy como um “representante” de um objeto real.) com ID NULL até realmente precisar buscar do banco. */ - log.info("Verificacao de existencia de Fut realizada com sucesso!"); + .thenApply( + futModel -> { + log.info("Verificacao de existencia de Fut realizada com sucesso!"); - List listResponce = new ArrayList<>(); + List listResponce = new ArrayList<>(); - for (PeladeiroModel p : futModel.getPeladeiros()) { - listResponce.add(peladeiroMapper.modelToPeladeiroResponse(p)); - } - return listResponce; + for (PeladeiroModel p : futModel.getPeladeiros()) { + listResponce.add(peladeiroMapper.modelToPeladeiroResponse(p)); + } + return listResponce; + }); } // ===================== lista Editores ============================= @Override @Transactional - public void addEditor(AddEditorInFutListResquestDTO resquestDTO) { + @Async("defaultExecutor") + public CompletableFuture addEditor(AddEditorInFutListResquestDTO resquestDTO) { EditorModel editorModel = new EditorModel(); - // Verificacoes - FutModel futModel = queryService.verifyFutExistRetorn(resquestDTO.fut()); - PeladeiroModel peladeiroModel = - peladeiroQueryService.verifyPeladeiroExist(resquestDTO.peladeiro()); - queryService.verifyPeladeiroExistInListOrAdm(futModel, peladeiroModel); - - editorModel.setFut(futModel); - editorModel.setPeladeiro(peladeiroModel); - // Salvando Editor - editorService.create(editorModel); - // Adicionando Editor na lista de Editores de Fut. - futModel.getEditores().add(editorModel); - repository.save(futModel); - // Adicionado Editor na lista de Editores de Peladeiro. - peladeiroModel.getEditores().add(editorModel); - peladeiroRepository.save(peladeiroModel); + return queryService + .verifyFutExistRetorn(resquestDTO.fut()) + .thenCompose( + futModel -> + peladeiroQueryService + .verifyPeladeiroExist(resquestDTO.peladeiro()) + .thenAccept( + peladeiroModel -> { + queryService.verifyPeladeiroExistInListOrAdm(futModel, peladeiroModel); + + editorModel.setFut(futModel); + editorModel.setPeladeiro(peladeiroModel); + // Salvando Editor + editorService.create(editorModel); + // Adicionando Editor na lista de Editores de Fut. + futModel.getEditores().add(editorModel); + repository.save(futModel); + // Adicionado Editor na lista de Editores de Peladeiro. + peladeiroModel.getEditores().add(editorModel); + peladeiroRepository.save(peladeiroModel); + })); } @Override @Transactional - public List listarEditoresCadastradosFut(Long idFut) { - FutModel futModel = queryService.verifyFutExistRetornListEditores(idFut); - log.info("Verificacao de existencia de Fut realizada com sucesso!"); - - List listResponse = new ArrayList<>(); - - for (EditorModel e : futModel.getEditores()) { - listResponse.add(editorMapper.toResponseNameId(e)); - } - - return listResponse; + @Async("defaultExecutor") + public CompletableFuture> listarEditoresCadastradosFut( + Long idFut) { + return queryService + .verifyFutExistRetornListEditores(idFut) + .thenApply( + futModel -> { + log.info("Verificacao de existencia de Fut realizada com sucesso!"); + + List listResponse = new ArrayList<>(); + + for (EditorModel e : futModel.getEditores()) { + listResponse.add(editorMapper.toResponseNameId(e)); + } + + return listResponse; + }); } // ===================== upload arquivos fotos ====================== @Override @Transactional - public void atualizarFotoCapa(Long id, MultipartFile file) { + @Async("defaultExecutor") + public CompletableFuture atualizarFotoCapa(Long id, MultipartFile file) { queryService.verifyFutSaveFile(id, file); + return CompletableFuture.completedFuture(null); } // ============================= Banimentos ============================ @Override @Transactional - public SaveBanimentoResponseDTO addBanimentoList(SaveBanimentoRequestDTO dto) { - FutModel futModel = queryService.verifyFutExistRetorn(dto.fut()); - PeladeiroModel peladeiroModel = peladeiroQueryService.verifyPeladeiroExist(dto.peladeiro()); - - // Verificacao de existe o peladeiro em questao na lista de peladeiro... - queryService.verifyBanidoListPeladeiros(futModel, peladeiroModel); - - return banidoService.create(dto); + @Async("defaultExecutor") + public CompletableFuture addBanimentoList(SaveBanimentoRequestDTO dto) { + return queryService + .verifyFutExistRetorn(dto.fut()) + .thenCompose( + futModel -> + peladeiroQueryService + .verifyPeladeiroExist(dto.peladeiro()) + .thenCompose( + peladeiroModel -> { + // Verificacao de existe o peladeiro em questao na lista de peladeiro... + queryService.verifyBanidoListPeladeiros(futModel, peladeiroModel); + + return banidoService.create(dto); + })); } @Override @Transactional - public List findAllBanidos(Long idFut) { + @Async("defaultExecutor") + public CompletableFuture> findAllBanidos(Long idFut) { return banidoService.findAll(idFut); } @Override @Transactional - public void removeBanido(Long idPeladeiro, Long idFut) { - // TODO: retirar um Banido da lista - queryService.verifyBanidoListPeladeiros( - queryService.verifyFutExistRetorn(idFut), - peladeiroQueryService.verifyPeladeiroExist(idPeladeiro)); - - banidoService.delete(idPeladeiro); + @Async("defaultExecutor") + public CompletableFuture removeBanido(Long idPeladeiro, Long idFut) { + return queryService + .verifyFutExistRetorn(idFut) + .thenCompose( + futModel -> + peladeiroQueryService + .verifyPeladeiroExist(idPeladeiro) + .thenCompose( + peladeiroModel -> { + queryService.verifyBanidoListPeladeiros(futModel, peladeiroModel); + return banidoService.delete(idPeladeiro); + })); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/HistoricoPeladeiroService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/HistoricoPeladeiroService.java index aab5702..8557274 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/HistoricoPeladeiroService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/HistoricoPeladeiroService.java @@ -6,7 +6,9 @@ import br.com.vemprofut.repositories.HistoricoPeladeiroRepository; import br.com.vemprofut.services.IHistoricoPeladeiroService; import br.com.vemprofut.services.query.IHistoricoPeladeiroQueryService; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,41 +23,53 @@ public class HistoricoPeladeiroService implements IHistoricoPeladeiroService { @Override @Transactional - public HistoricoPeladeiroDTO create() { + @Async("defaultExecutor") + public CompletableFuture create() { HistoricoPeladeiroModel historico = new HistoricoPeladeiroModel(); - return mapper.toDTO(repository.save(historico)); + var response = mapper.toDTO(repository.save(historico)); + return CompletableFuture.completedFuture(response); + + // Se mudar futuramente repository para async tem que compor o metodo com thenApply. } @Override @Transactional(readOnly = true) - public HistoricoPeladeiroDTO findById(Long id) { + @Async("defaultExecutor") + public CompletableFuture findById(Long id) { - return mapper.toDTO(queryService.verityHistoricoPeladeiroExistReturn(id)); + return queryService.verityHistoricoPeladeiroExistReturn(id).thenApply(mapper::toDTO); } @Override @Transactional(readOnly = true) - public HistoricoPeladeiroModel findByIdModel(Long id) { + @Async("defaultExecutor") + public CompletableFuture findByIdModel(Long id) { return queryService.verityHistoricoPeladeiroExistReturn(id); } @Override - public HistoricoPeladeiroDTO update(Long id, HistoricoPeladeiroDTO dto) { - HistoricoPeladeiroModel historico = queryService.verityHistoricoPeladeiroExistReturn(id); - - historico.setGolsDoPeladeiro(dto.golsDoPeladeiro()); - historico.setNotaPeladeiro(dto.notaPeladeiro()); - historico.setPartidasJogadas(dto.partidasJogadas()); - historico.setPartidasGanhas(dto.partidasGanhas()); + @Async("defaultExecutor") + public CompletableFuture update(Long id, HistoricoPeladeiroDTO dto) { + return queryService + .verityHistoricoPeladeiroExistReturn(id) + .thenApply( + historicoPeladeiroModel -> { + historicoPeladeiroModel.setGolsDoPeladeiro(dto.golsDoPeladeiro()); + historicoPeladeiroModel.setNotaPeladeiro(dto.notaPeladeiro()); + historicoPeladeiroModel.setPartidasJogadas(dto.partidasJogadas()); + historicoPeladeiroModel.setPartidasGanhas(dto.partidasGanhas()); - return mapper.toDTO(repository.save(historico)); + return mapper.toDTO(repository.save(historicoPeladeiroModel)); + }); } @Override - public void delete(Long id) { + @Async("defaultExecutor") + public CompletableFuture delete(Long id) { queryService.verityHistoricoPeladeiroExist(id); repository.deleteById(id); + return CompletableFuture.completedFuture(null); } // TODO: implementar a somatoria de gols ao historico peladeiro diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PartidasService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PartidasService.java index 396b9e7..64a5bba 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PartidasService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PartidasService.java @@ -5,17 +5,17 @@ import br.com.vemprofut.mappers.ICartoesMapper; import br.com.vemprofut.mappers.IPartidasMapper; import br.com.vemprofut.mappers.IPeladeiroMapper; -import br.com.vemprofut.models.CartoesModel; import br.com.vemprofut.models.DTOs.PartidasDTO; import br.com.vemprofut.models.DTOs.PeladeiroDTO; import br.com.vemprofut.models.FutModel; import br.com.vemprofut.models.GolsPartidaModel; import br.com.vemprofut.models.PartidasModel; -import br.com.vemprofut.models.PeladeiroModel; import br.com.vemprofut.repositories.PartidasRepository; import br.com.vemprofut.services.*; import br.com.vemprofut.services.query.IPartidasQueryService; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,56 +40,77 @@ public class PartidasService implements IPartidasService { @Override @Transactional - public SavePartidasResponseDTO create(SavePartidaRequestDTO requestDTO, FutModel futModel) { - + @Async("defaultExecutor") + public CompletableFuture create( + SavePartidaRequestDTO requestDTO, FutModel futModel) { PartidasModel partidasModel = new PartidasModel(requestDTO.reservas(), futModel); - return mapperPartidas.toResponse(repository.save(partidasModel)); + SavePartidasResponseDTO response = mapperPartidas.toResponse(repository.save(partidasModel)); + return CompletableFuture.completedFuture(response); } @Override @Transactional(readOnly = true) - public PartidasDTO findById(Long id) { - return mapperPartidas.toDTO(queryService.verifyPartidaExistWithRetorn(id)); + @Async("defaultExecutor") + public CompletableFuture findById(Long id) { + return queryService.verifyPartidaExistWithRetorn(id).thenApply(mapperPartidas::toDTO); } @Override @Transactional(readOnly = true) - public PartidasModel findByIdModel(Long id) { + @Async("defaultExecutor") + public CompletableFuture findByIdModel(Long id) { return queryService.verifyPartidaExistWithRetorn(id); } @Override @Transactional - public void addGols(PeladeiroDTO peladeiroDTO, PartidasDTO partidasDTO) { + @Async("defaultExecutor") + public CompletableFuture addGols(PeladeiroDTO peladeiroDTO, PartidasDTO partidasDTO) { GolsPartidaModel gol = golsService.create(peladeiroDTO, partidasDTO); PartidasModel partida = mapperPartidas.toModel(partidasDTO); partida.getGolsPartida().add(gol); repository.save(partida); + return CompletableFuture.completedFuture(null); } @Override @Transactional - public void addPeladeiros(Long peladeiroId, PartidasDTO partidasDTO) { - // TODO: mudar o DTO para Long de peladeiro. - PeladeiroModel peladeiroModel = peladeiroService.findByIdModel(peladeiroId); - - PartidasModel partida = mapperPartidas.toModel(partidasDTO); - partida.getPeladeiros().add(peladeiroModel); - - repository.save(partida); + @Async("defaultExecutor") + public CompletableFuture addPeladeiros(Long peladeiroId, PartidasDTO partidasDTO) { + /* + Aqui você espera o CompletableFuture terminar. + Quando o PeladeiroModel estiver disponível, adiciona na partida e salva. + O método retorna um CompletableFuture que completa quando tudo terminar. + */ + return peladeiroService + .findByIdModel(peladeiroId) + .thenAccept( + peladeiroModel -> { + PartidasModel partida = mapperPartidas.toModel(partidasDTO); + partida.getPeladeiros().add(peladeiroModel); + }); } @Override @Transactional - public void addCartoes(Long cartaoId, PartidasDTO partidasDTO) { + @Async("defaultExecutor") + public CompletableFuture addCartoes(Long cartaoId, PartidasDTO partidasDTO) { // TODO: mudar o DTO para Long de cartoes. + /* ---> sincrono CartoesModel cartoesModel = cartoesService.findByIdModel(cartaoId); - PartidasModel partida = mapperPartidas.toModel(partidasDTO); partida.getCartoes().add(cartoesModel); - - repository.save(partida); + return repository.save(partida); */ + // Async + return cartoesService + .findByIdModel(cartaoId) + .thenAccept( + cartoesModel -> { + PartidasModel partida = mapperPartidas.toModel(partidasDTO); + partida.getCartoes().add(cartoesModel); + repository.save(partida); + }); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PeladeiroService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PeladeiroService.java index 0201483..61b4a23 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PeladeiroService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/implementacao/PeladeiroService.java @@ -8,15 +8,16 @@ import br.com.vemprofut.controllers.response.UpdatePeladeiroResponseDTO; import br.com.vemprofut.mappers.IHistoricoPeladeiroMapper; import br.com.vemprofut.mappers.IPeladeiroMapper; -import br.com.vemprofut.models.DTOs.HistoricoPeladeiroDTO; import br.com.vemprofut.models.PeladeiroModel; import br.com.vemprofut.repositories.PeladeiroRepository; import br.com.vemprofut.services.ICartoesService; import br.com.vemprofut.services.IHistoricoPeladeiroService; import br.com.vemprofut.services.IPeladeiroService; import br.com.vemprofut.services.query.IPeladeiroQueryService; +import java.util.concurrent.CompletableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -39,63 +40,82 @@ public class PeladeiroService implements IPeladeiroService { @Override @Transactional - public SavePeladeiroResponseDTO create(SavePeladeiroRequestDTO dto) { + @Async("defaultExecutor") + public CompletableFuture create(SavePeladeiroRequestDTO dto) { queryService.verifyEmail(dto.email()); log.info("Email verificado!"); PeladeiroModel peladeiroModel = peladeiroMapper.saveRequestToModel(dto); PeladeiroModel peladeiroSalvo = repository.save(peladeiroModel); - HistoricoPeladeiroDTO historico = historicoPeladeiroService.create(); - peladeiroSalvo.setHistoricoPeladeiro(historicoMapper.toModel(historico)); + return historicoPeladeiroService + .create() + .thenApply( + historico -> { + peladeiroSalvo.setHistoricoPeladeiro(historicoMapper.toModel(historico)); + PeladeiroModel salvo = repository.save(peladeiroSalvo); - log.info("Peladeiro cadastrado com sucesso!"); - return peladeiroMapper.modelToSaveResponse(repository.save(peladeiroSalvo)); + log.info("Peladeiro cadastrado com sucesso!"); + return peladeiroMapper.modelToSaveResponse(salvo); + }); } @Override @Transactional - public UpdatePeladeiroResponseDTO update(Long id, UpdatePeladeiroRequestDTO dto) { - var peladeiroModel = queryService.verifyPeladeiroExist(id); + @Async("defaultExecutor") + public CompletableFuture update( + Long id, UpdatePeladeiroRequestDTO dto) { log.info("Verificado a existencia de Peladeiro"); - - peladeiroModel.setNome(dto.nome()); - peladeiroModel.setEmail(dto.email()); - peladeiroModel.setApelido(dto.apelido()); - peladeiroModel.setDescricao(dto.descricao()); - peladeiroModel.setWhatsapp(dto.whatsapp()); - peladeiroModel.setPeDominante(dto.peDominante()); - - log.info("Peladeiro alterado com sucesso!"); - return peladeiroMapper.modelToUpdateResponse(repository.save(peladeiroModel)); + return queryService + .verifyPeladeiroExist(id) + .thenApply( + peladeiroModel -> { + peladeiroModel.setNome(dto.nome()); + peladeiroModel.setEmail(dto.email()); + peladeiroModel.setApelido(dto.apelido()); + peladeiroModel.setDescricao(dto.descricao()); + peladeiroModel.setWhatsapp(dto.whatsapp()); + peladeiroModel.setPeDominante(dto.peDominante()); + + log.info("Peladeiro alterado com sucesso!"); + + return peladeiroMapper.modelToUpdateResponse(repository.save(peladeiroModel)); + }); } @Override @Transactional(readOnly = true) - public PeladeiroDetailResponse findById(Long id) { + @Async("defaultExecutor") + public CompletableFuture findById(Long id) { log.info("Buscando peladeiro pelo id... saida de resposta"); - PeladeiroModel retorno = queryService.verifyPeladeiroExist(id); - CartoesResumoResponseDTO resumo = cartoesService.contarCartoesPeladeiro(id); - return new PeladeiroDetailResponse( - retorno.getId(), - retorno.getNome(), - retorno.getEmail(), - retorno.getApelido(), - retorno.getDescricao(), - retorno.getWhatsapp(), - retorno.getPeDominante(), - resumo); + CompletableFuture peladeiroFuture = queryService.verifyPeladeiroExist(id); + CompletableFuture resumoFuture = + cartoesService.contarCartoesPeladeiro(id); + return peladeiroFuture.thenCombine( + resumoFuture, + (retorno, resumo) -> + new PeladeiroDetailResponse( + retorno.getId(), + retorno.getNome(), + retorno.getEmail(), + retorno.getApelido(), + retorno.getDescricao(), + retorno.getWhatsapp(), + retorno.getPeDominante(), + resumo)); } @Override @Transactional(readOnly = true) - public PeladeiroModel findByIdModel(Long id) { + @Async("defaultExecutor") + public CompletableFuture findByIdModel(Long id) { log.info("Buscando peladeiro pelo id... saida de uso interno"); return queryService.verifyPeladeiroExist(id); } // @Override // @Transactional(readOnly = true) - // public List findAll() { + // @Async("defaultExecutor") + // public CompletableFuture> findAll() { // // return repository.findAll() // .stream() @@ -104,16 +124,20 @@ public PeladeiroModel findByIdModel(Long id) { // } @Override + @Async("defaultExecutor") @Transactional - public void delete(Long id) { + public CompletableFuture delete(Long id) { queryService.verifyPeladeiroExist(id); log.info("Existência de Peladeiro confirmada com sucesso!"); repository.deleteById(id); + return CompletableFuture.completedFuture(null); } @Override + @Async("defaultExecutor") @Transactional - public void atualizarFoto(Long id, MultipartFile file) { + public CompletableFuture atualizarFoto(Long id, MultipartFile file) { queryService.verifyPeladeiroSaveFile(id, file); + return CompletableFuture.completedFuture(null); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IFutQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IFutQueryService.java index 238927e..111f544 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IFutQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IFutQueryService.java @@ -2,27 +2,29 @@ import br.com.vemprofut.models.FutModel; import br.com.vemprofut.models.PeladeiroModel; +import java.util.concurrent.CompletableFuture; import org.springframework.web.multipart.MultipartFile; public interface IFutQueryService { - void verifyFutExist(Long dto); + CompletableFuture verifyFutExist(Long dto); - FutModel verifyFutExistRetorn(Long fut); + CompletableFuture verifyFutExistRetorn(Long fut); - FutModel verifyFutExistRetornListPeladeiro(Long id); + CompletableFuture verifyFutExistRetornListPeladeiro(Long id); - FutModel verifyFutExistRetornListEditores(Long id); + CompletableFuture verifyFutExistRetornListEditores(Long id); - void verifyNomeFutExist(String nome); + CompletableFuture verifyNomeFutExist(String nome); - FutModel verifyNomeFutExistRetorn(String nome); + CompletableFuture verifyNomeFutExistRetorn(String nome); - void verifyPeladeiroExistInListOrAdm(FutModel futModel, PeladeiroModel model); + CompletableFuture verifyPeladeiroExistInListOrAdm(FutModel futModel, PeladeiroModel model); - void verifyFutSaveFile(Long id, MultipartFile file); + CompletableFuture verifyFutSaveFile(Long id, MultipartFile file); - void verityPeladeiroInList(FutModel futModel, PeladeiroModel peladeiroModel); + CompletableFuture verityPeladeiroInList(FutModel futModel, PeladeiroModel peladeiroModel); - void verifyBanidoListPeladeiros(FutModel futModel, PeladeiroModel peladeiroModel); + CompletableFuture verifyBanidoListPeladeiros( + FutModel futModel, PeladeiroModel peladeiroModel); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IHistoricoPeladeiroQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IHistoricoPeladeiroQueryService.java index 182da8c..134d80a 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IHistoricoPeladeiroQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IHistoricoPeladeiroQueryService.java @@ -1,10 +1,11 @@ package br.com.vemprofut.services.query; import br.com.vemprofut.models.HistoricoPeladeiroModel; +import java.util.concurrent.CompletableFuture; public interface IHistoricoPeladeiroQueryService { - HistoricoPeladeiroModel verityHistoricoPeladeiroExistReturn(Long id); + CompletableFuture verityHistoricoPeladeiroExistReturn(Long id); - void verityHistoricoPeladeiroExist(Long id); + CompletableFuture verityHistoricoPeladeiroExist(Long id); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPartidasQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPartidasQueryService.java index 1d0d7dd..445a98a 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPartidasQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPartidasQueryService.java @@ -1,8 +1,9 @@ package br.com.vemprofut.services.query; import br.com.vemprofut.models.PartidasModel; +import java.util.concurrent.CompletableFuture; public interface IPartidasQueryService { - PartidasModel verifyPartidaExistWithRetorn(Long id); + CompletableFuture verifyPartidaExistWithRetorn(Long id); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPeladeiroQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPeladeiroQueryService.java index a7057cc..d7e16b2 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPeladeiroQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/IPeladeiroQueryService.java @@ -1,13 +1,14 @@ package br.com.vemprofut.services.query; import br.com.vemprofut.models.PeladeiroModel; +import java.util.concurrent.CompletableFuture; import org.springframework.web.multipart.MultipartFile; public interface IPeladeiroQueryService { - void verifyEmail(final String email); + CompletableFuture verifyEmail(final String email); - PeladeiroModel verifyPeladeiroExist(final Long id); + CompletableFuture verifyPeladeiroExist(final Long id); - void verifyPeladeiroSaveFile(Long id, MultipartFile file); + CompletableFuture verifyPeladeiroSaveFile(Long id, MultipartFile file); } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/FutQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/FutQueryService.java index 95c01ef..4ab8534 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/FutQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/FutQueryService.java @@ -4,13 +4,14 @@ import br.com.vemprofut.models.FutModel; import br.com.vemprofut.models.PeladeiroModel; import br.com.vemprofut.repositories.FutRepository; -import br.com.vemprofut.repositories.PeladeiroRepository; import br.com.vemprofut.services.IUploadLocalService; import br.com.vemprofut.services.query.IFutQueryService; import jakarta.persistence.EntityNotFoundException; import java.io.IOException; +import java.util.concurrent.CompletableFuture; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -21,91 +22,128 @@ public class FutQueryService implements IFutQueryService { private final FutRepository repository; private final IUploadLocalService uploadLocalService; - private final PeladeiroRepository peladeiroRepository; @Override - public void verifyFutExist(Long dto) { + @Async("defaultExecutor") + public CompletableFuture verifyFutExist(Long dto) { if (repository.existsById(dto)) { - throw new FutInUseException("Fut já cadastrado!"); + return CompletableFuture.failedFuture(new FutInUseException("Fut já cadastrado!")); } + return CompletableFuture.completedFuture(null); } @Override - public FutModel verifyFutExistRetorn(Long fut) { + @Async("defaultExecutor") + public CompletableFuture verifyFutExistRetorn(Long fut) { return repository .findById(fut) - .orElseThrow(() -> new NotFoundException("Não foi encontrado o Fut de id " + fut)); + .map(CompletableFuture::completedFuture) + .orElseGet( + () -> + CompletableFuture.failedFuture( + new NotFoundException("Não foi encontrado o Fut de id " + fut))); } @Override - public FutModel verifyFutExistRetornListPeladeiro(Long id) { + @Async("defaultExecutor") + public CompletableFuture verifyFutExistRetornListPeladeiro(Long id) { return repository .buscarFutComListPeladeiros(id) - .orElseThrow( - () -> new NotFoundException("Não foi encontrado o Fut de id ou lista de Peladeiro")); + .map(CompletableFuture::completedFuture) + .orElseGet( + () -> + CompletableFuture.failedFuture( + new NotFoundException("Não foi encontrado o Fut de id ou lista de Peladeiro"))); } @Override - public FutModel verifyFutExistRetornListEditores(Long id) { + @Async("defaultExecutor") + public CompletableFuture verifyFutExistRetornListEditores(Long id) { return repository .buscarFutComListEditores(id) - .orElseThrow( - () -> new NotFoundException("Não foi encontrado o Fut de id ou lista de Editores")); + .map(CompletableFuture::completedFuture) + .orElseGet( + () -> + CompletableFuture.failedFuture( + new NotFoundException("Não foi encontrado o Fut de id ou lista de Editores"))); } @Override - public void verifyNomeFutExist(String nome) { + @Async("defaultExecutor") + public CompletableFuture verifyNomeFutExist(String nome) { log.info("Iniciando a verificacao do nome..."); - boolean exists = repository.existsByNomeStartingWith(nome); - if (exists) { + if (repository.existsByNomeStartingWith(nome)) { log.warn("Nome já existente: " + nome); - throw new NomeInUseException("O nome '" + nome + "' já está cadastrado!"); + return CompletableFuture.failedFuture( + new NomeInUseException("O nome '" + nome + "' já está cadastrado!")); } log.info("Nome disponível."); + return CompletableFuture.completedFuture(null); } @Override - public FutModel verifyNomeFutExistRetorn(String nome) { + @Async("defaultExecutor") + public CompletableFuture verifyNomeFutExistRetorn(String nome) { return repository .findByNome(nome) - .orElseThrow( - () -> new EntityNotFoundException("Futebol com nome '" + nome + "' não encontrado")); + .map(CompletableFuture::completedFuture) + .orElseGet( + () -> + CompletableFuture.failedFuture( + new EntityNotFoundException("Futebol com nome '" + nome + "' não encontrado"))); } @Override - public void verifyPeladeiroExistInListOrAdm(FutModel futModel, PeladeiroModel model) { + @Async("defaultExecutor") + public CompletableFuture verifyPeladeiroExistInListOrAdm( + FutModel futModel, PeladeiroModel model) { if (!(futModel.getPeladeiros().contains(model))) { - throw new NotFoundException("Editor nao cadastrado na lista de peladeiros do fut!"); + return CompletableFuture.failedFuture( + new NotFoundException("Editor nao cadastrado na lista de peladeiros do fut!")); } if (futModel.getAdministradorPeladeiro().equals(model)) { - throw new NotFoundException("O Editor selecionado já é o Administrador do Fut!"); + return CompletableFuture.failedFuture( + new NotFoundException("O Editor selecionado já é o Administrador do Fut!")); } + return CompletableFuture.completedFuture(null); } @Override - public void verifyFutSaveFile(Long id, MultipartFile file) { - FutModel futModel = verifyFutExistRetorn(id); - try { - String url = uploadLocalService.upload(file, "fut"); - futModel.setFoto_url(url); - repository.save(futModel); - } catch (IOException ex) { - throw new FileStorageException( - "Erro ao salvar a foto do peladeiro com id: " + id, ex.getCause()); - } + @Async("defaultExecutor") + public CompletableFuture verifyFutSaveFile(Long id, MultipartFile file) { + return verifyFutExistRetorn(id) + .thenAccept( + futModel -> { + try { + String url = uploadLocalService.upload(file, "fut"); + futModel.setFoto_url(url); + repository.save(futModel); + } catch (IOException ex) { + throw new FileStorageException( + "Erro ao salvar a foto do peladeiro com id: " + id, ex.getCause()); + } + }); } @Override - public void verityPeladeiroInList(FutModel futModel, PeladeiroModel peladeiroModel) { + @Async("defaultExecutor") + public CompletableFuture verityPeladeiroInList( + FutModel futModel, PeladeiroModel peladeiroModel) { if (futModel.getPeladeiros().contains(peladeiroModel)) { - throw new PeladeiroNotExistException("Peladeiro já cadastrado na lista de peladeiros!"); + return CompletableFuture.failedFuture( + new PeladeiroNotExistException("Peladeiro já cadastrado na lista de peladeiros!")); } + return CompletableFuture.completedFuture(null); } @Override - public void verifyBanidoListPeladeiros(FutModel futModel, PeladeiroModel peladeiroModel) { + @Async("defaultExecutor") + public CompletableFuture verifyBanidoListPeladeiros( + FutModel futModel, PeladeiroModel peladeiroModel) { if (!(futModel.getPeladeiros().contains(peladeiroModel))) { - throw new NotFoundException("Nao consta esse Peladeiro na lista de Peladeiros"); + return CompletableFuture.failedFuture( + new NotFoundException("Nao consta esse Peladeiro na lista de Banidos")); } + return CompletableFuture.completedFuture(null); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/HistoricoPeladeiroQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/HistoricoPeladeiroQueryService.java index 4ece915..7ddfe08 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/HistoricoPeladeiroQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/HistoricoPeladeiroQueryService.java @@ -4,7 +4,9 @@ import br.com.vemprofut.models.HistoricoPeladeiroModel; import br.com.vemprofut.repositories.HistoricoPeladeiroRepository; import br.com.vemprofut.services.query.IHistoricoPeladeiroQueryService; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service @@ -12,18 +14,24 @@ public class HistoricoPeladeiroQueryService implements IHistoricoPeladeiroQueryS @Autowired HistoricoPeladeiroRepository repository; @Override - public HistoricoPeladeiroModel verityHistoricoPeladeiroExistReturn(Long id) { - + @Async("defaultExecutor") + public CompletableFuture verityHistoricoPeladeiroExistReturn(Long id) { return repository .findById(id) - .orElseThrow( - () -> new NotFoundException("Não foi encontrado o Historico de Peladeiro de id " + id)); + .map(CompletableFuture::completedFuture) + .orElseGet( + () -> + CompletableFuture.failedFuture( + new NotFoundException( + "Não foi encontrado o Historico de Peladeiro de id " + id))); } @Override - public void verityHistoricoPeladeiroExist(Long id) { + @Async("defaultExecutor") + public CompletableFuture verityHistoricoPeladeiroExist(Long id) { if (!repository.existsById(id)) { throw new NotFoundException("Id: " + id + "de Historico Jogador não encontrado!"); } + return CompletableFuture.completedFuture(null); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PartidasQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PartidasQueryService.java index dc8abd3..9806409 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PartidasQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PartidasQueryService.java @@ -7,7 +7,9 @@ import br.com.vemprofut.repositories.PartidasRepository; import br.com.vemprofut.repositories.PeladeiroRepository; import br.com.vemprofut.services.query.IPartidasQueryService; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service @@ -21,9 +23,14 @@ public class PartidasQueryService implements IPartidasQueryService { @Autowired private PeladeiroRepository peladeiroRepository; @Override - public PartidasModel verifyPartidaExistWithRetorn(Long id) { + @Async("defaultExecutor") + public CompletableFuture verifyPartidaExistWithRetorn(Long id) { return repository .findById(id) - .orElseThrow(() -> new NotFoundException("Não foi encontrado a Partida de id " + id)); + .map(CompletableFuture::completedFuture) + .orElseGet( + () -> + CompletableFuture.failedFuture( + new NotFoundException("Não foi encontrado a Partida de id " + id))); } } diff --git a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PeladeiroQueryService.java b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PeladeiroQueryService.java index 2670d1f..a96cb9b 100644 --- a/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PeladeiroQueryService.java +++ b/VemProFutApi/src/main/java/br/com/vemprofut/services/query/implementacao/PeladeiroQueryService.java @@ -8,8 +8,10 @@ import br.com.vemprofut.services.IUploadLocalService; import br.com.vemprofut.services.query.IPeladeiroQueryService; import java.io.IOException; +import java.util.concurrent.CompletableFuture; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -22,42 +24,45 @@ public class PeladeiroQueryService implements IPeladeiroQueryService { private final IUploadLocalService uploadLocalService; @Override - public void verifyEmail(String email) { + @Async("defaultExecutor") + public CompletableFuture verifyEmail(String email) { if (repository.existsByEmail(email)) { var message = "O e-mail " + email + " já está em uso"; log.error(message); throw new EmailInUseException(message); } + return CompletableFuture.completedFuture(null); } @Override - public PeladeiroModel verifyPeladeiroExist(Long id) { + @Async("defaultExecutor") + public CompletableFuture verifyPeladeiroExist(Long id) { log.debug("Verificando existência do Peladeiro com ID: {}", id); - PeladeiroModel peladeiro = - repository - .findById(id) - .orElseThrow( - () -> { - log.warn("Peladeiro com ID {} não encontrado no banco de dados", id); - return new NotFoundException("Não foi encontrado o Peladeiro de id " + id); - }); - - log.debug("Peladeiro encontrado: {}", peladeiro); - return peladeiro; + return repository + .findById(id) + .map(CompletableFuture::completedFuture) + .orElseGet( + () -> + CompletableFuture.failedFuture( + new NotFoundException("Não foi encontrado o Peladeiro de id " + id))); } @Override - public void verifyPeladeiroSaveFile(Long id, MultipartFile file) { - PeladeiroModel peladeiroModel = verifyPeladeiroExist(id); - try { - String url = uploadLocalService.upload(file, "peladeiro"); - peladeiroModel.setFotoUrl(url); - repository.save(peladeiroModel); - log.info("Foto salva!"); - } catch (IOException ex) { - throw new FileStorageException( - "Erro ao salvar a foto do peladeiro com id: " + id, ex.getCause()); - } + @Async("defaultExecutor") + public CompletableFuture verifyPeladeiroSaveFile(Long id, MultipartFile file) { + return verifyPeladeiroExist(id) // retorna CompletableFuture + .thenAccept( + peladeiroModel -> { + try { + String url = uploadLocalService.upload(file, "peladeiro"); + peladeiroModel.setFotoUrl(url); + repository.save(peladeiroModel); + log.info("Foto salva!"); + } catch (IOException ex) { + throw new FileStorageException( + "Erro ao salvar a foto do peladeiro com id: " + id, ex); + } + }); } } diff --git a/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/FutServiceTest.java b/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/FutServiceTest.java index 0d6d866..abf2aaa 100644 --- a/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/FutServiceTest.java +++ b/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/FutServiceTest.java @@ -9,23 +9,18 @@ import br.com.vemprofut.controllers.response.SaveFutResponseDTO; import br.com.vemprofut.exceptions.NomeInUseException; import br.com.vemprofut.exceptions.NotFoundException; -import br.com.vemprofut.mappers.IEditorMapper; import br.com.vemprofut.mappers.IFutMapper; -import br.com.vemprofut.mappers.IPartidasMapper; -import br.com.vemprofut.mappers.IPeladeiroMapper; import br.com.vemprofut.models.DTOs.FutDTO; import br.com.vemprofut.models.FutModel; import br.com.vemprofut.models.HistoricoFutModel; import br.com.vemprofut.models.PeladeiroModel; import br.com.vemprofut.repositories.*; -import br.com.vemprofut.services.IBanimentoService; -import br.com.vemprofut.services.IEditorService; import br.com.vemprofut.services.IHistoricoFutService; -import br.com.vemprofut.services.IPartidasService; import br.com.vemprofut.services.implementacao.FutService; import br.com.vemprofut.services.query.IFutQueryService; import br.com.vemprofut.services.query.IPeladeiroQueryService; import java.util.List; +import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -40,19 +35,9 @@ public class FutServiceTest { @Mock private IFutQueryService queryService; @Mock private IFutMapper mapper; - @Mock private IPartidasMapper partidasMapper; @Mock private FutRepository repository; - @Mock private IPartidasService partidasService; - @Mock private PartidasRepository partidasRepository; @Mock private IPeladeiroQueryService peladeiroQueryService; - @Mock private PeladeiroRepository peladeiroRepository; - @Mock private IPeladeiroMapper peladeiroMapper; @Mock private IHistoricoFutService historicoFutService; - @Mock private CartoesRepository cartoesRepository; - @Mock private GolsPartidaRepository golsRepository; - @Mock private IEditorService editorService; - @Mock private IEditorMapper editorMapper; - @Mock private IBanimentoService banidoService; @InjectMocks private FutService futService; @@ -88,16 +73,17 @@ void create_quandoFutValido_retornaFutSalvo() { new SaveFutResponseDTO( 1L, "Fut teste", 4, 10, 2, historicoFutModel.getId(), peladeiroModel.getId()); - doNothing().when(queryService).verifyNomeFutExist(futModel.getNome()); + when(queryService.verifyNomeFutExist(futModel.getNome())) + .thenReturn(CompletableFuture.completedFuture(null)); when(peladeiroQueryService.verifyPeladeiroExist(saveFutRequestDTO.administradorPeladeiro())) - .thenReturn(peladeiroModel); + .thenReturn(CompletableFuture.completedFuture(peladeiroModel)); when(mapper.saveRequestToModel(saveFutRequestDTO)).thenReturn(futModel); when(repository.save(futModel)).thenReturn(futModel); when(historicoFutService.create()).thenReturn(historicoFutModel); when(mapper.toSaveResponse(futModel)).thenReturn(saveFutResponseDTO); // Act: - SaveFutResponseDTO response = futService.create(saveFutRequestDTO); + SaveFutResponseDTO response = futService.create(saveFutRequestDTO).join(); // Assert: assertThat(response.id()).isNotNull().isEqualTo(1L); @@ -140,11 +126,12 @@ void findById_quandoFutExiste_retornaFutDetailsResponse() { FutDetailsResponse futDetailsResponse = new FutDetailsResponse(1L, "Fut teste", 4, 10, 2, 1L, 1L); - when(queryService.verifyFutExistRetorn(1L)).thenReturn(futModel); + when(queryService.verifyFutExistRetorn(1L)) + .thenReturn(CompletableFuture.completedFuture(futModel)); when(mapper.modelToDetailsResponse(futModel)).thenReturn(futDetailsResponse); // Act: - FutDetailsResponse response = futService.findById(1L); + FutDetailsResponse response = futService.findById(1L).join(); // Assert assertThat(response.id()).isNotNull().isEqualTo(1L); @@ -159,8 +146,6 @@ void findById_quandoFutExiste_retornaFutDetailsResponse() { void findById_quandoFutInexistente_retornaNotFoundException() { // Arrange: - FutDetailsResponse futDetailsResponse = - new FutDetailsResponse(1L, "Fut teste", 4, 10, 2, 1L, 1L); when(queryService.verifyFutExistRetorn(99L)) .thenThrow(new NotFoundException("Não foi encontrado o Fut de id " + 99L)); @@ -181,11 +166,12 @@ void findByNome_quandoFutExiste_retornaFutDTO() { List cartoes = List.of(1L, 2L, 3L, 5L); FutDTO futDTO = new FutDTO(1L, "Fut Test", 4, 10, 2, 1L, 1L, editores, peladeiros, cartoes); - when(queryService.verifyNomeFutExistRetorn("Fut Test")).thenReturn(futModel); + when(queryService.verifyNomeFutExistRetorn("Fut Test")) + .thenReturn(CompletableFuture.completedFuture(futModel)); when(mapper.toDTO(futModel)).thenReturn(futDTO); // Act - FutDTO response = futService.findByNome("Fut Test"); + FutDTO response = futService.findByNome("Fut Test").join(); // Assert assertThat(response).isNotNull(); diff --git a/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/PeladeiroServiceTest.java b/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/PeladeiroServiceTest.java index ef9d681..322e43c 100644 --- a/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/PeladeiroServiceTest.java +++ b/VemProFutApi/src/test/java/br/com/vemprofut/unit/services/PeladeiroServiceTest.java @@ -14,6 +14,8 @@ import br.com.vemprofut.exceptions.NotFoundException; import br.com.vemprofut.mappers.IHistoricoPeladeiroMapper; import br.com.vemprofut.mappers.IPeladeiroMapper; +import br.com.vemprofut.models.DTOs.HistoricoPeladeiroDTO; +import br.com.vemprofut.models.HistoricoPeladeiroModel; import br.com.vemprofut.models.PeladeiroModel; import br.com.vemprofut.models.enuns.PeDominante; import br.com.vemprofut.repositories.PeladeiroRepository; @@ -22,6 +24,7 @@ import br.com.vemprofut.services.implementacao.PeladeiroService; import br.com.vemprofut.services.query.IPeladeiroQueryService; import java.util.List; +import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -30,6 +33,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.web.multipart.MultipartFile; @ExtendWith(MockitoExtension.class) public class PeladeiroServiceTest { @@ -37,9 +41,9 @@ public class PeladeiroServiceTest { @Mock private IPeladeiroQueryService queryService; @Mock private PeladeiroRepository repository; @Mock private IPeladeiroMapper peladeiroMapper; - @Mock private IHistoricoPeladeiroMapper historicoMapper; - @Mock private IHistoricoPeladeiroService historicoPeladeiroService; @Mock private ICartoesService cartoesService; + @Mock private IHistoricoPeladeiroService historicoPeladeiroService; + @Mock private IHistoricoPeladeiroMapper historicoPeladeiroMapper; @InjectMocks private PeladeiroService peladeiroService; @@ -67,12 +71,21 @@ void create_quandoPeladeiroValido() { PeDominante.DESTRO, "81999999999"); + HistoricoPeladeiroDTO historicoPeladeiroDTO = new HistoricoPeladeiroDTO(1L, 10, 9.5, 5, 3); + + HistoricoPeladeiroModel historicoPeladeiroModel = new HistoricoPeladeiroModel(); + // cria listas simuladas List partidas = List.of(10L, 20L); List futs = List.of(30L); List cartoes = List.of(40L, 50L); - doNothing().when(queryService).verifyEmail(savePeladeiroRequestDTO.email()); + when(queryService.verifyEmail(savePeladeiroRequestDTO.email())) + .thenReturn(CompletableFuture.completedFuture(null)); + when(historicoPeladeiroService.create()) + .thenReturn(CompletableFuture.completedFuture(historicoPeladeiroDTO)); + when(historicoPeladeiroMapper.toModel(historicoPeladeiroDTO)) + .thenReturn(historicoPeladeiroModel); when(peladeiroMapper.saveRequestToModel(savePeladeiroRequestDTO)).thenReturn(peladeiroModel); when(repository.save(peladeiroModel)).thenReturn(peladeiroModel); when(peladeiroMapper.modelToSaveResponse(peladeiroModel)) @@ -91,12 +104,14 @@ void create_quandoPeladeiroValido() { futs, cartoes)); // Act - SavePeladeiroResponseDTO response = peladeiroService.create(savePeladeiroRequestDTO); + SavePeladeiroResponseDTO response = peladeiroService.create(savePeladeiroRequestDTO).join(); // Assert assertThat(response.nome()).isEqualTo("Marcio"); verify(queryService).verifyEmail(savePeladeiroRequestDTO.email()); + verify(historicoPeladeiroService).create(); + verify(historicoPeladeiroMapper).toModel(historicoPeladeiroDTO); verify(repository, times(2)).save(peladeiroModel); verify(peladeiroMapper).saveRequestToModel(savePeladeiroRequestDTO); verify(peladeiroMapper).modelToSaveResponse(peladeiroModel); @@ -115,11 +130,6 @@ void create_quandoEmailJaCadastrado_retornaEmailInUseException() { PeDominante.DESTRO, "81999999999"); - // cria listas simuladas - List partidas = List.of(10L, 20L); - List futs = List.of(30L); - List cartoes = List.of(40L, 50L); - doThrow( new EmailInUseException( "O e-mail " + savePeladeiroRequestDTO.email() + " já está em uso")) @@ -148,7 +158,8 @@ void update_quandoPeladeiroExiste_retornaPeladeiroAlterado() { PeDominante.CANHOTO, "81999993332"); - when(queryService.verifyPeladeiroExist(1L)).thenReturn(peladeiroModel); + when(queryService.verifyPeladeiroExist(1L)) + .thenReturn(CompletableFuture.completedFuture(peladeiroModel)); when(repository.save(peladeiroModel)).thenReturn(peladeiroModel); when(peladeiroMapper.modelToUpdateResponse(peladeiroModel)) .thenReturn( @@ -162,7 +173,7 @@ void update_quandoPeladeiroExiste_retornaPeladeiroAlterado() { "foto.com/url")); // Act - UpdatePeladeiroResponseDTO responseDTO = peladeiroService.update(1L, requestDTO); + UpdatePeladeiroResponseDTO responseDTO = peladeiroService.update(1L, requestDTO).join(); // Assert assertThat(responseDTO).isNotNull(); @@ -202,11 +213,13 @@ void update_quandoPeladeiroInexistente_retornaNotFoundException() { void findById_quandoPeladeiroExiste_retornaPeladeiroDetailResponse() { // Arrange CartoesResumoResponseDTO cartoesResumoResponseDTO = new CartoesResumoResponseDTO(2, 3, 2); - when(queryService.verifyPeladeiroExist(1L)).thenReturn(peladeiroModel); - when(cartoesService.contarCartoesPeladeiro(1L)).thenReturn(cartoesResumoResponseDTO); + when(queryService.verifyPeladeiroExist(1L)) + .thenReturn(CompletableFuture.completedFuture(peladeiroModel)); + when(cartoesService.contarCartoesPeladeiro(1L)) + .thenReturn(CompletableFuture.completedFuture(cartoesResumoResponseDTO)); // Act - PeladeiroDetailResponse peladeiroDetailResponse = peladeiroService.findById(1L); + PeladeiroDetailResponse peladeiroDetailResponse = peladeiroService.findById(1L).join(); // Assert assertThat(peladeiroDetailResponse).isNotNull(); @@ -239,13 +252,14 @@ void findById_quandoPeladeiroInexistente_retornaNotFoundException() { } @Test - @DisplayName("") + @DisplayName("Deve retornar PeladeiroModel quando ID existe") void findByIdModel_quandoPeladeiroExiste_retornaPeladeiroModel() { // Arrenge - when(queryService.verifyPeladeiroExist(1L)).thenReturn(peladeiroModel); + when(queryService.verifyPeladeiroExist(1L)) + .thenReturn(CompletableFuture.completedFuture(peladeiroModel)); // Act - PeladeiroModel response = peladeiroService.findByIdModel(1L); + PeladeiroModel response = peladeiroService.findByIdModel(1L).join(); // Assert assertThat(response.getId()).isEqualTo(1L); @@ -256,7 +270,7 @@ void findByIdModel_quandoPeladeiroExiste_retornaPeladeiroModel() { } @Test - @DisplayName("") + @DisplayName("Deve retornar erro NotFoundException quando ID nao existe") void findByIdModel_quandoPeladeiroInexistente_retornaNotFoundException() { // Arrenge when(queryService.verifyPeladeiroExist(99L)) @@ -274,11 +288,12 @@ void findByIdModel_quandoPeladeiroInexistente_retornaNotFoundException() { @DisplayName("Deve apagar o Peladeiro indicado pelo numero do ID") void delete_quandoPeladeiroExiste() { // Arrenge - when(queryService.verifyPeladeiroExist(1L)).thenReturn(peladeiroModel); + when(queryService.verifyPeladeiroExist(1L)) + .thenReturn(CompletableFuture.completedFuture(peladeiroModel)); doNothing().when(repository).deleteById(1L); // Act - peladeiroService.delete(1L); + peladeiroService.delete(1L).join(); // Assert verify(queryService).verifyPeladeiroExist(1L); @@ -300,4 +315,34 @@ void delete_quandoPeladeiroInexistente() { verify(queryService).verifyPeladeiroExist(99L); } + + @Test + @DisplayName("Deve atualizar a foto do Peladeiro") + void atualizarFoto_quandoPeladeiroExiste() { + MultipartFile file = mock(MultipartFile.class); + + when(queryService.verifyPeladeiroSaveFile(1L, file)) + .thenReturn(CompletableFuture.completedFuture(null)); + peladeiroService.atualizarFoto(1L, file).join(); + + verify(queryService).verifyPeladeiroSaveFile(1L, file); + } + + @Test + @DisplayName("Deve lançar NotFoundException ao tentar atualizar foto de Peladeiro inexistente") + void atualizarFoto_quandoPeladeiroInexistente_retornaNotFoundException() { + MultipartFile file = mock(MultipartFile.class); + + // Arrange: simula que o queryService lança exceção + doThrow(new NotFoundException("Não foi encontrado o Peladeiro de id 99")) + .when(queryService) + .verifyPeladeiroSaveFile(99L, file); + + // Act + Assert + assertThatThrownBy(() -> peladeiroService.atualizarFoto(99L, file).join()) + .isInstanceOf(NotFoundException.class) + .hasMessage("Não foi encontrado o Peladeiro de id 99"); + + verify(queryService).verifyPeladeiroSaveFile(99L, file); + } }