Skip to content

Commit

Permalink
refactor: 이미지가 여러 개인 페스티벌이 중복 조회되는 버그 수정 (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
punchdrunkard authored Oct 7, 2024
1 parent 629de66 commit 09b8c3b
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@ Page<FestivalWithSido> findFestivalsAndSidoWithinDateRange(LocalDate startDate,

Map<Long, String> findThumbnailImageByFestivalId(List<Long> festivalIds);

Page<FestivalInfoWithBookmark> findBookmarkedFestivals(Long userId, Pageable pageable);
Page<FestivalWithBookmarkAndSido> findBookmarkedFestivals(Long userId, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -306,41 +306,15 @@ public Map<Long, String> findThumbnailImageByFestivalId(List<Long> festivalIds)
}

@Override
public Page<FestivalInfoWithBookmark> findBookmarkedFestivals(Long userId, Pageable pageable) {
List<FestivalInfoWithBookmark> festivals = queryFactory.select(
Projections.fields(FestivalInfoWithBookmark.class,
festival.id.as("festivalId"),
festival.name,
sido.name.as("sido"),
festival.sigungu,
min(festivalImage.imageUrl).as("thumbnailImage"),
festival.startDate,
festival.endDate,
public Page<FestivalWithBookmarkAndSido> findBookmarkedFestivals(Long userId, Pageable pageable) {

new CaseBuilder()
.when(festivalBookmarkUserIdEq(userId))
.then(true)
.otherwise(false).as("isBookmarked")
)
).from(festival)
List<FestivalWithBookmarkAndSido> festivals = selectFestivalsWithBookmarkAndSido(pageable, userId)
.where(festivalBookmarkUserIdEq(userId))
.leftJoin(festivalBookmarkForIsBookmarked)
.on(festivalBookmarkForIsBookmarked.festivalId.eq(festival.id),
festivalBookmarkUserIdEq(userId))
.leftJoin(sido)
.on(sidoIdFestivalSidoIdEq())
.leftJoin(festivalImage)
.on(festival.id.eq(festivalImage.festivalId))
.orderBy(festivalBookmarkForIsBookmarked.createdAt.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

JPAQuery<Long> countQuery = queryFactory.select(festival.count())
.from(festival)
.leftJoin(festivalBookmarkForIsBookmarked)
.on(festivalBookmarkForIsBookmarked.festivalId.eq(festival.id),
festivalBookmarkUserIdEq(userId))
JPAQuery<Long> countQuery = queryFactory.select(festivalBookmarkForIsBookmarked.count())
.from(festivalBookmarkForIsBookmarked)
.where(festivalBookmarkUserIdEq(userId));

return PageableExecutionUtils.getPage(festivals, pageable, countQuery::fetchOne);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,18 @@ public PageResponse<FestivalBasic> getTrendingFestival(String rankingKey, Long p
(page.intValue() / size) + 1);
}

public Page<FestivalInfoWithBookmark> getBookmarkedFestivals(User user, Pageable pageable) {
validateUserId(user.getId());

Page<FestivalWithBookmarkAndSido> bookmarkedFestivals = festivalRepository.findBookmarkedFestivals(user.getId(),
pageable);

List<FestivalInfoWithBookmark> festivals = getFestivalWithBookmarkAndSidoAndThumbnailImage(
bookmarkedFestivals);

return new PageImpl<>(festivals, pageable, bookmarkedFestivals.getTotalElements());
}

private List<FestivalInfoWithBookmark> getFestivalWithBookmarkAndSidoAndThumbnailImage(
Page<FestivalWithBookmarkAndSido> festivalsByFilters) {
// 1. 페스티벌 아이디를 가져온다.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.odiga.fiesta.common.error.ErrorCode;
import com.odiga.fiesta.common.error.exception.CustomException;
import com.odiga.fiesta.festival.dto.response.FestivalInfoWithBookmark;
import com.odiga.fiesta.festival.service.FestivalService;
import com.odiga.fiesta.user.domain.User;
import com.odiga.fiesta.user.dto.request.ProfileCreateRequest;
import com.odiga.fiesta.user.dto.request.SocialLoginRequest;
Expand Down Expand Up @@ -56,7 +57,8 @@ public class UserController {
private final UserService userService;
private final AuthService authService;
private final BadgeService badgeService;

private final FestivalService festivalService;

@PostMapping("/oauth/login")
@Operation(summary = "소셜 로그인", description = "소셜 로그인을 진행합니다.")
public ResponseEntity<BasicResponse<LoginResponse>> kakaoLogin(@RequestBody SocialLoginRequest request) {
Expand Down Expand Up @@ -112,17 +114,17 @@ public ResponseEntity<BasicResponse<TokenReissueResponse>> reissue(@RequestHeade
}

@Operation(
summary = "유저가 스크랩한 페스티벌 조회",
description = "유저가 스크랩한 페스티벌을 다건 조회합니다."
summary = "유저가 북마크한 페스티벌 조회",
description = "유저가 북마크한 페스티벌을 다건 조회합니다."
)
@GetMapping("/bookmarks")
public ResponseEntity<BasicResponse<PageResponse<FestivalInfoWithBookmark>>> getBookmarkedFestivals(
@AuthUser User user,
@ParameterObject @Parameter(description = "Paging parameters", example = "{\"page\":0,\"size\":6,\"sort\":[\"createdAt,desc\"]}")
@PageableDefault(sort = {"createdAt"}, direction = Sort.Direction.DESC, size = 6) Pageable pageable) {

Page<FestivalInfoWithBookmark> festivals = userService.getBookmarkedFestivals(user, pageable);
return ResponseEntity.ok(BasicResponse.ok("스크랩한 페스티벌 조회 성공", PageResponse.of(festivals)));
Page<FestivalInfoWithBookmark> festivals = festivalService.getBookmarkedFestivals(user, pageable);
return ResponseEntity.ok(BasicResponse.ok("북마크한 페스티벌 조회 성공", PageResponse.of(festivals)));
}

@GetMapping("/badges")
Expand Down
13 changes: 4 additions & 9 deletions src/main/java/com/odiga/fiesta/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import com.odiga.fiesta.common.error.exception.CustomException;
import com.odiga.fiesta.companion.domain.Companion;
import com.odiga.fiesta.companion.repository.CompanionRepository;
import com.odiga.fiesta.festival.dto.projection.FestivalWithBookmarkAndSido;
import com.odiga.fiesta.festival.dto.response.FestivalInfoWithBookmark;
import com.odiga.fiesta.festival.repository.FestivalRepository;
import com.odiga.fiesta.festival.service.FestivalService;
import com.odiga.fiesta.mood.domain.Mood;
import com.odiga.fiesta.mood.repository.MoodRepository;
import com.odiga.fiesta.priority.domain.Priority;
Expand Down Expand Up @@ -54,7 +56,9 @@
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class UserService {

private final FestivalRepository festivalRepository;
private final FestivalService festivalService;

private final UserCategoryRepository userCategoryRepository;
private final UserCompanionRepository userCompanionRepository;
Expand Down Expand Up @@ -103,15 +107,6 @@ public ProfileCreateResponse createProfile(User user, ProfileCreateRequest reque
.build();
}

public Page<FestivalInfoWithBookmark> getBookmarkedFestivals(User user, Pageable pageable) {
validateUser(user);

Page<FestivalInfoWithBookmark> festivals = festivalRepository.findBookmarkedFestivals(user.getId(),
pageable);

return festivals;
}

@Transactional
public UserIdResponse updateUserInfo(User user, UserInfoUpdateRequest request) {
validateUser(user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,67 +181,6 @@ void findThumbnailImageByFestivalId() {
assertThat(thumbnailImageByFestivalId.get(festival3.getId())).isNull();
}

@DisplayName("현재 유저가 북마크 한 페스티벌들을 조회한다.")
@Test
void findBookmarkedFestivals() {
// given
User currentUser = createUser();
em.persist(currentUser);

User otherUser = createUser();
em.persist(otherUser);

Sido sido = createSido();
em.persist(sido);

List<Festival> bookmarkedFestivals = new ArrayList<>();

for (int i = 0; i < 30; i++) {
Festival festival = createFestival(LocalDate.of(2024, 10, 1), LocalDate.of(2024, 10, 10), sido.getId());
em.persist(festival);

for (int j = 0; j < 3; j++) {
FestivalImage image = createFestivalImage(festival);
em.persist(image);
}

FestivalBookmark bookmark = FestivalBookmark.builder()
.festivalId(festival.getId())
.userId(currentUser.getId())
.build();

em.persist(bookmark);

bookmarkedFestivals.add(festival);
}

for (int i = 0; i < 10; i++) {
Festival festival = createFestival(LocalDate.of(2024, 10, 1), LocalDate.of(2024, 10, 10), sido.getId());
em.persist(festival);

FestivalBookmark bookmark = FestivalBookmark.builder()
.festivalId(festival.getId())
.userId(otherUser.getId())
.build();
em.persist(bookmark);
}

Pageable pageable = PageRequest.of(0, 6);

// when
Page<FestivalInfoWithBookmark> result = festivalRepository.findBookmarkedFestivals(currentUser.getId(),
pageable);

// then
assertThat(result).isNotNull();
assertThat(result.getTotalElements()).isEqualTo(30);
assertEquals(6, result.getSize());
List<FestivalInfoWithBookmark> content = result.getContent();
for (FestivalInfoWithBookmark festivalInfoWithBookmark : content) {
assertThat(festivalInfoWithBookmark.getIsBookmarked()).isTrue();
}
}

private static FestivalImage createFestivalImage(Festival festival) {
return FestivalImage.builder()
.festivalId(festival.getId())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ void getFestival() {
.collect(Collectors.toList())
);

FestivalImage image1 = FestivalImage.builder().festivalId(festival.getId()).imageUrl("imageUrl1").build();
FestivalImage image2 = FestivalImage.builder().festivalId(festival.getId()).imageUrl("imageUrl2").build();
FestivalImage image1 = createFestivalImage(festival);
FestivalImage image2 = createFestivalImage(festival);

List<FestivalImage> images = festivalImageRepository.saveAll(List.of(image1, image2));

Expand Down Expand Up @@ -840,6 +840,109 @@ private static FestivalBookmark createFestivalBookmark(Long festvialId, Long use
.build();
}

@DisplayName("유저가 북마크한 페스티벌 조회 - 성공 케이스, 페스티벌이 하나의 이미지만 가지고 있음")
@Test
void findBookmarkedFestivals() {
// given
User currentUser = userRepository.save(createUser());

Festival festival = createFestival();
Festival festival2 = createFestival();
festivalRepository.saveAll(List.of(festival, festival2));

FestivalImage image = createFestivalImage(festival);
festivalImageRepository.save(image);

FestivalBookmark bookmark = festivalBookmarkRepository.save(
createFestivalBookmark(festival.getId(), currentUser.getId()));
festivalBookmarkRepository.save(bookmark);

int bookmarkCount = 1;

// when
Page<FestivalInfoWithBookmark> bookmarkedFestivals = festivalService.getBookmarkedFestivals(currentUser,
PageRequest.of(0, 5));

// then
assertThat(bookmarkedFestivals.getContent())
.hasSize(1)
.extracting("festivalId", "thumbnailImage", "isBookmarked")
.containsExactly(
tuple(festival.getId(), image.getImageUrl(), true)
);

assertEquals(bookmarkedFestivals.getTotalElements(), bookmarkCount);
}

@DisplayName("유저가 북마크한 페스티벌 조회 - 페스티벌의 이미지가 여러 개인 경우에도 첫 번째 이미지만 반환한다.")
@Test
void findBookmarkedFestivals_multipleFestivalImages() {
// given
User currentUser = userRepository.save(createUser());

Festival festival = createFestival();
festivalRepository.save(festival);

FestivalImage image1 = createFestivalImage(festival);
FestivalImage image2 = createFestivalImage(festival);
FestivalImage image3 = createFestivalImage(festival);
festivalImageRepository.saveAll(List.of(image1, image2, image3));

FestivalBookmark bookmark = festivalBookmarkRepository.save(
createFestivalBookmark(festival.getId(), currentUser.getId()));
festivalBookmarkRepository.save(bookmark);

// when
Page<FestivalInfoWithBookmark> bookmarkedFestivals = festivalService.getBookmarkedFestivals(currentUser,
PageRequest.of(0, 5));

// then
assertThat(bookmarkedFestivals.getContent())
.hasSize(1)
.extracting("festivalId", "thumbnailImage", "isBookmarked")
.containsExactly(
tuple(festival.getId(), image1.getImageUrl(), true)
);
}

@DisplayName("유저가 북마크한 페스티벌 조회 - 성공, 북마크 한 페스티벌이 여러 개 일 때")
@Test
void findBookmarkedFestivals_Success() {
// given
User currentUser = userRepository.save(createUser());

Festival festival = createFestival();
Festival festival2 = createFestival();
Festival festival3 = createFestival();
Festival festival4 = createFestival();
Festival festival5 = createFestival();
festivalRepository.saveAll(List.of(festival, festival2, festival3, festival4, festival5));

FestivalBookmark bookmark1 = festivalBookmarkRepository.save(
createFestivalBookmark(festival.getId(), currentUser.getId()));
FestivalBookmark bookmark2 = festivalBookmarkRepository.save(
createFestivalBookmark(festival.getId(), currentUser.getId()));
FestivalBookmark bookmark3 = festivalBookmarkRepository.save(
createFestivalBookmark(festival.getId(), currentUser.getId()));

festivalBookmarkRepository.saveAll(List.of(bookmark1, bookmark2, bookmark3));

int pageSize = 2;
int bookmarkedFestivalCount = 3;

// when
Page<FestivalInfoWithBookmark> bookmarkedFestivals = festivalService.getBookmarkedFestivals(currentUser,
PageRequest.of(0, pageSize));

// then
assertThat(bookmarkedFestivals.getContent()).hasSize(pageSize);
assertThat(bookmarkedFestivals.getTotalElements()).isEqualTo(bookmarkedFestivalCount);
}

private static FestivalImage createFestivalImage(Festival festival) {
return FestivalImage.builder().festivalId(festival.getId()).imageUrl("imageUrl1").build();
}

private static Festival createFestival(LocalDate startDate, LocalDate endDate, Long sidoId) {
return Festival.builder()
.userId(1L)
Expand Down Expand Up @@ -906,6 +1009,10 @@ private static Festival createFestival(String name, LocalDate currentDate, Doubl
.build();
}

private static Festival createFestival() {
return createFestival("페스티벌 이름");
}

private static Festival createFestival(String name) {
return Festival.builder()
.userId(1L)
Expand Down
29 changes: 0 additions & 29 deletions src/test/java/com/odiga/fiesta/user/service/UserServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,35 +130,6 @@ void createProfile_Success() {
verify(userCompanionRepository).saveAll(anyList());
}

@DisplayName("유저가 북마크한 페스티벌들을 조회")
@Test
void getBookmarkedFestivals() {
// given
User currentUser = createNoProfileUser();
given(userRepository.existsById(currentUser.getId())).willReturn(true);

Pageable pageable = PageRequest.of(0, 5);
List<FestivalInfoWithBookmark> festivals = Arrays.asList(
new FestivalInfoWithBookmark(1L, "Festival 1", "Sido 1", "Sigungu 1", "image1.jpg",
LocalDate.of(2024, 10, 1), LocalDate.of(2024, 10, 10), true),
new FestivalInfoWithBookmark(2L, "Festival 2", "Sido 2", "Sigungu 2", "image2.jpg",
LocalDate.of(2024, 10, 2), LocalDate.of(2024, 10, 11), true)
);

Page<FestivalInfoWithBookmark> festivalPage = new PageImpl<>(festivals, pageable, festivals.size());
given(festivalRepository.findBookmarkedFestivals(currentUser.getId(), pageable)).willReturn(festivalPage);

// when
Page<FestivalInfoWithBookmark> result = userService.getBookmarkedFestivals(currentUser, pageable);

// then
assertThat(result).isNotNull(); // 반환된 값이 null이 아닌지 확인
assertThat(result.getTotalElements()).isEqualTo(2); // 총 북마크된 페스티벌 수 확인
assertThat(result.getContent())
.usingRecursiveComparison()
.isEqualTo(festivals);
}

@DisplayName("유저 정보 수정 - 성공")
@Test
void updateUserInfo_Success() {
Expand Down

0 comments on commit 09b8c3b

Please sign in to comment.