Skip to content

Commit

Permalink
Refactor: 마이페이지 내에서 개인 대시보드 조회 기능 추가 & 상대방 프로필은 isPublic이 true인 것만 보이…
Browse files Browse the repository at this point in the history
…도록 수정 (#152)

* Refactor: 마이페이지 내에서 개인 대시보드 조회 기능 추가 & 상대방 프로필은 isPublic이 true인 것만 보이도록 수정

* Docs: mypage 대시보드 & 챌린지 목록 조회 문서 수정

* Test: mypage 개인 대시보드 확인 로직 추가 수정
  • Loading branch information
inhooo00 authored Sep 21, 2024
1 parent 508a8e3 commit d0ced15
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/docs/asciidoc/member.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ include::{snippets}/member/mypage/request-headers.adoc[]
include::{snippets}/member/mypage/http-response.adoc[]
include::{snippets}/member/mypage/response-fields.adoc[]

=== 대시보드와 챌린지 정보 조회 API
=== 대시보드와 챌린지 정보 조회 API

==== 요청

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public interface DashboardCustomRepository {

List<PersonalDashboard> findForPersonalDashboard(Member member);

Page<PersonalDashboard> findForPersonalDashboard(Member member, Pageable pageable);

Set<String> findCategoriesForDashboard(Member member);

Page<TeamDashboard> findForTeamDashboard(Member member, Pageable pageable);
Expand All @@ -22,4 +24,5 @@ public interface DashboardCustomRepository {

double calculateCompletionPercentage(Long dashboardId);

Page<PersonalDashboard> findPublicPersonalDashboard(Member member, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ public List<PersonalDashboard> findForPersonalDashboard(Member member) {
.fetch();
}

@Override
public Page<PersonalDashboard> findForPersonalDashboard(Member member, Pageable pageable) {
long total = queryFactory
.selectFrom(personalDashboard)
.where(personalDashboard._super.member.eq(member)
.and(personalDashboard._super.status.eq(Status.ACTIVE)))
.fetchCount();

List<PersonalDashboard> dashboards = queryFactory
.selectFrom(personalDashboard)
.where(personalDashboard._super.member.eq(member)
.and(personalDashboard._super.status.eq(Status.ACTIVE)))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

return new PageImpl<>(dashboards, pageable, total);
}

@Override
public Set<String> findCategoriesForDashboard(Member member) {
return queryFactory
Expand Down Expand Up @@ -118,4 +137,25 @@ public double calculateCompletionPercentage(Long dashboardId) {

return (double) completedBlocks / totalBlocks * 100;
}

@Override
public Page<PersonalDashboard> findPublicPersonalDashboard(Member member, Pageable pageable) {
long total = queryFactory
.selectFrom(personalDashboard)
.where(personalDashboard._super.member.eq(member)
.and(personalDashboard._super.status.eq(Status.ACTIVE))
.and(personalDashboard.isPublic.eq(true))) // isPublic이 true인 경우
.fetchCount();

List<PersonalDashboard> dashboards = queryFactory
.selectFrom(personalDashboard)
.where(personalDashboard._super.member.eq(member)
.and(personalDashboard._super.status.eq(Status.ACTIVE))
.and(personalDashboard.isPublic.eq(true)))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

return new PageImpl<>(dashboards, pageable, total);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response;

import lombok.Builder;
import shop.kkeujeok.kkeujeokbackend.dashboard.team.api.dto.response.TeamDashboardInfoResDto;
import shop.kkeujeok.kkeujeokbackend.global.dto.PageInfoResDto;

import java.util.List;

@Builder
public record PersonalDashboardPageListResDto(
List<PersonalDashboardInfoResDto> personalDashboardInfoResDto,
PageInfoResDto pageInfoResDto
) {
public static PersonalDashboardPageListResDto of(List<PersonalDashboardInfoResDto> personalDashboards,
PageInfoResDto pageInfoResDto) {
return PersonalDashboardPageListResDto.builder()
.personalDashboardInfoResDto(personalDashboards)
.pageInfoResDto(pageInfoResDto)
.build();
}

public static PersonalDashboardPageListResDto from(List<PersonalDashboardInfoResDto> personalDashboards) {
return PersonalDashboardPageListResDto.builder()
.personalDashboardInfoResDto(personalDashboards)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import java.util.List;
import java.util.Set;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.kkeujeok.kkeujeokbackend.dashboard.exception.DashboardNotFoundException;
Expand All @@ -12,9 +15,11 @@
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response.PersonalDashboardCategoriesResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response.PersonalDashboardInfoResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response.PersonalDashboardListResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response.PersonalDashboardPageListResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.domain.PersonalDashboard;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.domain.repository.PersonalDashboardRepository;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.exception.DashboardAccessDeniedException;
import shop.kkeujeok.kkeujeokbackend.global.dto.PageInfoResDto;
import shop.kkeujeok.kkeujeokbackend.member.domain.Member;
import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository;
import shop.kkeujeok.kkeujeokbackend.member.exception.MemberNotFoundException;
Expand Down Expand Up @@ -115,4 +120,32 @@ private void verifyMemberIsAuthor(PersonalDashboard dashboard, Member member) {
}
}

}
// isPublic이 true인 대시보드 조회 메서드
public PersonalDashboardPageListResDto findPublicPersonalDashboards(String email, Pageable pageable) {
Member member = memberRepository.findByEmail(email).orElseThrow(MemberNotFoundException::new);

Page<PersonalDashboard> publicDashboards = personalDashboardRepository.findPublicPersonalDashboard(member, pageable);

List<PersonalDashboardInfoResDto> publicDashboardInfoResDtoList = publicDashboards.stream()
.map(dashboard -> PersonalDashboardInfoResDto.of(member, dashboard))
.toList();

return PersonalDashboardPageListResDto.of(publicDashboardInfoResDtoList, PageInfoResDto.from(publicDashboards));
}

// 개인 대시보드 전체 조회(페이지네이션 적용)
public PersonalDashboardPageListResDto findForPersonalDashboard(String email, Pageable pageable) {
Member member = memberRepository.findByEmail(email).orElseThrow(MemberNotFoundException::new);

// Repository를 통해 페이징된 개인 대시보드 조회
Page<PersonalDashboard> personalDashboards = personalDashboardRepository.findForPersonalDashboard(member, pageable);

// DTO 변환
List<PersonalDashboardInfoResDto> personalDashboardInfoResDtoList = personalDashboards.stream()
.map(p -> PersonalDashboardInfoResDto.of(member, p))
.toList();

// 페이징 정보를 포함한 응답 반환
return PersonalDashboardPageListResDto.of(personalDashboardInfoResDtoList, PageInfoResDto.from(personalDashboards));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import shop.kkeujeok.kkeujeokbackend.global.annotation.CurrentUserEmail;
Expand All @@ -12,8 +11,6 @@
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response.TeamDashboardsAndChallengesResDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.application.MyPageService;

import java.util.Set;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/members")
Expand All @@ -35,9 +32,10 @@ public RspTemplate<MyPageInfoResDto> update(@CurrentUserEmail String email,

@GetMapping("/mypage/dashboard-challenges")
public RspTemplate<TeamDashboardsAndChallengesResDto> getTeamDashboardsAndChallenges(@CurrentUserEmail String email,
@RequestParam(name = "requestEmail") String requestEmail,
@RequestParam(name = "page", defaultValue = "0") int page,
@RequestParam(name = "size", defaultValue = "10") int size) {
TeamDashboardsAndChallengesResDto response = myPageService.findTeamDashboardsAndChallenges(email, PageRequest.of(page, size));
return new RspTemplate<>(HttpStatus.OK, "대시보드와 챌린지 정보 조회", response);
TeamDashboardsAndChallengesResDto response = myPageService.findTeamDashboardsAndChallenges(email, requestEmail, PageRequest.of(page, size));
return new RspTemplate<>(HttpStatus.OK, "대시보드와 챌린지 정보 조회", response);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response;

import shop.kkeujeok.kkeujeokbackend.challenge.api.dto.response.ChallengeListResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response.PersonalDashboardPageListResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.team.api.dto.response.TeamDashboardListResDto;

public record TeamDashboardsAndChallengesResDto(
PersonalDashboardPageListResDto personalDashboardList,
TeamDashboardListResDto teamDashboardList,
ChallengeListResDto challengeList
) {
public static TeamDashboardsAndChallengesResDto of(TeamDashboardListResDto teamDashboardList, ChallengeListResDto challengeList) {
public static TeamDashboardsAndChallengesResDto of(PersonalDashboardPageListResDto personalDashboardList,
TeamDashboardListResDto teamDashboardList,
ChallengeListResDto challengeList) {
return new TeamDashboardsAndChallengesResDto(
personalDashboardList,
teamDashboardList,
challengeList
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import shop.kkeujeok.kkeujeokbackend.auth.exception.EmailNotFoundException;
import shop.kkeujeok.kkeujeokbackend.challenge.api.dto.response.ChallengeListResDto;
import shop.kkeujeok.kkeujeokbackend.challenge.application.ChallengeService;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response.PersonalDashboardPageListResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.application.PersonalDashboardService;
import shop.kkeujeok.kkeujeokbackend.dashboard.team.api.dto.response.TeamDashboardListResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.team.application.TeamDashboardService;
import shop.kkeujeok.kkeujeokbackend.member.domain.Member;
Expand All @@ -22,6 +24,7 @@
public class MyPageService {

private final MemberRepository memberRepository;
private final PersonalDashboardService personalDashboardService;
private final TeamDashboardService teamDashboardService;
private final ChallengeService challengeService;

Expand All @@ -46,13 +49,24 @@ public MyPageInfoResDto update(String email, MyPageUpdateReqDto myPageUpdateReqD
return MyPageInfoResDto.From(member);
}

// 대시보드 & 챌린지 정보 조회
// 대시보드 & 챌린지 정보 조회
@Transactional(readOnly = true)
public TeamDashboardsAndChallengesResDto findTeamDashboardsAndChallenges(String email, Pageable pageable) {
TeamDashboardListResDto teamDashboardListResDto = teamDashboardService.findForTeamDashboard(email, pageable);
ChallengeListResDto challengeListResDto = challengeService.findChallengeForMemberId(email, pageable);
public TeamDashboardsAndChallengesResDto findTeamDashboardsAndChallenges(String email,
String requestEmail,
Pageable pageable) {
TeamDashboardListResDto teamDashboardListResDto = teamDashboardService.findForTeamDashboard(requestEmail, pageable);
ChallengeListResDto challengeListResDto = challengeService.findChallengeForMemberId(requestEmail, pageable);

return TeamDashboardsAndChallengesResDto.of(teamDashboardListResDto, challengeListResDto);
PersonalDashboardPageListResDto personalDashboardPageListResDto;

if (email.equals(requestEmail)) {
// 본인이면 isPublic과 상관없이 모든 대시보드 및 챌린지 조회
personalDashboardPageListResDto = personalDashboardService.findForPersonalDashboard(requestEmail, pageable);
} else {
// 타인이면 isPublic이 true인 대시보드 및 챌린지 조회
personalDashboardPageListResDto = personalDashboardService.findPublicPersonalDashboards(requestEmail, pageable);
}
return TeamDashboardsAndChallengesResDto.of(personalDashboardPageListResDto,teamDashboardListResDto, challengeListResDto);
}

private boolean isNicknameChanged(Member member, String newNickname) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.http.MediaType;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import shop.kkeujeok.kkeujeokbackend.challenge.api.dto.response.ChallengeListResDto;
import shop.kkeujeok.kkeujeokbackend.common.annotation.ControllerTest;
import shop.kkeujeok.kkeujeokbackend.dashboard.personal.api.dto.response.PersonalDashboardPageListResDto;
import shop.kkeujeok.kkeujeokbackend.dashboard.team.api.dto.response.TeamDashboardListResDto;
import shop.kkeujeok.kkeujeokbackend.global.annotationresolver.CurrentUserEmailArgumentResolver;
import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.TokenReqDto;
Expand All @@ -21,16 +19,13 @@
import shop.kkeujeok.kkeujeokbackend.member.domain.Member;
import shop.kkeujeok.kkeujeokbackend.member.domain.Role;
import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.request.MyPageUpdateReqDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response.MyPageInfoResDto;
import shop.kkeujeok.kkeujeokbackend.member.mypage.api.dto.response.TeamDashboardsAndChallengesResDto;

import java.util.ArrayList;
import java.util.Collections;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.when;
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
Expand All @@ -49,7 +44,6 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.hamcrest.Matchers.is;
import static shop.kkeujeok.kkeujeokbackend.global.restdocs.RestDocsHandler.requestFields;
import static shop.kkeujeok.kkeujeokbackend.global.restdocs.RestDocsHandler.responseFields;

public class MemberControllerTest extends ControllerTest {
Expand Down Expand Up @@ -121,19 +115,24 @@ void setUp(RestDocumentationContextProvider restDocumentation) {
.andExpect(jsonPath("$.data").exists());
}

@DisplayName("대시보드와 챌린지 정보를 가져옵니다.")
@DisplayName("대시보드와 챌린지 정보를 가져옵니다.")
@Test
void 팀_대시보드와_챌린지_정보를_가져옵니다() throws Exception {
// Given
TeamDashboardsAndChallengesResDto resDto = new TeamDashboardsAndChallengesResDto(
new PersonalDashboardPageListResDto(new ArrayList<>(), new PageInfoResDto(0, 0, 0)),
new TeamDashboardListResDto(new ArrayList<>(), new PageInfoResDto(0, 0, 0)),
new ChallengeListResDto(new ArrayList<>(), new PageInfoResDto(0, 0, 0))
);

when(myPageService.findTeamDashboardsAndChallenges(anyString(), any())).thenReturn(resDto);
when(tokenProvider.getUserEmailFromToken(any(TokenReqDto.class))).thenReturn("email");
when(myPageService.findTeamDashboardsAndChallenges(anyString(), anyString(), any(PageRequest.class)))
.thenReturn(resDto);

when(tokenProvider.getUserEmailFromToken(any(TokenReqDto.class))).thenReturn("[email protected]");

mockMvc.perform(get("/api/members/mypage/dashboard-challenges")
.header("Authorization", "Bearer valid-token")
.param("requestEmail", "[email protected]")
.param("page", "0")
.param("size", "10"))
.andDo(print())
Expand All @@ -144,12 +143,17 @@ void setUp(RestDocumentationContextProvider restDocumentation) {
headerWithName("Authorization").description("JWT 토큰")
),
queryParameters(
parameterWithName("requestEmail").description("조회할 사용자의 이메일"),
parameterWithName("page").description("페이지 번호 (기본값: 0)"),
parameterWithName("size").description("페이지 당 항목 수 (기본값: 10)")
),
responseFields(
fieldWithPath("statusCode").description("상태 코드"),
fieldWithPath("message").description("응답 메시지"),
fieldWithPath("data.personalDashboardList.personalDashboardInfoResDto").description("개인 대시보드 정보 목록"),
fieldWithPath("data.personalDashboardList.pageInfoResDto.currentPage").description("현재 페이지 번호"),
fieldWithPath("data.personalDashboardList.pageInfoResDto.totalPages").description("총 페이지 수"),
fieldWithPath("data.personalDashboardList.pageInfoResDto.totalItems").description("총 항목 수"),
fieldWithPath("data.teamDashboardList.teamDashboardInfoResDto").description("팀 대시보드 정보 목록"),
fieldWithPath("data.teamDashboardList.pageInfoResDto.currentPage").description("현재 페이지 번호"),
fieldWithPath("data.teamDashboardList.pageInfoResDto.totalPages").description("총 페이지 수"),
Expand All @@ -161,7 +165,7 @@ void setUp(RestDocumentationContextProvider restDocumentation) {
)
))
.andExpect(status().isOk())
.andExpect(jsonPath("$.message", is("대시보드와 챌린지 정보 조회")))
.andExpect(jsonPath("$.message", is("대시보드와 챌린지 정보 조회")))
.andExpect(jsonPath("$.data").exists());
}

Expand Down
Loading

0 comments on commit d0ced15

Please sign in to comment.