Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] 마이페이지 인사이트 조회 #159

Merged
merged 5 commits into from
Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ccc.keeweapi.dto.ApiResponse;
import ccc.keeweapi.dto.insight.*;
import ccc.keeweapi.service.insight.InsightApiService;
import ccc.keewecore.consts.KeeweConsts;
import ccc.keewedomain.persistence.repository.utils.CursorPageable;
import lombok.RequiredArgsConstructor;
import org.springframework.lang.Nullable;
Expand Down Expand Up @@ -56,4 +57,14 @@ public ApiResponse<BookmarkToggleResponse> toggleBookmark(@PathVariable Long ins
public ApiResponse<ChallengeRecordResponse> getChallengeRecord(@PathVariable Long insightId) {
return ApiResponse.ok(insightApiService.getChallengeRecord(insightId));
}

@GetMapping("/my-page/{userId}")
public ApiResponse<List<InsightMyPageResponse>> getInsightForMyPage(
@PathVariable Long userId,
@RequestParam(required = false) Long drawerId,
@RequestParam(required = false, defaultValue = KeeweConsts.LONG_MAX_STRING) Long cursor,
@RequestParam Long limit) {

return ApiResponse.ok(insightApiService.getInsightsForMyPage(userId, drawerId, CursorPageable.of(cursor, limit)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,17 @@ public ChallengeRecordResponse toChallengeRecordResponse(Challenge challenge) {
return ChallengeRecordResponse.of(challenge.getId(), challenge.getName(), null, null);
}

public InsightMyPageResponse toInsightMyPageResponse(InsightMyPageDto dto) {
return InsightMyPageResponse.of(
dto.getId(),
dto.getContents(),
dto.getLink(),
toReactionAggregationResponse(dto.getReaction()),
dto.getCreatedAt().toString(),
dto.isBookmark()
);
}

private boolean isAuthor(Insight insight) {
return insight.getWriter().getId() == SecurityUtil.getUserId();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ccc.keeweapi.dto.insight;

import ccc.keewedomain.persistence.domain.common.Link;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor(staticName = "of")
public class InsightMyPageResponse {
private Long id;
private String contents;
private Link link;
private ReactionAggregationResponse reaction;
private String createdAt;
private boolean isBookmark;
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,11 @@ public ChallengeRecordResponse getChallengeRecord(Long insightId) {

return insightAssembler.toChallengeRecordResponse(participation.getChallenge());
}

@Transactional(readOnly = true)
public List<InsightMyPageResponse> getInsightsForMyPage(Long userId, Long drawerId, CursorPageable<Long> cPage) {
return insightDomainService.getByUserId(SecurityUtil.getUser(), userId, drawerId, cPage).stream()
.map(insightAssembler::toInsightMyPageResponse)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ccc.keewedomain.dto.insight.ReactionAggregationGetDto;
import ccc.keewedomain.persistence.domain.common.Link;
import ccc.keewedomain.persistence.domain.common.Interest;
import ccc.keewedomain.persistence.repository.utils.CursorPageable;
import com.epages.restdocs.apispec.ResourceSnippetParameters;
import org.json.JSONObject;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -318,4 +319,82 @@ void insight_challenge_record() throws Exception {
)));
}

@Test
@DisplayName("마이페이지 인사이트 조회 API")
void get_insight_my_page_test() throws Exception {
Long targetUserId = 1L;
Long drawerId = 5L;
CursorPageable<Long> cPage = CursorPageable.of(15L, 3L);

InsightMyPageResponse insight1 = InsightMyPageResponse.of(
30L,
"세 번째 인사이트 내용입니다. 즐거운 개발 되세요!",
Link.of("www.keewe.com"),
ReactionAggregationResponse.of(1L, 2L, 3L, 4L, 5L, 6L),
LocalDateTime.now().toString(),
true
);

InsightMyPageResponse insight2 = InsightMyPageResponse.of(
24L,
"두 번째 인사이트 내용입니다. 즐거운 개발 되세요!",
Link.of("www.keewe.com"),
ReactionAggregationResponse.of(1L, 2L, 3L, 4L, 5L, 6L),
LocalDateTime.now().minusDays(1L).toString(),
true
);

InsightMyPageResponse insight3 = InsightMyPageResponse.of(
7L,
"첫 번째 인사이트 내용입니다. 즐거운 개발 되세요!",
Link.of("www.keewe.com"),
ReactionAggregationResponse.of(1L, 2L, 3L, 4L, 5L, 6L),
LocalDateTime.now().minusDays(2L).toString(),
true
);




when(insightApiService.getInsightsForMyPage(any(), any(), any()))
.thenReturn(List.of(insight1, insight2, insight3));

ResultActions resultActions = mockMvc.perform(get("/api/v1/insight/my-page/{userId}", targetUserId)
.param("cursor", String.valueOf(cPage.getCursor()))
.param("limit", String.valueOf(cPage.getLimit()))
.param("drawerId", String.valueOf(drawerId))
.header(HttpHeaders.AUTHORIZATION, "Bearer " + JWT))
.andExpect(status().isOk());

resultActions.andDo(restDocs.document(resource(
ResourceSnippetParameters.builder()
.description("마이페이지 인사이트 조회 API 입니다. 파라미터 optional 표시 잘 봐주세요")
.summary("마이페이지 인사이트 조회 API")
.pathParameters(
parameterWithName("userId").description("대상 유저의 ID"))
.requestParameters(
parameterWithName("cursor").description("대상 인사이트의 ID(첫 조회시 비우세요").optional(),
parameterWithName("limit").description("가져올 인사이트의 개수"),
parameterWithName("drawerId").description("폴더의 ID(전체 조회 시 비우세요)").optional())
.requestHeaders(
headerWithName("Authorization").description("유저의 JWT"))
.responseFields(
fieldWithPath("message").description("요청 결과 메세지"),
fieldWithPath("code").description("결과 코드"),
fieldWithPath("data[].id").description("인사이트 ID"),
fieldWithPath("data[].contents").description("인사이트 내용"),
fieldWithPath("data[].link.url").description("인사이트 링크"),
fieldWithPath("data[].createdAt").description("인사이트 생성 시각"),
fieldWithPath("data[].reaction.clap").description("인사이트 박수 반응 수"),
fieldWithPath("data[].reaction.heart").description("인사이트 하트 반응 수"),
fieldWithPath("data[].reaction.sad").description("인사이트 슬픔 반응 수"),
fieldWithPath("data[].reaction.surprise").description("인사이트 놀람 반응 수"),
fieldWithPath("data[].reaction.fire").description("인사이트 불 반응 수"),
fieldWithPath("data[].reaction.eyes").description("인사이트 눈 반응 수"),
fieldWithPath("data[].bookmark").description("인사이트 북마크 여부"))
.tag("Insight")
.build()
)));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ccc.keewedomain.dto.insight;

import ccc.keewedomain.persistence.domain.common.Link;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor(staticName = "of")
public class InsightMyPageDto {
private Long id;
private String contents;
private Link link;
private ReactionAggregationGetDto reaction;
private LocalDateTime createdAt;
private boolean isBookmark;
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class Insight extends BaseTimeEntity {
@OneToMany(mappedBy = "insight", fetch = LAZY)
private List<Comment> comments = new ArrayList<>();

@ManyToOne
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "drawer_id")
private Drawer drawer;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,22 @@ public Long countValidByIdBeforeAndParticipation(ChallengeParticipation particip
.and(insight.id.lt(insightId)))
.fetchFirst();
}

public List<Insight> findByUserIdAndDrawerId(Long userId, Long drawerId, CursorPageable<Long> cPage) {
return queryFactory
.select(insight)
.from(insight)
.where(insight.writer.id.eq(userId)
.and(insight.id.lt(cPage.getCursor()))
.and(drawerIdEq(drawerId))
)
.orderBy(insight.id.desc())
.limit(cPage.getLimit())
.fetch();
}


private BooleanExpression drawerIdEq(Long drawerId) {
return drawerId != null ? insight.drawer.id.eq(drawerId) : null;
}
Comment on lines +111 to +128
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drawerId가 Null인 케이스는 서랍 탭 중에 전체인 경우죠?

그럼 조건이 equal null로 들어가면 전체 조회가 안되지 않을까여?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 drawerId가 null이면 전체인 경우에요

저렇게 사용하면 drawerId가 null인 경우 and(null)로 들어가면 파라미터가 null로 들어가서 조건문에서 제외돼요.
그래서 drawerId가 null인 경우에 아래처럼 쿼리가 나갑니다.
where
insight0_.writer_id=?
and insight0_.insight_id<?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아.. 그냥 뭉탱이로 Null이면 상관없나요

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 확인했습니닷

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 querydsl의 where에서 파라미터가 null인 경우에는 제외한다고 하네요

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -177,6 +176,22 @@ public Long getThisWeekCount(ChallengeParticipation participation, LocalDateTime
return insightQueryRepository.countByParticipationBetween(participation, startDate, endDate);
}

@Transactional(readOnly = true)
public List<InsightMyPageDto> getByUserId(User user, Long targetUserId, Long drawerId, CursorPageable<Long> cPage) {
List<Insight> insights = insightQueryRepository.findByUserIdAndDrawerId(targetUserId, drawerId, cPage);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List를 가져오는것과 단일객체를 가져올때 네이밍 구분이 명확했음 좋겠어요

이름은 userId로만 가져오는 것처럼 단순해보이지만 실제 파라미터는 너무 많아서 그렇지 않은거같기도하구요.ㅎ

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서랍이 추가되기도 하면서 이름이 알맞지 않아보이네요
getInsightsForMyPage로 바꾸겠습니다

Map<Long, Boolean> bookmarkPresenceMap = bookmarkQueryRepository.getBookmarkPresenceMap(user, insights);
return insights.parallelStream()
.map(insight -> InsightMyPageDto.of(
insight.getId(),
insight.getContents(),
insight.getLink(),
getReactionAggregation(insight.getId()),
insight.getCreatedAt(),
bookmarkPresenceMap.getOrDefault(insight.getId(), false)
))
.collect(Collectors.toList());
}

/*****************************************************************
********************** private 메소드 영역 분리 *********************
*****************************************************************/
Expand Down
13 changes: 8 additions & 5 deletions scripts/batch_deploy.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
JAR_DIR='/home/ubuntu/'$2

cp keewe-batch/build/libs/keewe-batch-0.0.1-SNAPSHOT.jar ${JAR_DIR}/

echo "> Auto batch deploy starting...."

mkdir $JAR_DIR
mkdir -p $JAR_DIR
cd $JAR_DIR

ORIGIN_JAR_PATH= "${JAR_DIR}/*.jar"
chmod 770 ${JAR_DIR}/$1-0.0.1-SNAPSHOT.jar
ORIGIN_JAR_PATH="${JAR_DIR}/$1-0.0.1-SNAPSHOT.jar"
ORIGIN_JAR_NAME=$(basename ${ORIGIN_JAR_PATH})
TARGET_PATH="${JAR_DIR}/batch-application.jar"

echo "> Do deploy :: $1"
echo " > 배포 JAR: "${ORIGIN_JAR_NAME}

echo " > sudo ln -s -f ${JAR_DIR}${ORIGIN_JAR_NAME} ${TARGET_PATH}"
sudo ln -s -f ${JAR_DIR}${ORIGIN_JAR_NAME} ${TARGET_PATH}
echo " > sudo ln -s -f ${JAR_DIR}/${ORIGIN_JAR_NAME} ${TARGET_PATH}"
ln -s -f "${JAR_DIR}/${ORIGIN_JAR_NAME} ${TARGET_PATH}"

echo "> Batch deploy Complete ! !"
echo "> Batch deploy Complete ! !"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JAR_DIR /로 끝나면 잘되나요?ㅎㅋ

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

되기는 하는데 다른 데서도 안붙여서 떼는게 좋아 보여요

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보니까 젠킨스에서 파라미터 주입하게돼있던데 파라미터 혹시 잘못넣으면 걱정돼서요 ㅎ

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 거기까진 생각 못했네요