Skip to content

Commit

Permalink
[#34] feat: 찜한 코스 모아보기, 마이 코스 모아보기 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
jaeuk520 committed Sep 9, 2024
1 parent 24ccdb1 commit 44cca5b
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 11 deletions.
21 changes: 16 additions & 5 deletions src/main/java/com/ku/covigator/controller/CourseController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,20 @@

@Tag(name = "course", description = "커뮤니티 코스")
@RestController
@RequestMapping("/community/courses")
@RequiredArgsConstructor
public class CourseController {

private final CourseService courseService;

@Operation(summary = "코스 등록")
@PostMapping
@PostMapping("/community/courses")
public ResponseEntity<Void> addCommunityCourse(@LoggedInMemberId Long memberId, @RequestBody PostCourseRequest request) {
courseService.addCommunityCourse(memberId, request);
return ResponseEntity.ok().build();
}

@Operation(summary = "전체 코스 조회")
@GetMapping
@GetMapping("/community/courses")
public ResponseEntity<GetCourseListResponse> getAllCommunityCourses(
@PageableDefault(
page = 0, size = 10, sort = "createdAt", direction = Sort.Direction.DESC
Expand All @@ -39,18 +38,30 @@ public ResponseEntity<GetCourseListResponse> getAllCommunityCourses(
}

@Operation(summary = "상세 코스 조회")
@GetMapping("/{course_id}")
@GetMapping("/community/courses/{course_id}")
public ResponseEntity<GetCommunityCourseInfoResponse> getCommunityCourseInfo(
@LoggedInMemberId Long memberId,
@PathVariable(name = "course_id") Long courseId) {
return ResponseEntity.ok(courseService.findCourse(memberId, courseId));
}

@Operation(summary = "코스 삭제")
@DeleteMapping("/{course_id}")
@DeleteMapping("/community/courses/{course_id}")
public ResponseEntity<Void> deleteCommunityCourse(
@PathVariable(name = "course_id") Long courseId) {
courseService.deleteCourse(courseId);
return ResponseEntity.ok().build();
}

@Operation(summary = "찜한 코스 모아보기")
@GetMapping("/my-page/liked-courses")
public ResponseEntity<GetCourseListResponse> getLikedCourses(@LoggedInMemberId Long memberId){
return ResponseEntity.ok(courseService.findLikedCourses(memberId));
}

@Operation(summary = "마이 코스 모아보기")
@GetMapping("/my-page/my-courses")
public ResponseEntity<GetCourseListResponse> getMyCourses(@LoggedInMemberId Long memberId) {
return ResponseEntity.ok(courseService.findMyCourses(memberId));
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/ku/covigator/repository/CourseRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,15 @@ public interface CourseRepository extends JpaRepository<Course, Long> {

@EntityGraph(attributePaths = "places")
Optional<Course> findCourseWithPlacesById(Long courseId);

@Query("""
SELECT c
FROM Course c, Like l
WHERE l.member.id = :memberId AND l.course.id = c.id
ORDER BY l.createdAt DESC
""")
Slice<Course> findLikedCoursesByMemberId(Long memberId, Pageable pageable);

@EntityGraph(attributePaths = "member")
Slice<Course> findMyCoursesByMemberId(Long memberId, Pageable pageable);
}
16 changes: 16 additions & 0 deletions src/main/java/com/ku/covigator/service/CourseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import com.ku.covigator.repository.CourseRepository;
import com.ku.covigator.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -49,6 +51,20 @@ public GetCourseListResponse findAllCourses(Pageable pageable) {

}

public GetCourseListResponse findLikedCourses(Long memberId) {

Pageable pageable = PageRequest.of(0, 10);
Slice<Course> courses = courseRepository.findLikedCoursesByMemberId(memberId, pageable);
return GetCourseListResponse.fromCourseSlice(courses);
}

public GetCourseListResponse findMyCourses(Long memberId) {

Pageable pageable = PageRequest.of(0, 10, Sort.by("createdAt").descending());
Slice<Course> courses = courseRepository.findMyCoursesByMemberId(memberId, pageable);
return GetCourseListResponse.fromCourseSlice(courses);
}

@Transactional(readOnly = true)
public GetCommunityCourseInfoResponse findCourse(Long memberId, Long courseId) {

Expand Down
3 changes: 0 additions & 3 deletions src/main/java/com/ku/covigator/service/ReviewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@
import com.ku.covigator.repository.MemberRepository;
import com.ku.covigator.repository.ReviewRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class ReviewService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,72 @@ void deleteCommunityCourse() throws Exception {
.andDo(print())
.andExpect(status().isOk());
}

@DisplayName("찜한 코스 모아보기를 요청한다.")
@Test
void getLikedCourses() throws Exception {
//given
Long memberId = 1L;

GetCourseListResponse.CourseDto courseDto = GetCourseListResponse.CourseDto.builder()
.name("건대 풀코스")
.description("건대 핫플 요약 코스")
.score(5.0)
.build();

GetCourseListResponse response = GetCourseListResponse.builder()
.courses(List.of(courseDto))
.hasNext(false)
.build();

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

//when //then
mockMvc.perform(get("/my-page/liked-courses"))
.andDo(print())
.andExpectAll(
status().isOk(),
jsonPath("$.courses[0].name").value("건대 풀코스"),
jsonPath("$.courses[0].description").value("건대 핫플 요약 코스"),
jsonPath("$.courses[0].score").value(5.0),
jsonPath("$.has_next").value(false)
);
}

@DisplayName("마이 코스 모아보기를 요청한다.")
@Test
void getMyCourses() throws Exception {
//given
Long memberId = 1L;

GetCourseListResponse.CourseDto courseDto = GetCourseListResponse.CourseDto.builder()
.name("건대 풀코스")
.description("건대 핫플 요약 코스")
.score(5.0)
.build();

GetCourseListResponse response = GetCourseListResponse.builder()
.courses(List.of(courseDto))
.hasNext(false)
.build();

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

//when //then
mockMvc.perform(get("/my-page/my-courses"))
.andDo(print())
.andExpectAll(
status().isOk(),
jsonPath("$.courses[0].name").value("건대 풀코스"),
jsonPath("$.courses[0].description").value("건대 핫플 요약 코스"),
jsonPath("$.courses[0].score").value(5.0),
jsonPath("$.has_next").value(false)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import com.ku.covigator.security.jwt.JwtProvider;
import com.ku.covigator.security.kakao.KakaoOauthProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down
105 changes: 104 additions & 1 deletion src/test/java/com/ku/covigator/service/CourseServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
import com.ku.covigator.dto.response.GetCommunityCourseInfoResponse;
import com.ku.covigator.dto.response.GetCourseListResponse;
import com.ku.covigator.exception.notfound.NotFoundMemberException;
import com.ku.covigator.repository.*;
import com.ku.covigator.repository.CoursePlaceRepository;
import com.ku.covigator.repository.CourseRepository;
import com.ku.covigator.repository.LikeRepository;
import com.ku.covigator.repository.MemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -402,6 +405,106 @@ void test() {
);
}

@DisplayName("찜한 코스 리스트를 찜 시간 최신순으로 조회한다.")
@Test
void findLikedCourses() {
//given
Member member = createMember();
Member savedMember = memberRepository.save(member);

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

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

Course course3 = Course.builder()
.name("건대 풀코스3")
.isPublic('Y')
.description("건대 핫플 리스트3")
.member(member)
.likeCnt(10L)
.build();
courseRepository.save(course3);

Like like = Like.builder()
.member(savedMember)
.course(savedCourse)
.build();
Like like2 = Like.builder()
.member(savedMember)
.course(savedCourse2)
.build();
likeRepository.saveAll(List.of(like, like2));

//when
GetCourseListResponse response = courseService.findLikedCourses(savedMember.getId());

//then
assertAll(
() -> assertEquals(2, response.courses().size()),
() -> assertThat(response.courses())
.extracting("name")
.containsExactly("건대 풀코스2", "건대 풀코스"),
() -> assertThat(response.courses())
.extracting("description")
.containsExactly("건대 핫플 리스트2", "건대 핫플 리스트"),
() -> assertThat(response.hasNext()).isFalse()
);
}

@DisplayName("마이 코스 리스트를 생성시간 기준 최신순으로 조회한다.")
@Test
void findMyCourses() {
//given
Member member = createMember();
Member savedMember = memberRepository.save(member);

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

Course course2 = Course.builder()
.name("건대 풀코스2")
.isPublic('Y')
.description("건대 핫플 리스트2")
.member(member)
.likeCnt(10L)
.build();
courseRepository.saveAll(List.of(course, course2));

//when
GetCourseListResponse response = courseService.findMyCourses(savedMember.getId());

//then
assertAll(
() -> assertEquals(2, response.courses().size()),
() -> assertThat(response.courses())
.extracting("name")
.containsExactly("건대 풀코스2", "건대 풀코스"),
() -> assertThat(response.courses())
.extracting("description")
.containsExactly("건대 핫플 리스트2", "건대 핫플 리스트"),
() -> assertThat(response.hasNext()).isFalse()
);
}

private Member createMember() {
return Member.builder()
.name("김코비")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.ku.covigator.exception.notfound.NotFoundPlaceException;
import com.ku.covigator.repository.PlaceRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.locationtech.jts.geom.Coordinate;
Expand Down

0 comments on commit 44cca5b

Please sign in to comment.