Skip to content

Commit

Permalink
feat: 이번주 페스티벌 조회 api 구현 (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
punchdrunkard authored Aug 17, 2024
1 parent f7c0838 commit eb21e5e
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
import com.odiga.fiesta.common.BasicResponse;
import com.odiga.fiesta.common.PageResponse;
import com.odiga.fiesta.common.error.exception.CustomException;
import com.odiga.fiesta.festival.dto.response.FestivalThisWeekResponse;
import com.odiga.fiesta.user.domain.User;
import com.odiga.fiesta.festival.dto.response.FestivalMonthlyResponse;
import com.odiga.fiesta.festival.dto.response.FestivalInfoResponse;
import com.odiga.fiesta.festival.dto.request.FestivalFilterRequest;
import com.odiga.fiesta.festival.dto.response.FestivalBookmarkResponse;
import com.odiga.fiesta.festival.dto.response.FestivalInfoResponse;
Expand Down Expand Up @@ -102,6 +106,19 @@ public ResponseEntity<BasicResponse<PageResponse<FestivalInfoResponse>>> getFest
return ResponseEntity.ok(BasicResponse.ok("페스티벌 필터 조회 성공", PageResponse.of(festivals)));
}


@Operation(
summary = "이번 주 페스티벌 조회",
description = "이번 주에 진행되고 있는 페스티벌을 조회한다."
)
@GetMapping("/thisweek")
public ResponseEntity<BasicResponse<PageResponse<FestivalThisWeekResponse>>> getFestivalsInThisWeek(
@PageableDefault(size = 3) Pageable pageable) {

Page<FestivalThisWeekResponse> festivalsInThisWeek = festivalService.getFestivalsInThisWeek(pageable);
return ResponseEntity.ok(BasicResponse.ok("이번 주 페스티벌 조회 성공", PageResponse.of(festivalsInThisWeek)));
}

@Operation(summary = "페스티벌 북마크 등록/해제", description = "페스티벌 북마크를 등록 또는 해제합니다.")
@PatchMapping("/{festivalId}/bookmark")
public ResponseEntity<BasicResponse<FestivalBookmarkResponse>> updateFestivalBookmark(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
@SuperBuilder
@Getter
@NoArgsConstructor
@ToString
public class FestivalWithBookmarkAndSido extends FestivalWithBookmark {

private String sido;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.odiga.fiesta.festival.dto.projection;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@SuperBuilder
@Getter
@NoArgsConstructor
public class FestivalWithSido extends FestivalData {

private String sido;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.odiga.fiesta.festival.dto.response;

import java.time.LocalDate;

import com.odiga.fiesta.festival.dto.projection.FestivalWithSido;

import lombok.Builder;

public class FestivalThisWeekResponse extends FestivalBasicResponse {

private String sido;
private String sigungu;
private String thumbnailImage;
private LocalDate startDate;
private LocalDate endDate;

@Builder
public FestivalThisWeekResponse(Long festivalId, String name, String sido,
String sigungu, String thumbnailImage, LocalDate startDate, LocalDate endDate) {
super(festivalId, name);
this.sido = sido;
this.sigungu = sigungu;
this.thumbnailImage = thumbnailImage;
this.startDate = startDate;
this.endDate = endDate;
}

public static FestivalThisWeekResponse of(FestivalWithSido festival, String thumbnailImageUrl) {
return FestivalThisWeekResponse.builder()
.festivalId(festival.getFestivalId())
.name(festival.getName())
.sido(festival.getSido())
.sigungu(festival.getSigungu())
.thumbnailImage(thumbnailImageUrl)
.startDate(festival.getStartDate())
.endDate(festival.getEndDate())
.build();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.data.domain.Pageable;

import com.odiga.fiesta.festival.domain.Festival;
import com.odiga.fiesta.festival.dto.projection.FestivalWithSido;
import com.odiga.fiesta.festival.dto.projection.FestivalWithBookmarkAndSido;
import com.odiga.fiesta.festival.dto.request.FestivalFilterCondition;

Expand All @@ -19,4 +20,8 @@ public interface FestivalCustomRepository {
Page<FestivalWithBookmarkAndSido> findFestivalsByFiltersAndSort(Long userId,
FestivalFilterCondition festivalFilterCondition, Double latitude, Double longitude,
LocalDate date, Pageable pageable);

Page<FestivalWithSido> findFestivalsAndSidoWithinDateRange(LocalDate startDate, LocalDate endDate,
Pageable pageable);

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.springframework.data.support.PageableExecutionUtils;

import com.odiga.fiesta.festival.domain.Festival;
import com.odiga.fiesta.festival.dto.projection.FestivalWithSido;
import com.odiga.fiesta.festival.dto.projection.FestivalWithBookmark;
import com.odiga.fiesta.festival.dto.projection.FestivalWithBookmarkAndSido;
import com.odiga.fiesta.festival.dto.request.FestivalFilterCondition;
Expand Down Expand Up @@ -44,10 +45,8 @@ public List<Festival> findFestivalsWithinDateRange(LocalDate startDate, LocalDat
return queryFactory
.select(festival)
.from(festival)
.where(festival.startDate.between(startDate, endDate)
.or(festival.endDate.between(startDate, endDate))
.or(festival.startDate.loe(startDate).and(festival.endDate.goe(endDate)))
).fetch();
.where(getDateBetweenCondition(startDate, endDate))
.fetch();
}

@Override
Expand Down Expand Up @@ -89,6 +88,24 @@ public Page<FestivalWithBookmarkAndSido> findFestivalsByFiltersAndSort(Long user
return PageableExecutionUtils.getPage(festivals, pageable, countQuery::fetchOne);
}

@Override
public Page<FestivalWithSido> findFestivalsAndSidoWithinDateRange(LocalDate startDate, LocalDate endDate,
Pageable pageable) {
List<FestivalWithSido> festivals = selectFestivalWithSido()
.where(getDateBetweenCondition(startDate, endDate))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(festival.startDate.asc())
.fetch();

JPAQuery<Long> countQuery = queryFactory
.select(festival.count())
.from(festival)
.where(getDateBetweenCondition(startDate, endDate));

return PageableExecutionUtils.getPage(festivals, pageable, countQuery::fetchOne);
}

private List<OrderSpecifier> getAllOrderSpecifiers(Pageable pageable, Double latitude, Double longitude) {
List<OrderSpecifier> orderSpecifiers = new ArrayList<>();

Expand Down Expand Up @@ -206,6 +223,22 @@ private JPAQuery<FestivalWithBookmark> selectFestivalWithBookmark(Long userId) {
festivalBookmarkUserIdEq(userId));
}

private JPAQuery<FestivalWithSido> selectFestivalWithSido() {

return queryFactory.select(
Projections.fields(FestivalWithSido.class,
festival.id.as("festivalId"),
festival.name,
sido.name.as("sido"),
festival.sigungu,
festival.startDate,
festival.endDate
)
).from(festival)
.leftJoin(sido)
.on(festival.sidoId.eq(sido.id));
}

private static BooleanExpression getOngoingFestivalCondition(LocalDate date) {
return festival.endDate.goe(Expressions.asDate(date));
}
Expand All @@ -221,5 +254,11 @@ private BooleanExpression festivalBookmarkUserIdEq(Long userId) {
private BooleanExpression getDateRangeCondition(LocalDate date) {
return festival.startDate.loe(date).and(festival.endDate.goe(date));
}

private BooleanExpression getDateBetweenCondition(LocalDate startDate, LocalDate endDate) {
return festival.startDate.between(startDate, endDate)
.or(festival.endDate.between(startDate, endDate))
.or(festival.startDate.loe(startDate).and(festival.endDate.goe(endDate)));
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static java.util.stream.Collectors.*;

import java.time.Clock;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Collections;
Expand All @@ -24,12 +25,14 @@
import com.odiga.fiesta.common.error.exception.CustomException;
import com.odiga.fiesta.festival.domain.Festival;
import com.odiga.fiesta.festival.dto.projection.FestivalWithBookmarkAndSido;
import com.odiga.fiesta.festival.dto.projection.FestivalWithSido;
import com.odiga.fiesta.festival.dto.request.FestivalFilterCondition;
import com.odiga.fiesta.festival.dto.request.FestivalFilterRequest;
import com.odiga.fiesta.festival.dto.response.DailyFestivalContents;
import com.odiga.fiesta.festival.dto.response.FestivalBasicResponse;
import com.odiga.fiesta.festival.dto.response.FestivalInfoResponse;
import com.odiga.fiesta.festival.dto.response.FestivalMonthlyResponse;
import com.odiga.fiesta.festival.dto.response.FestivalThisWeekResponse;
import com.odiga.fiesta.festival.repository.FestivalImageRepository;
import com.odiga.fiesta.festival.repository.FestivalRepository;
import com.odiga.fiesta.sido.repository.SidoRepository;
Expand Down Expand Up @@ -90,12 +93,11 @@ public Page<FestivalInfoResponse> getFestivalsByDay(Long userId, int year, int m

public Page<FestivalInfoResponse> getFestivalByFiltersAndSort(Long userId,
FestivalFilterRequest festivalFilterRequest,
Double latitude, Double longitude,Pageable pageable) {
Double latitude, Double longitude, Pageable pageable) {

FestivalFilterCondition festivalFilterCondition = getFestivalFilterCondition(festivalFilterRequest);

LocalDate date = LocalDate.now(clock);
System.out.println("date: " + date);
Page<FestivalWithBookmarkAndSido> festivalsByFilters = festivalRepository.findFestivalsByFiltersAndSort(userId,
festivalFilterCondition, latitude, longitude, date, pageable);

Expand All @@ -104,6 +106,26 @@ public Page<FestivalInfoResponse> getFestivalByFiltersAndSort(Long userId,
return new PageImpl<>(responses, pageable, festivalsByFilters.getTotalElements());
}

public Page<FestivalThisWeekResponse> getFestivalsInThisWeek(Pageable pageable) {

LocalDate now = LocalDate.now(clock);
LocalDate startDayOfWeek = now.with(DayOfWeek.MONDAY);
LocalDate endDayOfWeek = now.with(DayOfWeek.SUNDAY);

Page<FestivalWithSido> festivals = festivalRepository.findFestivalsAndSidoWithinDateRange(startDayOfWeek,
endDayOfWeek, pageable);
List<FestivalThisWeekResponse> responses = getFestivalAndSidoWithThumbnailImage(festivals);
return new PageImpl<>(responses, pageable, festivals.getTotalElements());
}

private List<FestivalThisWeekResponse> getFestivalAndSidoWithThumbnailImage(
Page<FestivalWithSido> festivals) {
return festivals.getContent().stream().map(festival -> {
String thumbnailImage = festivalImageRepository.findImageUrlByFestivalId(festival.getFestivalId());
return FestivalThisWeekResponse.of(festival, thumbnailImage);
}).toList();
}

private List<FestivalInfoResponse> getFestivalWithBookmarkAndSidoAndThumbnailImage(
Page<FestivalWithBookmarkAndSido> festivalsByFilters) {
return festivalsByFilters.getContent().stream().map(festival -> {
Expand Down Expand Up @@ -190,4 +212,5 @@ private void validateFestivalDay(int year, int month, int day) {
throw new CustomException(INVALID_FESTIVAL_DATE);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.odiga.fiesta.festival.dto.response.DailyFestivalContents;
import com.odiga.fiesta.festival.dto.response.FestivalInfoResponse;
import com.odiga.fiesta.festival.dto.response.FestivalMonthlyResponse;
import com.odiga.fiesta.festival.dto.response.FestivalThisWeekResponse;
import com.odiga.fiesta.festival.repository.FestivalImageRepository;
import com.odiga.fiesta.festival.repository.FestivalRepository;
import com.odiga.fiesta.sido.domain.Sido;
Expand Down Expand Up @@ -63,7 +64,7 @@ class FestivalServiceTest {
private Clock clock;

@BeforeEach
void beforeEach(){
void beforeEach() {
doReturn(Instant.now(CURRENT_CLOCK))
.when(clock)
.instant();
Expand Down Expand Up @@ -93,18 +94,18 @@ void getMonthlyFestivals() {
List<DailyFestivalContents> contents = response.getContents();
YearMonth yearMonth = YearMonth.of(year, month);

assertEquals(yearMonth.lengthOfMonth(), contents.size());
assertEquals(yearMonth.lengthOfMonth(), contents.size());

List<LocalDate> allDatesInApril = Stream.iterate(yearMonth.atDay(1), date -> date.plusDays(1))
.limit(yearMonth.lengthOfMonth())
.toList();

for (int i = 0; i < contents.size(); i++) {
DailyFestivalContents dailyContent = contents.get(i);
assertEquals(allDatesInApril.get(i), dailyContent.getDate());
assertEquals(1, dailyContent.getFestivals().size());
assertEquals(festival1.getName(), dailyContent.getFestivals().get(0).getName());
assertEquals(1, dailyContent.getTotalElements());
assertEquals(allDatesInApril.get(i), dailyContent.getDate());
assertEquals(1, dailyContent.getFestivals().size());
assertEquals(festival1.getName(), dailyContent.getFestivals().get(0).getName());
assertEquals(1, dailyContent.getTotalElements());
}
}

Expand Down Expand Up @@ -253,6 +254,32 @@ void getFestivalByFiltersAndSort_orderByDist() {
);
}

@DisplayName("이번 주 페스티벌 조회")
@Test
void getFestivalsInThisWeek() {
// given
Festival festival1 = createFestival(LocalDate.of(2023, 12, 31), LocalDate.of(2024, 1, 1));
Festival festival2 = createFestival(LocalDate.of(2023, 12, 30), LocalDate.of(2023, 12, 30));
Festival festival3 = createFestival(LocalDate.of(2024, 1, 7), LocalDate.of(2024, 1, 10));
Festival festival4 = createFestival(LocalDate.of(2024, 1, 8), LocalDate.of(2024, 1, 10));

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

festivalRepository.saveAll(List.of(festival1, festival2, festival3, festival4));

// when
Page<FestivalThisWeekResponse> responses = festivalService.getFestivalsInThisWeek(pageable);

// then
assertThat(responses.getContent())
.hasSize(2)
.extracting("startDate")
.containsExactly(
LocalDate.of(2023, 12 ,31),
LocalDate.of(2024, 1, 7)
);
}

private static Festival createFestival(LocalDate startDate, LocalDate endDate, Long sidoId) {
return Festival.builder()
.userId(1L)
Expand Down

0 comments on commit eb21e5e

Please sign in to comment.