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] 코스 전체 및 상세 조회 응답 형식 수정 #40

Merged
merged 3 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -2,6 +2,7 @@

import com.ku.covigator.dto.request.PostCourseRequest;
import com.ku.covigator.dto.response.GetCommunityCourseInfoResponse;
import com.ku.covigator.dto.response.GetCommunityCourseListResponse;
import com.ku.covigator.dto.response.GetCourseListResponse;
import com.ku.covigator.security.jwt.LoggedInMemberId;
import com.ku.covigator.service.CourseService;
Expand Down Expand Up @@ -32,7 +33,10 @@ public ResponseEntity<Void> addCommunityCourse(@LoggedInMemberId Long memberId,

@Operation(summary = "전체 코스 조회")
@GetMapping("/community/courses")
public ResponseEntity<GetCourseListResponse> getAllCommunityCourses(
public ResponseEntity<GetCommunityCourseListResponse> getAllCommunityCourses(

@LoggedInMemberId Long memberId,

@Parameter(description = "페이지 번호 (0부터 시작)", schema = @Schema(defaultValue = "0"))
@RequestParam(value = "page", defaultValue = "0") int page,

Expand All @@ -43,7 +47,7 @@ public ResponseEntity<GetCourseListResponse> getAllCommunityCourses(
@RequestParam(value = "sort", defaultValue = "createdAt") String sort) {

Pageable pageable = PageRequest.of(page, size, Sort.by(sort).descending());
return ResponseEntity.ok(courseService.findAllCourses(pageable));
return ResponseEntity.ok(courseService.findAllCourses(pageable, memberId));
}

@Operation(summary = "상세 코스 조회")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,25 @@

@Builder
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record GetCommunityCourseInfoResponse(String courseName, String courseDescription, Long likeCnt, Boolean isLiked,
List<PlaceDto> places) {
public record GetCommunityCourseInfoResponse(Long courseId, String courseName, String courseDescription, Long likeCnt,
Boolean isLiked, List<PlaceDto> places) {

@Builder
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record PlaceDto(String placeName, String placeDescription, String category) {
public record PlaceDto(Long placeId, String placeName, String placeDescription, String category) {
}

public static GetCommunityCourseInfoResponse from(Course course, boolean isLiked) {
List<PlaceDto> places = course.getPlaces().stream()
.map(place -> PlaceDto.builder()
.placeId(place.getId())
.placeDescription(place.getDescription())
.placeName(place.getName())
.category(place.getCategory())
.build()
).toList();
return GetCommunityCourseInfoResponse.builder()
.courseId(course.getId())
.courseName(course.getName())
.courseDescription(course.getDescription())
.likeCnt(course.getLikeCnt())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.ku.covigator.dto.response;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.ku.covigator.domain.Course;
import lombok.Builder;
import org.springframework.data.domain.Slice;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Builder
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record GetCommunityCourseListResponse(List<CourseDto> courses, Boolean hasNext) {

@Builder
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record CourseDto(Long courseId, String name, String description, Double score, Boolean isLiked) {
}

public static GetCommunityCourseListResponse from(Slice<Course> courseSlice, Set<Long> likedCourseIds) {
List<CourseDto> courseDtos = courseSlice.getContent().stream()
.map(course -> CourseDto.builder()
.courseId(course.getId())
.name(course.getName())
.description(course.getDescription())
.score(course.getAvgScore())
.isLiked(likedCourseIds.contains(course.getId())) // 좋아요 여부 판단
.build()
).collect(Collectors.toList());

return GetCommunityCourseListResponse.builder()
.courses(courseDtos)
.hasNext(courseSlice.hasNext())
.build();
}

}
18 changes: 16 additions & 2 deletions src/main/java/com/ku/covigator/service/CourseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.ku.covigator.domain.member.Member;
import com.ku.covigator.dto.request.PostCourseRequest;
import com.ku.covigator.dto.response.GetCommunityCourseInfoResponse;
import com.ku.covigator.dto.response.GetCommunityCourseListResponse;
import com.ku.covigator.dto.response.GetCourseListResponse;
import com.ku.covigator.exception.notfound.NotFoundCourseException;
import com.ku.covigator.exception.notfound.NotFoundMemberException;
Expand All @@ -20,6 +21,8 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
Expand All @@ -44,11 +47,17 @@ public void addCommunityCourse(Long memberId, PostCourseRequest request) {
}

@Transactional(readOnly = true)
public GetCourseListResponse findAllCourses(Pageable pageable) {
public GetCommunityCourseListResponse findAllCourses(Pageable pageable, Long memberId) {

Member member = memberRepository.findMemberWithLikesById(memberId)
.orElseThrow(NotFoundMemberException::new);

Slice<Course> courses = courseRepository.findAllCoursesByIsPublic(pageable, 'Y');
return GetCourseListResponse.fromCourseSlice(courses);

// 회원이 좋아요한 코스 리스트 ID 반환
Set<Long> likedCourseIds = getLikedCourseIds(member);

return GetCommunityCourseListResponse.from(courses, likedCourseIds);
}

public GetCourseListResponse findLikedCourses(Long memberId) {
Expand Down Expand Up @@ -92,4 +101,9 @@ private boolean checkIfLiked(Long courseId, Member member) {
);
}

private Set<Long> getLikedCourseIds(Member member) {
return member.getLikes().stream()
.map(like -> like.getCourse().getId())
.collect(Collectors.toSet());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ku.covigator.dto.request.PostCourseRequest;
import com.ku.covigator.dto.response.GetCommunityCourseInfoResponse;
import com.ku.covigator.dto.response.GetCommunityCourseListResponse;
import com.ku.covigator.dto.response.GetCourseListResponse;
import com.ku.covigator.security.jwt.JwtAuthArgumentResolver;
import com.ku.covigator.security.jwt.JwtAuthInterceptor;
Expand Down Expand Up @@ -79,18 +80,34 @@ void addCourse() throws Exception {
@Test
void getAllCommunityCourses() throws Exception {
//given
GetCourseListResponse.CourseDto courseDto = GetCourseListResponse.CourseDto.builder()
Long memberId = 1L;

GetCommunityCourseListResponse.CourseDto courseDto = GetCommunityCourseListResponse.CourseDto.builder()
.courseId(1L)
.name("건대 풀코스")
.description("건대 핫플 요약 코스")
.score(5.0)
.isLiked(true)
.build();

GetCourseListResponse response = GetCourseListResponse.builder()
.courses(List.of(courseDto))
GetCommunityCourseListResponse.CourseDto courseDto2 = GetCommunityCourseListResponse.CourseDto.builder()
.courseId(2L)
.name("건대 풀코스2")
.description("건대 핫플 요약 코스2")
.score(0.0)
.isLiked(false)
.build();

GetCommunityCourseListResponse response = GetCommunityCourseListResponse.builder()
.courses(List.of(courseDto, courseDto2))
.hasNext(false)
.build();

given(courseService.findAllCourses(any())).willReturn(response);
given(jwtAuthArgumentResolver.resolveArgument(any(), any(), any(), any()))
.willReturn(memberId);
given(jwtAuthArgumentResolver.supportsParameter(any())).willReturn(true);

given(courseService.findAllCourses(any(), any())).willReturn(response);
this.mockMvc = MockMvcBuilders.standaloneSetup(
new CourseController(this.courseService)
)
Expand All @@ -102,9 +119,16 @@ void getAllCommunityCourses() throws Exception {
.andDo(print())
.andExpectAll(
status().isOk(),
jsonPath("$.courses[0].course_id").value(1L),
jsonPath("$.courses[0].name").value("건대 풀코스"),
jsonPath("$.courses[0].description").value("건대 핫플 요약 코스"),
jsonPath("$.courses[0].score").value(5.0),
jsonPath("$.courses[0].is_liked").value(true),
jsonPath("$.courses[1].course_id").value(2L),
jsonPath("$.courses[1].name").value("건대 풀코스2"),
jsonPath("$.courses[1].description").value("건대 핫플 요약 코스2"),
jsonPath("$.courses[1].score").value(0.0),
jsonPath("$.courses[1].is_liked").value(false),
jsonPath("$.has_next").value(false)
);
}
Expand Down
74 changes: 64 additions & 10 deletions src/test/java/com/ku/covigator/service/CourseServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.ku.covigator.domain.member.Platform;
import com.ku.covigator.dto.request.PostCourseRequest;
import com.ku.covigator.dto.response.GetCommunityCourseInfoResponse;
import com.ku.covigator.dto.response.GetCommunityCourseListResponse;
import com.ku.covigator.dto.response.GetCourseListResponse;
import com.ku.covigator.exception.notfound.NotFoundMemberException;
import com.ku.covigator.repository.CoursePlaceRepository;
Expand Down Expand Up @@ -139,15 +140,58 @@ void addCourseFailsWhenMemberNotExists() {
void findCoursesSortByCreatedAt() {
//given
Member member = createMember();
memberRepository.save(member);
Member savedMember = memberRepository.save(member);

Course course = Course.builder()
.name("건대 풀코스")
.isPublic('Y')
.description("건대 핫플 리스트")
.member(member)
.build();
courseRepository.save(course);
Course savedCourse = courseRepository.save(course);

Course course2 = Course.builder()
.name("건대 풀코스2")
.isPublic('Y')
.description("건대 핫플 리스트2")
.member(member)
.build();
Course savedCourse2 = courseRepository.save(course2);

Pageable pageable = PageRequest.of(0, 10, Sort.by("createdAt").descending());

//when
GetCommunityCourseListResponse response = courseService.findAllCourses(pageable, savedMember.getId());

//then
assertAll(
() -> assertThat(response.courses()).hasSize(2),
() -> assertThat(response.courses())
.extracting("courseId")
.containsExactly(savedCourse2.getId(), savedCourse.getId()),
() -> assertThat(response.courses())
.extracting("name")
.containsExactly("건대 풀코스2", "건대 풀코스"),
() -> assertThat(response.courses())
.extracting("description")
.containsExactly("건대 핫플 리스트2", "건대 핫플 리스트")
);
}

@DisplayName("전체 코스 리스트를 조회시 좋아요 여부를 판단한다.")
@Test
void findCoursesWithLiked() {
//given
Member member = createMember();
Member savedMember = memberRepository.save(member);

Course course = Course.builder()
.name("건대 풀코스")
.isPublic('Y')
.description("건대 핫플 리스트")
.member(member)
.build();
Course savedCourse = courseRepository.save(course);

Course course2 = Course.builder()
.name("건대 풀코스2")
Expand All @@ -157,10 +201,16 @@ void findCoursesSortByCreatedAt() {
.build();
courseRepository.save(course2);

Like like = Like.builder()
.course(savedCourse)
.member(savedMember)
.build();
likeRepository.save(like);

Pageable pageable = PageRequest.of(0, 10, Sort.by("createdAt").descending());

//when
GetCourseListResponse response = courseService.findAllCourses(pageable);
GetCommunityCourseListResponse response = courseService.findAllCourses(pageable, savedMember.getId());

//then
assertAll(
Expand All @@ -170,7 +220,10 @@ void findCoursesSortByCreatedAt() {
.containsExactly("건대 풀코스2", "건대 풀코스"),
() -> assertThat(response.courses())
.extracting("description")
.containsExactly("건대 핫플 리스트2", "건대 핫플 리스트")
.containsExactly("건대 핫플 리스트2", "건대 핫플 리스트"),
() -> assertThat(response.courses())
.extracting("isLiked")
.containsExactly(false, true)
);
}

Expand All @@ -179,7 +232,7 @@ void findCoursesSortByCreatedAt() {
void findCoursesSortByReviewScore() {
//given
Member member = createMember();
memberRepository.save(member);
Member savedMember = memberRepository.save(member);

Course course = Course.builder()
.name("건대 풀코스")
Expand All @@ -202,7 +255,7 @@ void findCoursesSortByReviewScore() {
Pageable pageable = PageRequest.of(0, 10, Sort.by("avgScore").descending());

//when
GetCourseListResponse response = courseService.findAllCourses(pageable);
GetCommunityCourseListResponse response = courseService.findAllCourses(pageable, savedMember.getId());

//then
assertAll(
Expand All @@ -224,7 +277,7 @@ void findCoursesSortByReviewScore() {
void findCoursesSortByLikes() {
//given
Member member = createMember();
memberRepository.save(member);
Member savedMember = memberRepository.save(member);

Course course = Course.builder()
.name("건대 풀코스")
Expand All @@ -247,7 +300,7 @@ void findCoursesSortByLikes() {
Pageable pageable = PageRequest.of(0, 10, Sort.by("likeCnt").descending());

//when
GetCourseListResponse response = courseService.findAllCourses(pageable);
GetCommunityCourseListResponse response = courseService.findAllCourses(pageable, savedMember.getId());

//then
assertAll(
Expand All @@ -266,7 +319,7 @@ void findCoursesSortByLikes() {
void findCoursesOnlyIsPublicTrue() {
//given
Member member = createMember();
memberRepository.save(member);
Member savedMember = memberRepository.save(member);

Course course = Course.builder()
.name("건대 풀코스")
Expand All @@ -288,7 +341,7 @@ void findCoursesOnlyIsPublicTrue() {
Pageable pageable = PageRequest.of(0, 10);

//when
GetCourseListResponse response = courseService.findAllCourses(pageable);
GetCommunityCourseListResponse response = courseService.findAllCourses(pageable, savedMember.getId());

//then
assertAll(
Expand Down Expand Up @@ -344,6 +397,7 @@ void findCourseInfo() {

//then
assertAll(
() -> assertThat(response.courseId()).isEqualTo(savedCourse.getId()),
() -> assertThat(response.courseName()).isEqualTo("건대 풀코스"),
() -> assertThat(response.courseDescription()).isEqualTo("건대 핫플 리스트"),
() -> assertThat(response.isLiked()).isTrue(),
Expand Down
Loading