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

[#60] 에약가능 시간 조회 로직 개선 #61

Merged
merged 1 commit into from
Mar 22, 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,32 +2,45 @@

import com.modoospace.reservation.domain.Reservation;
import com.modoospace.space.domain.Schedule;
import lombok.Getter;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lombok.Getter;

@Getter
public class TimeResponse {

private Integer hour;
private Boolean available;
private final Integer hour;
private final Boolean available;

public TimeResponse(Integer hour, Boolean available) {
this.hour = hour;
this.available = available;
}

public static List<TimeResponse> createTimeResponse(List<Schedule> schedules,
List<Reservation> reservations, LocalDate date) {
public static List<TimeResponse> createTimeResponse(List<Schedule> schedules, List<Reservation> reservations, LocalDate date) {
LocalDateTime now = LocalDateTime.now();
LocalDate nowDate = now.toLocalDate();
int nowHour = now.getHour();

return IntStream.range(0, 24)
.mapToObj(hour -> {
Boolean isAvailable = checkSchedules(schedules, hour);
Boolean isReserved = checkReservations(reservations, date, hour);
return new TimeResponse(hour, isAvailable && !isReserved);
})
.collect(Collectors.toList());
.mapToObj(hour -> {
if (date.isBefore(nowDate)) {
return new TimeResponse(hour, false);
}

if (date.equals(nowDate) && hour <= nowHour) {
return new TimeResponse(hour, false);
}

Boolean isAvailable = checkSchedules(schedules, hour);
Boolean isReserved = checkReservations(reservations, date, hour);
return new TimeResponse(hour, isAvailable && !isReserved);
})
.collect(Collectors.toList());
}

private static Boolean checkSchedules(List<Schedule> schedules, int hour) {
Expand All @@ -39,8 +52,7 @@ private static Boolean checkSchedules(List<Schedule> schedules, int hour) {
return false;
}

private static Boolean checkReservations(List<Reservation> reservations, LocalDate date,
int hour) {
private static Boolean checkReservations(List<Reservation> reservations, LocalDate date, int hour) {
for (Reservation reservation : reservations) {
if (reservation.isBetween(date, hour)) {
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.modoospace.reservation.controller.dto;

import com.modoospace.member.domain.Member;
import com.modoospace.member.domain.Role;
import com.modoospace.reservation.domain.DateTimeRange;
import com.modoospace.reservation.domain.Reservation;
import com.modoospace.space.domain.Facility;
import com.modoospace.space.domain.Schedule;
import com.modoospace.space.domain.Space;
import com.modoospace.space.domain.TimeRange;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;

class TimeResponseTest {
private final LocalDateTime now = LocalDateTime.now();
private final LocalDate nowDate = now.toLocalDate();
private final int nowHour = now.getHour();

private Member visitorMember;

private Facility facility;

@BeforeEach
public void setup() {
Member hostMember = Member.builder()
.email("host@email")
.name("host")
.role(Role.HOST)
.build();

visitorMember = Member.builder()
.email("visitor@email")
.name("visitor")
.role(Role.VISITOR)
.build();

Space space = Space.builder()
.name("스터디")
.host(hostMember)
.build();

facility = Facility.builder()
.name("스터디룸 1~3인실")
.reservationEnable(true)
.minUser(1)
.maxUser(3)
.description("1~3인실 입니다.")
.space(space)
.build();
}

@DisplayName("어제 날짜의 예약가능 여부를 체크하면 available 필드 모두 false를 반환한다.")
@Test
public void createTimeResponse_returnAllFalse_ifCheckYesterday() {
List<Schedule> schedules = List.of(new Schedule(nowDate.minusDays(1), new TimeRange(0, 24)));

List<TimeResponse> timeResponses = TimeResponse.createTimeResponse(schedules, new ArrayList<>(), nowDate.minusDays(1));

assertThat(timeResponses).hasSize(24);
assertThat(timeResponses).extracting("available").containsOnly(false);
}

@DisplayName("오늘 날짜의 예약가능 여부를 체크할 경우 현재 시간 이하면 available 필드 모두 false를 반환한다.")
@Test
public void createTimeResponse_returnFalse_ifCheckBeforeHour() {
List<Schedule> schedules = List.of(new Schedule(nowDate, new TimeRange(0, 24)));

List<TimeResponse> timeResponses = TimeResponse.createTimeResponse(schedules, new ArrayList<>(), nowDate);

assertThat(timeResponses).hasSize(24);
timeResponses.stream()
.filter(timeResponse -> timeResponse.getHour() <= nowHour)
.forEach(timeResponse -> assertThat(timeResponse.getAvailable()).isFalse());
}

@DisplayName("예약가능 여부를 체크하여 예약이 가능하면 available 필드에 true, 불가능하면 false를 반환한다.")
@Test
public void createTimeResponse() {
LocalDate tomorrow = nowDate.plusDays(1);
List<Schedule> schedules = List.of(new Schedule(tomorrow, new TimeRange(6, 22)));
List<Reservation> reservations = List.of(createReservation(tomorrow, 6, 10), createReservation(tomorrow, 12, 14));

List<TimeResponse> timeResponses = TimeResponse.createTimeResponse(schedules, reservations, tomorrow);

List<TimeResponse> availableResponse = timeResponses.stream()
.filter(TimeResponse::getAvailable)
.collect(Collectors.toList());
assertThat(availableResponse).hasSize(10); // (22-6)-(10-6)-(14-12)
assertThat(availableResponse).extracting("hour")
.containsExactly(10, 11, 14, 15, 16, 17, 18, 19, 20, 21);
}

private Reservation createReservation(LocalDate tomorrow, int startHour, int endHour) {
return Reservation.builder()
.numOfUser(2)
.dateTimeRange(new DateTimeRange(tomorrow, startHour, tomorrow, endHour))
.facility(facility)
.visitor(visitorMember)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public void createReservationRoom_throwException_ifNotOpen() {
@Test
public void getAvailabilityTime() {
AvailabilityTimeResponse retResponse = reservationService.getAvailabilityTime(facilityOpen9Close24.getId(),
now);
now.plusDays(1));

// 9~23
Assertions.assertThat(retResponse.getTimeResponses().stream()
Expand All @@ -211,7 +211,7 @@ public void getAvailabilityTime() {
@Test
public void getAvailabilityTime_24Open() {
AvailabilityTimeResponse retResponse = reservationService.getAvailabilityTime(facilityOpenClose24.getId(),
LocalDate.now());
LocalDate.now().plusDays(1));

// 0~23
Assertions.assertThat(retResponse.getTimeResponses().stream()
Expand All @@ -222,13 +222,13 @@ public void getAvailabilityTime_24Open() {
@DisplayName("특정 날짜의 예약가능시간을 조회할 수 있다.(12~15시 예약존재)")
@Test
public void getAvailableTimes_ifPresentReservation() {
ReservationCreateRequest createRequest = new ReservationCreateRequest(3, now, 12, now, 15);
LocalDate tomorrow = LocalDate.now().plusDays(1);
ReservationCreateRequest createRequest = new ReservationCreateRequest(3, tomorrow, 12, tomorrow, 15);

reservationService.createReservation(createRequest, facilityOpen9Close24.getId(),
visitorMember.getEmail());

AvailabilityTimeResponse retResponse = reservationService.getAvailabilityTime(facilityOpen9Close24.getId(),
LocalDate.now());
AvailabilityTimeResponse retResponse = reservationService.getAvailabilityTime(facilityOpen9Close24.getId(), tomorrow);

// 9시 ~ 12시, 15시 ~ 24시
Assertions.assertThat(retResponse.getTimeResponses().stream()
Expand Down
Loading