diff --git a/src/main/java/cholog/wiseshop/api/campaign/controller/CampaignController.java b/src/main/java/cholog/wiseshop/api/campaign/controller/CampaignController.java index 2551a5f..0d62e38 100644 --- a/src/main/java/cholog/wiseshop/api/campaign/controller/CampaignController.java +++ b/src/main/java/cholog/wiseshop/api/campaign/controller/CampaignController.java @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api/v1/campaigns") @@ -30,7 +31,7 @@ public CampaignController(CampaignService campaignService) { @PostMapping public ResponseEntity createCampaigns(@Auth Member member, - @RequestBody CreateCampaignRequest request) { + @RequestBody CreateCampaignRequest request) { var response = campaignService.createCampaign(request, member, LocalDateTime.now()); return ResponseEntity.status(HttpStatus.CREATED).body(response); } @@ -52,4 +53,12 @@ public ResponseEntity> readMemberCampaign(@Auth Mem List response = campaignService.readMemberCampaign(member); return ResponseEntity.ok(response); } + + @GetMapping("/search") + public ResponseEntity> searchCampaigns(@RequestParam String keyword, + @RequestParam int page, + @RequestParam int size) { + List response = campaignService.searchByProductName(keyword, page, size); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/cholog/wiseshop/api/campaign/service/CampaignService.java b/src/main/java/cholog/wiseshop/api/campaign/service/CampaignService.java index 0ca1533..8cbe51f 100644 --- a/src/main/java/cholog/wiseshop/api/campaign/service/CampaignService.java +++ b/src/main/java/cholog/wiseshop/api/campaign/service/CampaignService.java @@ -18,6 +18,10 @@ import cholog.wiseshop.exception.WiseShopException; import java.time.LocalDateTime; import java.util.List; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -127,4 +131,25 @@ public List readMemberCampaign(Member member) { return MemberCampaignResponse.of(campaign, products.getFirst()); }).toList(); } + + public List searchByProductName(String keyword, int page, int size) { + keyword = keyword.trim(); + Pageable pageable = PageRequest.of(page, size, Sort.by("id").ascending()); + Page pages = productRepository.findByNameContaining(keyword, pageable); + return pages.getContent().stream() + .map(product -> { + Campaign campaign = product.getCampaign(); + return new ReadCampaignResponse( + campaign.getId(), + campaign.getStartDate().toString(), + campaign.getEndDate().toString(), + campaign.getGoalQuantity(), + campaign.getSoldQuantity(), + product.getStock().getTotalQuantity(), + campaign.getState(), + new ProductResponse(product), + campaign.getMember().orElse(Member.createEmpty()).getId() + ); + }).toList(); + } } diff --git a/src/main/java/cholog/wiseshop/db/product/ProductRepository.java b/src/main/java/cholog/wiseshop/db/product/ProductRepository.java index e91edff..585fe29 100644 --- a/src/main/java/cholog/wiseshop/db/product/ProductRepository.java +++ b/src/main/java/cholog/wiseshop/db/product/ProductRepository.java @@ -2,6 +2,8 @@ import cholog.wiseshop.db.campaign.Campaign; import java.util.List; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -14,4 +16,8 @@ public interface ProductRepository extends JpaRepository { List findAllByCampaign(Campaign campaign); List findAllByOwnerId(Long memberId); + + @Query(value = "SELECT p FROM Product p JOIN FETCH p.stock JOIN FETCH p.campaign WHERE p.name LIKE %:keyword%", + countQuery = "SELECT COUNT(p) FROM Product p WHERE p.name LIKE %:keyword%") + Page findByNameContaining(String keyword, Pageable pageable); } diff --git a/src/test/java/cholog/wiseshop/domain/CampaignServiceTest.java b/src/test/java/cholog/wiseshop/domain/CampaignServiceTest.java index d660869..1f14ac4 100644 --- a/src/test/java/cholog/wiseshop/domain/CampaignServiceTest.java +++ b/src/test/java/cholog/wiseshop/domain/CampaignServiceTest.java @@ -311,4 +311,31 @@ class 캠페인을_조회한다 { assertThat(response).hasSize(2); } } + + @Nested + class 캠페인을_상품이름으로_검색한다 { + + @Test + void 캠페인_상품이름으로_검색() { + // given + Member member = memberRepository.save(MemberFixture.최준호()); + Campaign campaign = campaignRepository.save(CampaignFixture.진행중인_보약_캠페인(member)); + Stock stock = new Stock(20); + stockRepository.save(stock); + productRepository.save( + ProductFixture.재고가_설정된_이름있는_캠페인의_보약(campaign, stock, member, "아주 좋은 보약")); + + Campaign campaign2 = campaignRepository.save(CampaignFixture.진행중인_보약_캠페인(member)); + Stock stock2 = new Stock(30); + stockRepository.save(stock2); + productRepository.save( + ProductFixture.재고가_설정된_이름있는_캠페인의_보약(campaign2, stock2, member, "아주 나쁜 보약")); + + // when + List response = campaignService.searchByProductName("좋은", 0, 10); + + // then + assertThat(response).hasSize(1); + } + } } diff --git a/src/test/java/cholog/wiseshop/fixture/ProductFixture.java b/src/test/java/cholog/wiseshop/fixture/ProductFixture.java index ef230ed..2e59177 100644 --- a/src/test/java/cholog/wiseshop/fixture/ProductFixture.java +++ b/src/test/java/cholog/wiseshop/fixture/ProductFixture.java @@ -18,6 +18,20 @@ public class ProductFixture { .build(); } + public static Product 재고가_설정된_이름있는_캠페인의_보약( + Campaign campaign, + Stock stock, + Member owner, + String name) { + return Product.builder() + .name(name) + .campaign(campaign) + .price(1000) + .stock(stock) + .owner(owner) + .build(); + } + public static Product 재고가_설정된_캠페인의_보약(Campaign campaign, Stock stock, Member owner) { return Product.builder() .campaign(campaign)