From 2d3b2dd3931adc86209fe8e4d2ccfae94c8ded97 Mon Sep 17 00:00:00 2001 From: Taehyeon Jo <70999462+whxogus215@users.noreply.github.com> Date: Thu, 20 Feb 2025 18:36:15 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EC=9C=BC=EB=A1=9C=20=EC=BA=A0=ED=8E=98=EC=9D=B8=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B2=80=EC=83=89=20API?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CampaignController.java | 11 +++++++- .../api/campaign/service/CampaignService.java | 25 +++++++++++++++++ .../db/product/ProductRepository.java | 4 +++ .../wiseshop/domain/CampaignServiceTest.java | 27 +++++++++++++++++++ .../wiseshop/fixture/ProductFixture.java | 14 ++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) 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..6583fd1 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,6 @@ public interface ProductRepository extends JpaRepository { List findAllByCampaign(Campaign campaign); List findAllByOwnerId(Long memberId); + + 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) From a1b79a8ac565a113cbbcbd86ea6558a43a81531b Mon Sep 17 00:00:00 2001 From: Taehyeon Jo <70999462+whxogus215@users.noreply.github.com> Date: Thu, 20 Feb 2025 23:18:06 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=ED=8E=98=EC=9D=B4=EC=A7=95=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C,=20Fetch=20Join=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - N+1 문제 해결 --- .../java/cholog/wiseshop/db/product/ProductRepository.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/cholog/wiseshop/db/product/ProductRepository.java b/src/main/java/cholog/wiseshop/db/product/ProductRepository.java index 6583fd1..8fd8a60 100644 --- a/src/main/java/cholog/wiseshop/db/product/ProductRepository.java +++ b/src/main/java/cholog/wiseshop/db/product/ProductRepository.java @@ -17,5 +17,9 @@ public interface ProductRepository extends JpaRepository { List findAllByOwnerId(Long memberId); +// Page findByNameContaining(String keyword, Pageable pageable); + + @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); } From b5ee6b627de23acb20aa31f2f7c8a17541fc4112 Mon Sep 17 00:00:00 2001 From: Taehyeon Jo <70999462+whxogus215@users.noreply.github.com> Date: Fri, 21 Feb 2025 13:29:01 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EC=A3=BC=EC=84=9D=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/cholog/wiseshop/db/product/ProductRepository.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/cholog/wiseshop/db/product/ProductRepository.java b/src/main/java/cholog/wiseshop/db/product/ProductRepository.java index 8fd8a60..585fe29 100644 --- a/src/main/java/cholog/wiseshop/db/product/ProductRepository.java +++ b/src/main/java/cholog/wiseshop/db/product/ProductRepository.java @@ -17,8 +17,6 @@ public interface ProductRepository extends JpaRepository { List findAllByOwnerId(Long memberId); -// Page findByNameContaining(String keyword, Pageable pageable); - @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);