From 77342436f38c1eeb7ee2b6a2482640f317292e64 Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:42:56 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[refactor]findTopContributorsByFundingId()?= =?UTF-8?q?=20=EB=B0=98=ED=99=98=20=EA=B0=92=20=EC=88=98=EC=A0=95=20(#330)?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0=EA=B0=80=20=EC=95=84=EB=8B=8C=20?= =?UTF-8?q?DTO=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- .../funding/repository/FundingDetailRepository.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepository.java b/src/main/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepository.java index 858571ad6..4ca24faa6 100644 --- a/src/main/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepository.java +++ b/src/main/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepository.java @@ -1,5 +1,6 @@ package org.kakaoshare.backend.domain.funding.repository; +import org.kakaoshare.backend.domain.funding.dto.rank.response.TopContributorResponse; import org.kakaoshare.backend.domain.funding.entity.Funding; import org.kakaoshare.backend.domain.funding.entity.FundingDetail; import org.kakaoshare.backend.domain.funding.repository.query.FundingDetailRepositoryCustom; @@ -21,7 +22,9 @@ public interface FundingDetailRepository extends JpaRepository findAllByFundingId(@Param("fundingId") final Long fundingId); - @Query("SELECT fd FROM FundingDetail fd WHERE fd.funding.fundingId = :fundingId ORDER BY fd.amount DESC") - Page findTopContributorsByFundingId(@Param("fundingId") Long fundingId, Pageable pageable); - + @Query("SELECT NEW org.kakaoshare.backend.domain.funding.dto.rank.response.TopContributorResponse(fd.member.profileImageUrl, fd.member.name, fd.rate) " + + "FROM FundingDetail fd " + + "LEFT JOIN fd.member m ON m.memberId = fd.member.memberId " + + "WHERE fd.funding.fundingId = :fundingId") + Page findTopContributorsByFundingId(@Param("fundingId") Long fundingId, Pageable pageable); } From 61acc5c47c41eb509681f308a367bb1640a535d1 Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:43:20 +0900 Subject: [PATCH 2/8] =?UTF-8?q?[refactor]getTopContributors()=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=20(#330)=20=EC=99=B8=EB=B6=80=20?= =?UTF-8?q?API=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EA=B3=A0=20=EA=B5=AC=ED=98=84=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- .../funding/service/FundingDetailService.java | 43 ++----------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/kakaoshare/backend/domain/funding/service/FundingDetailService.java b/src/main/java/org/kakaoshare/backend/domain/funding/service/FundingDetailService.java index 011daea56..0e38bd1a5 100644 --- a/src/main/java/org/kakaoshare/backend/domain/funding/service/FundingDetailService.java +++ b/src/main/java/org/kakaoshare/backend/domain/funding/service/FundingDetailService.java @@ -3,29 +3,22 @@ import com.querydsl.core.util.StringUtils; import lombok.RequiredArgsConstructor; import org.kakaoshare.backend.common.dto.PageResponse; -import org.kakaoshare.backend.domain.friend.service.KakaoFriendService; import org.kakaoshare.backend.domain.funding.dto.inquiry.ContributedFundingHistoryDto; import org.kakaoshare.backend.domain.funding.dto.inquiry.request.ContributedFundingHistoryRequest; import org.kakaoshare.backend.domain.funding.dto.inquiry.response.ContributedFundingHistoryResponse; -import org.kakaoshare.backend.domain.funding.dto.inquiry.response.FundingContributorResponse; -import org.kakaoshare.backend.domain.funding.entity.FundingDetail; +import org.kakaoshare.backend.domain.funding.dto.rank.response.TopContributorResponse; import org.kakaoshare.backend.domain.funding.repository.FundingDetailRepository; import org.kakaoshare.backend.domain.funding.vo.FundingHistoryDate; -import org.kakaoshare.backend.domain.member.dto.oauth.profile.detail.KakaoFriendListDto; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class FundingDetailService { private final FundingDetailRepository fundingDetailRepository; - private final KakaoFriendService kakaoFriendService; public PageResponse lookUp(final String providerId, final ContributedFundingHistoryRequest contributedFundingHistoryRequest, @@ -45,36 +38,8 @@ private Page getFundingDetailHistoryDto(final Stri return fundingDetailRepository.findHistoryByCondition(providerId, date, status, pageable); } - public PageResponse getTopContributors(Long fundingId, Pageable pageable, String accessToken) { - Page fundingDetails = fundingDetailRepository.findTopContributorsByFundingId(fundingId, pageable); - - List friendsList = kakaoFriendService.getFriendsList(accessToken); - - List responses = fundingDetails.stream() - .map(detail -> { - KakaoFriendListDto friendProfile = findFriendProfile(detail.getMember().getProviderId(), friendsList); - return FundingContributorResponse.of( - friendProfile.getProfileThumbnailImage(), - friendProfile.getProfileNickname(), - detail.getAmount(), - calculateContributionPercentage(detail) - ); - }).toList(); - - Page contributorResponses = new PageImpl<>(responses, pageable, fundingDetails.getTotalElements()); - return PageResponse.from(contributorResponses); - } - - private KakaoFriendListDto findFriendProfile(String providerId, List friendsList) { - return friendsList.stream() - .filter(friend -> friend.getId().equals(providerId)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("No matching friend found for providerId: " + providerId)); - } - - - - private double calculateContributionPercentage(FundingDetail detail) { - return 100.0 * detail.getAmount() / detail.getFunding().getGoalAmount(); + public PageResponse getTopContributors(final Long fundingId, final Pageable pageable) { + final Page page = fundingDetailRepository.findTopContributorsByFundingId(fundingId, pageable); + return PageResponse.from(page); } } From 9c63dd5a02227dcdbf6be7626c2256e2b81226a8 Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:43:41 +0900 Subject: [PATCH 3/8] =?UTF-8?q?[feat]TopContributorResponse=20DTO=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- .../funding/dto/rank/response/TopContributorResponse.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/org/kakaoshare/backend/domain/funding/dto/rank/response/TopContributorResponse.java diff --git a/src/main/java/org/kakaoshare/backend/domain/funding/dto/rank/response/TopContributorResponse.java b/src/main/java/org/kakaoshare/backend/domain/funding/dto/rank/response/TopContributorResponse.java new file mode 100644 index 000000000..bf7b63b63 --- /dev/null +++ b/src/main/java/org/kakaoshare/backend/domain/funding/dto/rank/response/TopContributorResponse.java @@ -0,0 +1,8 @@ +package org.kakaoshare.backend.domain.funding.dto.rank.response; + +public record TopContributorResponse( + String profileUrl, + String name, + Double rate +) { +} From 96f89de47719c2bc3aa6fe4b8f38a8ae021f87b1 Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:44:08 +0900 Subject: [PATCH 4/8] =?UTF-8?q?[feat]getTopContributors()=20=EC=97=94?= =?UTF-8?q?=EB=93=9C=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=88=98=EC=A0=95=20(#330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- .../funding/controller/FundingController.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/kakaoshare/backend/domain/funding/controller/FundingController.java b/src/main/java/org/kakaoshare/backend/domain/funding/controller/FundingController.java index 60b3eee62..12439882b 100644 --- a/src/main/java/org/kakaoshare/backend/domain/funding/controller/FundingController.java +++ b/src/main/java/org/kakaoshare/backend/domain/funding/controller/FundingController.java @@ -1,16 +1,14 @@ package org.kakaoshare.backend.domain.funding.controller; -import java.util.List; import lombok.RequiredArgsConstructor; import org.kakaoshare.backend.common.dto.PageResponse; - -import org.kakaoshare.backend.domain.funding.dto.FundingCheckRequest; -import org.kakaoshare.backend.domain.funding.dto.inquiry.request.FriendFundingInquiryRequest; import org.kakaoshare.backend.domain.funding.dto.FriendFundingItemRequest; +import org.kakaoshare.backend.domain.funding.dto.FundingCheckRequest; import org.kakaoshare.backend.domain.funding.dto.FundingResponse; import org.kakaoshare.backend.domain.funding.dto.ProgressResponse; import org.kakaoshare.backend.domain.funding.dto.RegisterRequest; import org.kakaoshare.backend.domain.funding.dto.RegisterResponse; +import org.kakaoshare.backend.domain.funding.dto.inquiry.request.FriendFundingInquiryRequest; import org.kakaoshare.backend.domain.funding.dto.preview.request.FundingPreviewRequest; import org.kakaoshare.backend.domain.funding.dto.preview.response.FundingPreviewResponse; import org.kakaoshare.backend.domain.funding.entity.FundingStatus; @@ -24,18 +22,21 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @RequiredArgsConstructor @RestController @RequestMapping("/api/v1") public class FundingController { + private static final int DEFAULT_FUNDING_SIZE = 20; + private static final int DEFAULT_TOP_CONTRIBUTORS_SIZE = 5; + private final FundingService fundingService; private final FundingDetailService fundingDetailService; - private static final int FUNDING_DEFAULT_SIZE = 20; @PostMapping("/funding/{productId}") public ResponseEntity registerFunding(@PathVariable("productId") Long productId, @@ -74,7 +75,7 @@ public ResponseEntity getFriendsActiveFundingItems(@LoggedInMember String pro @GetMapping("/members/funding/products") public ResponseEntity getMyAllFundingProducts(@LoggedInMember String providerId, @RequestParam(name = "status", required = false) FundingStatus status, - @PageableDefault(size = FUNDING_DEFAULT_SIZE) final Pageable pageable) { + @PageableDefault(size = DEFAULT_FUNDING_SIZE) final Pageable pageable) { PageResponse response = fundingService.getMyFilteredFundingProducts(providerId, status, pageable); return ResponseEntity.ok(response); } @@ -85,14 +86,10 @@ public ResponseEntity preview(@RequestBody final FundingPreviewRequest fundin return ResponseEntity.ok(fundingPreviewResponse); } - @GetMapping("/{fundingId}/contributors") - public ResponseEntity getTopContributors(@PathVariable Long fundingId, - @PageableDefault(size = 5) Pageable pageable, - @RequestHeader("Authorization") String accessToken) { - - accessToken = accessToken.substring("Bearer ".length()); - PageResponse contributors = fundingDetailService.getTopContributors(fundingId, pageable, - accessToken); - return ResponseEntity.ok(contributors); + @GetMapping("/funding/{fundingId}/contributors") + public ResponseEntity getTopContributors(@PathVariable final Long fundingId, + @PageableDefault(size = DEFAULT_TOP_CONTRIBUTORS_SIZE) final Pageable pageable) { + final PageResponse response = fundingDetailService.getTopContributors(fundingId, pageable); + return ResponseEntity.ok(response); } } From 9dce30493ecf6a716bcd5e985bf0bd55829775e7 Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:44:29 +0900 Subject: [PATCH 5/8] =?UTF-8?q?[test]=EC=B5=9C=EB=8C=80=20=EA=B8=B0?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EC=A1=B0=ED=9A=8C=20Service=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- .../service/FundingDetailServiceTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/test/java/org/kakaoshare/backend/domain/funding/service/FundingDetailServiceTest.java b/src/test/java/org/kakaoshare/backend/domain/funding/service/FundingDetailServiceTest.java index dcc3c2b7a..d6d37e4e0 100644 --- a/src/test/java/org/kakaoshare/backend/domain/funding/service/FundingDetailServiceTest.java +++ b/src/test/java/org/kakaoshare/backend/domain/funding/service/FundingDetailServiceTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EmptySource; @@ -12,6 +13,7 @@ import org.kakaoshare.backend.domain.funding.dto.inquiry.ContributedFundingHistoryDto; import org.kakaoshare.backend.domain.funding.dto.inquiry.request.ContributedFundingHistoryRequest; import org.kakaoshare.backend.domain.funding.dto.inquiry.response.ContributedFundingHistoryResponse; +import org.kakaoshare.backend.domain.funding.dto.rank.response.TopContributorResponse; import org.kakaoshare.backend.domain.funding.repository.FundingDetailRepository; import org.kakaoshare.backend.domain.funding.vo.FundingHistoryDate; import org.kakaoshare.backend.domain.member.entity.Member; @@ -156,6 +158,25 @@ public void lookUpWhenInvalidDateRange(final String status) throws Exception { .isInstanceOf(DateException.class); } + + @Test + @DisplayName("최대 기여자 조회") + public void getTopContributors() throws Exception { + final Long fundingId = 1L; + final List content = List.of( + new TopContributorResponse("profileUrl1", "테스터1", 30.0), + new TopContributorResponse("profileUrl1", "테스터2", 20.0), + new TopContributorResponse("profileUrl1", "테스터3", 10.0) + ); + + final Page page = new PageImpl<>(content, pageable, content.size()); + doReturn(page).when(fundingDetailRepository).findTopContributorsByFundingId(fundingId, pageable); + + final PageResponse expect = PageResponse.from(page); + final PageResponse actual = fundingDetailService.getTopContributors(fundingId, pageable); + assertThat(actual).usingRecursiveComparison().isEqualTo(expect); + } + private ProductDto getProductDto(final Product product) { return new ProductDto( product.getProductId(), From d66e1c4080b355a5fefa17cba69deebbb5c4316d Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:44:36 +0900 Subject: [PATCH 6/8] =?UTF-8?q?[test]=EC=B5=9C=EB=8C=80=20=EA=B8=B0?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EC=A1=B0=ED=9A=8C=20Repository=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- .../FundingDetailRepositoryTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepositoryTest.java diff --git a/src/test/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepositoryTest.java b/src/test/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepositoryTest.java new file mode 100644 index 000000000..cbc6050fd --- /dev/null +++ b/src/test/java/org/kakaoshare/backend/domain/funding/repository/FundingDetailRepositoryTest.java @@ -0,0 +1,32 @@ +package org.kakaoshare.backend.domain.funding.repository; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.kakaoshare.backend.common.RepositoryTest; +import org.kakaoshare.backend.domain.funding.dto.rank.response.TopContributorResponse; +import org.springframework.beans.factory.annotation.Autowired; +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 java.util.List; + +@RepositoryTest +class FundingDetailRepositoryTest { + @Autowired + FundingDetailRepository fundingDetailRepository; + + @Test + @DisplayName("최대 기여자 조회") + public void findTopContributorsByFundingId() throws Exception { + final Long fundingId = 1L; + final Pageable pageable = PageRequest.of(0, 5, Sort.by(Sort.Direction.DESC, "rate")); + final Page page = fundingDetailRepository.findTopContributorsByFundingId(fundingId, pageable); + final List content = page.getContent(); + Assertions.assertThat(content.get(0).rate()).isEqualTo(30.0); + Assertions.assertThat(content.get(1).rate()).isEqualTo(20.0); + Assertions.assertThat(content.get(2).rate()).isEqualTo(10.0); + } +} \ No newline at end of file From 0b0956f7c96c5f9b76d516c84fd9842c35448446 Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:44:49 +0900 Subject: [PATCH 7/8] =?UTF-8?q?[feat]Payment=20=EB=8D=94=EB=AF=B8=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20SQL=20=EC=B6=94=EA=B0=80=20(#330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- src/main/resources/testdata/initial_5_payment.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/resources/testdata/initial_5_payment.sql diff --git a/src/main/resources/testdata/initial_5_payment.sql b/src/main/resources/testdata/initial_5_payment.sql new file mode 100644 index 000000000..9925c99d6 --- /dev/null +++ b/src/main/resources/testdata/initial_5_payment.sql @@ -0,0 +1,4 @@ +INSERT INTO payment (created_at, delivery_price, payment_id, purchase_price, total_price, payment_number, method) +VALUES (NOW(), 0, 1, 3000, 3000, '1', 'KAKAO_PAY'), + (NOW(), 0, 2, 2000, 2000, '2', 'KAKAO_PAY'), + (NOW(), 0, 3, 1000, 1000, '3', 'KAKAO_PAY'); \ No newline at end of file From 8da2ad82550d85ba8bdee2ae4c828f8cd461ecda Mon Sep 17 00:00:00 2001 From: kmw2378 Date: Fri, 19 Jul 2024 23:44:56 +0900 Subject: [PATCH 8/8] =?UTF-8?q?[feat]FundingDetail=20=EB=8D=94=EB=AF=B8=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20SQL=20=EC=B6=94=EA=B0=80=20(#330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: kmw2378 --- src/main/resources/testdata/initial_6_funding_detail.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/resources/testdata/initial_6_funding_detail.sql diff --git a/src/main/resources/testdata/initial_6_funding_detail.sql b/src/main/resources/testdata/initial_6_funding_detail.sql new file mode 100644 index 000000000..8505d37f4 --- /dev/null +++ b/src/main/resources/testdata/initial_6_funding_detail.sql @@ -0,0 +1,4 @@ +INSERT INTO funding_detail (created_at, amount, rate, funding_id, payment_id, member_id, status) +VALUES (NOW(), 3000, 30.0, 1, 1, 1, 'PROGRESS'), + (NOW(), 2000, 20.0, 1, 1, 2, 'PROGRESS'), + (NOW(), 1000, 10.0, 1, 1, 3, 'PROGRESS'); \ No newline at end of file