From 25d4589814d4ade689d2833b90c2a10126ae9b15 Mon Sep 17 00:00:00 2001 From: winter-you Date: Sun, 9 Oct 2022 17:19:46 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=9D=B8=EC=82=AC=EC=9D=B4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=EC=9E=90=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/insight/InsightController.java | 6 +++ .../keeweapi/component/InsightAssembler.java | 14 +++++- .../insight/InsightAuthorAreaResponse.java | 20 ++++++++ .../service/insight/InsightApiService.java | 8 +++ .../api/insight/InsightControllerTest.java | 50 +++++++++++++++++++ .../insight/InsightQueryRepository.java | 28 +++++++++++ .../repository/insight/InsightRepository.java | 2 +- .../service/insight/InsightDomainService.java | 9 +++- .../keeweinfra/service/MQPublishService.java | 2 +- 9 files changed, 133 insertions(+), 6 deletions(-) create mode 100644 keewe-api/src/main/java/ccc/keeweapi/dto/insight/InsightAuthorAreaResponse.java create mode 100644 keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightQueryRepository.java diff --git a/keewe-api/src/main/java/ccc/keeweapi/api/insight/InsightController.java b/keewe-api/src/main/java/ccc/keeweapi/api/insight/InsightController.java index b34b0f17..5f0b8835 100644 --- a/keewe-api/src/main/java/ccc/keeweapi/api/insight/InsightController.java +++ b/keewe-api/src/main/java/ccc/keeweapi/api/insight/InsightController.java @@ -1,6 +1,7 @@ package ccc.keeweapi.api.insight; import ccc.keeweapi.dto.ApiResponse; +import ccc.keeweapi.dto.insight.InsightAuthorAreaResponse; import ccc.keeweapi.dto.insight.InsightCreateRequest; import ccc.keeweapi.dto.insight.InsightCreateResponse; import ccc.keeweapi.service.insight.InsightApiService; @@ -26,4 +27,9 @@ public ApiResponse incrementViewCount(@PathVariable Long insightId) { return ApiResponse.ok(insightApiService.incrementViewCount(insightId)); } + @GetMapping("/author/{insightId}") + public ApiResponse getInsightAuthorAreaInfo(@PathVariable Long insightId) { + return ApiResponse.ok(insightApiService.getInsightAuthorAreaInfo(insightId)); + } + } diff --git a/keewe-api/src/main/java/ccc/keeweapi/component/InsightAssembler.java b/keewe-api/src/main/java/ccc/keeweapi/component/InsightAssembler.java index 828d3a56..1890d121 100644 --- a/keewe-api/src/main/java/ccc/keeweapi/component/InsightAssembler.java +++ b/keewe-api/src/main/java/ccc/keeweapi/component/InsightAssembler.java @@ -2,11 +2,12 @@ import ccc.keeweapi.dto.insight.*; import ccc.keeweapi.utils.SecurityUtil; -import ccc.keewedomain.persistence.domain.insight.Drawer; -import ccc.keewedomain.persistence.domain.insight.Insight; import ccc.keewedomain.dto.insight.DrawerCreateDto; import ccc.keewedomain.dto.insight.InsightCreateDto; import ccc.keewedomain.dto.insight.InsightViewIncrementDto; +import ccc.keewedomain.persistence.domain.insight.Drawer; +import ccc.keewedomain.persistence.domain.insight.Insight; +import ccc.keewedomain.persistence.domain.user.User; import org.springframework.stereotype.Component; @Component @@ -39,4 +40,13 @@ public InsightViewIncrementDto toInsightViewIncrementDto(Long insightId) { public InsightViewIncrementResponse toInsightViewIncrementResponse(Long viewCount) { return InsightViewIncrementResponse.of(viewCount); } + + public InsightAuthorAreaResponse toInsightAuthorAreaResponse(Insight insight) { + User writer = insight.getWriter(); + return InsightAuthorAreaResponse.of(insight.getId(), writer.getNickname(), "title", writer.getInterests(), "www.api-keewe.com/images" , isAuthor(insight), insight.getCreatedAt().toString()); + } + + private boolean isAuthor(Insight insight) { + return insight.getWriter().getId() == SecurityUtil.getUserId(); + } } diff --git a/keewe-api/src/main/java/ccc/keeweapi/dto/insight/InsightAuthorAreaResponse.java b/keewe-api/src/main/java/ccc/keeweapi/dto/insight/InsightAuthorAreaResponse.java new file mode 100644 index 00000000..3d049915 --- /dev/null +++ b/keewe-api/src/main/java/ccc/keeweapi/dto/insight/InsightAuthorAreaResponse.java @@ -0,0 +1,20 @@ +package ccc.keeweapi.dto.insight; + + +import ccc.keewedomain.persistence.domain.common.Interest; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@AllArgsConstructor(staticName = "of") +@Getter +public class InsightAuthorAreaResponse { + private Long authorId; + private String nickname; + private String title; + private List interests; + private String image; + private boolean isAuthor; + private String createdAt; +} diff --git a/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java b/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java index 2ec571c5..8fc6be89 100644 --- a/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java +++ b/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java @@ -1,6 +1,7 @@ package ccc.keeweapi.service.insight; import ccc.keeweapi.component.InsightAssembler; +import ccc.keeweapi.dto.insight.InsightAuthorAreaResponse; import ccc.keeweapi.dto.insight.InsightCreateRequest; import ccc.keeweapi.dto.insight.InsightCreateResponse; import ccc.keeweapi.dto.insight.InsightViewIncrementResponse; @@ -8,6 +9,7 @@ import ccc.keewedomain.service.insight.InsightDomainService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -25,4 +27,10 @@ public InsightViewIncrementResponse incrementViewCount(Long insightId) { Long viewCount = insightDomainService.incrementViewCount(insightAssembler.toInsightViewIncrementDto(insightId)); return insightAssembler.toInsightViewIncrementResponse(viewCount); } + + @Transactional(readOnly = true) + public InsightAuthorAreaResponse getInsightAuthorAreaInfo(Long insightId) { + Insight insight = insightDomainService.getInsight(insightId); + return insightAssembler.toInsightAuthorAreaResponse(insight); + } } diff --git a/keewe-api/src/test/java/ccc/keeweapi/api/insight/InsightControllerTest.java b/keewe-api/src/test/java/ccc/keeweapi/api/insight/InsightControllerTest.java index 3acfb9cb..e3522633 100644 --- a/keewe-api/src/test/java/ccc/keeweapi/api/insight/InsightControllerTest.java +++ b/keewe-api/src/test/java/ccc/keeweapi/api/insight/InsightControllerTest.java @@ -1,9 +1,11 @@ package ccc.keeweapi.api.insight; import ccc.keeweapi.document.utils.ApiDocumentationTest; +import ccc.keeweapi.dto.insight.InsightAuthorAreaResponse; import ccc.keeweapi.dto.insight.InsightCreateResponse; import ccc.keeweapi.dto.insight.InsightViewIncrementResponse; import ccc.keeweapi.service.insight.InsightApiService; +import ccc.keewedomain.persistence.domain.common.Interest; import com.epages.restdocs.apispec.ResourceSnippetParameters; import org.json.JSONObject; import org.junit.jupiter.api.BeforeEach; @@ -16,11 +18,15 @@ import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.test.web.servlet.ResultActions; +import java.time.LocalDateTime; +import java.util.List; + import static com.epages.restdocs.apispec.ResourceDocumentation.headerWithName; import static com.epages.restdocs.apispec.ResourceDocumentation.resource; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.when; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -107,4 +113,48 @@ void increment_insight_views() throws Exception { .build() ))); } + + @Test + @DisplayName("인사이트 작성자 프로필 조회 API") + void insight_author_get() throws Exception { + + when(insightApiService.getInsightAuthorAreaInfo(anyLong())).thenReturn( + InsightAuthorAreaResponse.of(1L, + "nickname", + "고급 기록가", + List.of(Interest.of("운동"), Interest.of("영화")), + "www.api-keewe.com/images/128398681", + true, + LocalDateTime.now().toString() + ) + ); + + ResultActions resultActions = mockMvc.perform(get("/api/v1/insight/author/{insightId}", 1L) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + JWT) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + + resultActions.andDo(restDocs.document(resource( + ResourceSnippetParameters.builder() + .description("인사이트 상세 조회 작성자 프로필 조회 API 입니다.") + .summary("인사이트 작성자 프로필 조회 API") + .requestHeaders( + headerWithName("Authorization").description("유저의 JWT")) + .responseFields( + fieldWithPath("message").description("요청 결과 메세지"), + fieldWithPath("code").description("결과 코드"), + fieldWithPath("data.authorId").description("작성자 ID (유저 ID)"), + fieldWithPath("data.nickname").description("작성자 닉네임"), + fieldWithPath("data.title").description("작성자 대표 타이틀 (업적)"), + fieldWithPath("data.interests[].name").description("작성자 관심사 목록"), + fieldWithPath("data.image").description("작성자 프로필 이미지 링크"), + fieldWithPath("data.author").description("인사이트 조회자와 작성자 일치 여부"), + fieldWithPath("data.createdAt").description("작성자 닉네임")) + .tag("Insight") + .build() + ))); + + } + + } diff --git a/keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightQueryRepository.java b/keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightQueryRepository.java new file mode 100644 index 00000000..7eb2f4b9 --- /dev/null +++ b/keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightQueryRepository.java @@ -0,0 +1,28 @@ +package ccc.keewedomain.persistence.repository.insight; + +import ccc.keewedomain.persistence.domain.insight.Insight; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import static ccc.keewedomain.persistence.domain.common.QInterest.interest; +import static ccc.keewedomain.persistence.domain.insight.QInsight.insight; +import static ccc.keewedomain.persistence.domain.user.QUser.user; + +@Repository +@RequiredArgsConstructor +public class InsightQueryRepository { + private final JPAQueryFactory queryFactory; + + public Insight findByIdWithWriter(Long insightId) { + return queryFactory.select(insight) + .from(insight) + .where(insight.id.eq(insightId)) + .leftJoin(insight.writer, user) + .fetchJoin() + .leftJoin(user.interests, interest) + .fetchJoin() + .fetchOne(); + + } +} diff --git a/keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightRepository.java b/keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightRepository.java index 999c66eb..c503506f 100644 --- a/keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightRepository.java +++ b/keewe-domain/src/main/java/ccc/keewedomain/persistence/repository/insight/InsightRepository.java @@ -17,7 +17,7 @@ public interface InsightRepository extends JpaRepository { @Query(value = "select i from Insight i where i.id = :id") Optional findByIdWithReadWriteLock(@Param("id") Long id); - default Insight findByIdOrElseThrow(Long id) { + default Insight findByIdWithLockOrElseThrow(Long id) { return findByIdWithReadWriteLock(id).orElseThrow(() -> new KeeweException(KeeweRtnConsts.ERR445)); } } diff --git a/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java b/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java index e9c64c7a..169e6d5a 100644 --- a/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java +++ b/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java @@ -10,6 +10,7 @@ import ccc.keewedomain.persistence.domain.insight.Drawer; import ccc.keewedomain.persistence.domain.insight.Insight; import ccc.keewedomain.persistence.domain.user.User; +import ccc.keewedomain.persistence.repository.insight.InsightQueryRepository; import ccc.keewedomain.persistence.repository.insight.InsightRepository; import ccc.keewedomain.service.challenge.ChallengeDomainService; import ccc.keewedomain.service.user.UserDomainService; @@ -29,7 +30,7 @@ public class InsightDomainService { private final UserDomainService userDomainService; private final ChallengeDomainService challengeDomainService; private final DrawerDomainService drawerDomainService; - + private final InsightQueryRepository insightQueryRepository; private final CInsightViewRepository cInsightViewRepository; //TODO 참가한 챌린지에 기록하기 @@ -55,11 +56,15 @@ public Long incrementViewCount(InsightViewIncrementDto dto) { @Transactional public Long incrementViewCount(Long insightId) { - Insight insight = insightRepository.findByIdOrElseThrow(insightId); + Insight insight = insightRepository.findByIdWithLockOrElseThrow(insightId); log.info("[IDS::incrementViewCount] DB Curr view {}, Next view {}", insight.getView(), insight.getView() + 1); return incrementViewCount(insight); } + public Insight getInsight(Long insightId) { + return insightQueryRepository.findByIdWithWriter(insightId); + } + private Long incrementViewCount(Insight insight) { Long viewCount = insight.incrementView(); diff --git a/keewe-infra/src/main/java/ccc/keeweinfra/service/MQPublishService.java b/keewe-infra/src/main/java/ccc/keeweinfra/service/MQPublishService.java index c0fe07e1..8641def6 100644 --- a/keewe-infra/src/main/java/ccc/keeweinfra/service/MQPublishService.java +++ b/keewe-infra/src/main/java/ccc/keeweinfra/service/MQPublishService.java @@ -13,7 +13,7 @@ public class MQPublishService { private final RabbitTemplate rabbitTemplate; //TODO: retry handler 도입 - public void publish(String exchange, Object body) { + public void publish(String exchange, T body) { rabbitTemplate.convertAndSend(exchange , KeeweConsts.DEFAULT_ROUTING_KEY , body); From 08d22af24b9468099074ad977083af519e4737b1 Mon Sep 17 00:00:00 2001 From: winter-you Date: Sun, 9 Oct 2022 17:26:07 +0900 Subject: [PATCH 2/2] =?UTF-8?q?method=20=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ccc/keeweapi/service/insight/InsightApiService.java | 2 +- .../ccc/keewedomain/service/insight/InsightDomainService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java b/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java index 8fc6be89..53c618e0 100644 --- a/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java +++ b/keewe-api/src/main/java/ccc/keeweapi/service/insight/InsightApiService.java @@ -30,7 +30,7 @@ public InsightViewIncrementResponse incrementViewCount(Long insightId) { @Transactional(readOnly = true) public InsightAuthorAreaResponse getInsightAuthorAreaInfo(Long insightId) { - Insight insight = insightDomainService.getInsight(insightId); + Insight insight = insightDomainService.getByIdWithWriter(insightId); return insightAssembler.toInsightAuthorAreaResponse(insight); } } diff --git a/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java b/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java index aa13763a..af3f0260 100644 --- a/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java +++ b/keewe-domain/src/main/java/ccc/keewedomain/service/insight/InsightDomainService.java @@ -77,7 +77,7 @@ public Long incrementViewCount(Long insightId) { return incrementViewCount(insight); } - public Insight getInsight(Long insightId) { + public Insight getByIdWithWriter(Long insightId) { return insightQueryRepository.findByIdWithWriter(insightId); }