From 75ebd64cee6b471cba1b687b6106c3bcb5153279 Mon Sep 17 00:00:00 2001 From: Shim MunSeong Date: Thu, 5 May 2022 13:16:10 +0900 Subject: [PATCH 01/22] chore: version 1.4.5 (#809) --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 4a33dd3f4..2fcb4f1ff 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "zzimkkong-frontend", - "version": "1.4.4", + "version": "1.4.5", "main": "src/index.tsx", "license": "MIT", "homepage": "https://github.com/woowacourse-teams/2021-zzimkkong", From c16d3cec4242e1e20e8095fc1ede16b037d30fd9 Mon Sep 17 00:00:00 2001 From: JO YUN HO Date: Fri, 6 May 2022 15:33:25 +0900 Subject: [PATCH 02/22] =?UTF-8?q?feat:=20=EB=A7=B5=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=EA=B3=BC=20=EA=B3=B5=EA=B0=84=20=EC=9D=B4=EB=A6=84=EC=9D=98=20?= =?UTF-8?q?=EC=B5=9C=EB=8C=80=EA=B8=B8=EC=9D=B4=EB=A5=BC=2020=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=9C=ED=95=9C=ED=95=9C=EB=8B=A4=20(#815)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/ManagerMapEditor/ManagerMapEditor.tsx | 1 + frontend/src/pages/ManagerSpaceEditor/units/Form.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/frontend/src/pages/ManagerMapEditor/ManagerMapEditor.tsx b/frontend/src/pages/ManagerMapEditor/ManagerMapEditor.tsx index d7663f202..a43156708 100644 --- a/frontend/src/pages/ManagerMapEditor/ManagerMapEditor.tsx +++ b/frontend/src/pages/ManagerMapEditor/ManagerMapEditor.tsx @@ -161,6 +161,7 @@ const ManagerMapEditor = (): JSX.Element => { value={name} onChange={onChangeBoard} placeholder="맵 이름을 입력해주세요" + maxLength={20} required /> diff --git a/frontend/src/pages/ManagerSpaceEditor/units/Form.tsx b/frontend/src/pages/ManagerSpaceEditor/units/Form.tsx index 869a9f025..b1f72665c 100644 --- a/frontend/src/pages/ManagerSpaceEditor/units/Form.tsx +++ b/frontend/src/pages/ManagerSpaceEditor/units/Form.tsx @@ -144,6 +144,7 @@ const Form = ({ name="name" onChange={onChange} ref={nameInputRef} + maxLength={20} required /> From 2b16aa04d8df01ba5550632a316094a344eda337 Mon Sep 17 00:00:00 2001 From: Shim MunSeong Date: Sat, 7 May 2022 15:36:56 +0900 Subject: [PATCH 03/22] =?UTF-8?q?fix:=20=EC=84=A0=ED=83=9D=EB=90=9C=20?= =?UTF-8?q?=EB=A7=B5=20ID=EA=B0=80=20=EC=97=86=EC=9D=84=20=EB=95=8C?= =?UTF-8?q?=EB=8F=84=20=EB=93=B1=EB=A1=9D=EB=90=9C=20=EC=8A=AC=EB=9E=99=20?= =?UTF-8?q?=EC=9B=B9=ED=9B=85=20URL=EC=9D=84=20=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95=20(#822)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/ManagerMain/ManagerMain.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/pages/ManagerMain/ManagerMain.tsx b/frontend/src/pages/ManagerMain/ManagerMain.tsx index 331852904..17eea0e86 100644 --- a/frontend/src/pages/ManagerMain/ManagerMain.tsx +++ b/frontend/src/pages/ManagerMain/ManagerMain.tsx @@ -113,6 +113,7 @@ const ManagerMain = (): JSX.Element => { const getSlackWebhookUrl = useSlackWebhookUrl( { mapId: selectedMapId as number }, { + enabled: !!selectedMapId, refetchOnWindowFocus: false, onSuccess: (response) => { if (!slackUrl) setSlackUrl(response.data.slackUrl); From 3f197cb12330265ee4de7025ae4eec87e8a63069 Mon Sep 17 00:00:00 2001 From: Jungseok Sung <58401309+sakjung@users.noreply.github.com> Date: Sun, 8 May 2022 17:47:13 +0900 Subject: [PATCH 04/22] =?UTF-8?q?feat:=20=EB=A7=B5=EB=B3=84=20=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=EC=82=AC=ED=95=AD=20=EB=B3=B4=EC=97=AC=EC=A3=BC?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#821)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 공지사항 api 추가 * feat: map 조회부분 slack, notice 필드 추가 * chore: asciidoc api 추가 * feat: 공지 사항 100자 limit 검증 기능 추가 * feat: DTO valid annotation 추가 --- backend/src/docs/asciidoc/map.adoc | 8 ++++++- .../zzimkkong/controller/MapController.java | 9 ++++++++ .../com/woowacourse/zzimkkong/domain/Map.java | 18 +++++++++++++-- .../zzimkkong/dto/map/MapFindResponse.java | 14 ++++++++++++ .../dto/map/NoticeCreateRequest.java | 19 ++++++++++++++++ .../zzimkkong/service/MapService.java | 9 ++++++++ .../prod/V15__map_add_column_notice.sql | 1 + .../controller/MapControllerTest.java | 22 +++++++++++++++++++ .../dto/NoticeCreateRequestTest.java | 21 ++++++++++++++++++ 9 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/dto/map/NoticeCreateRequest.java create mode 100644 backend/src/main/resources/db/migration/prod/V15__map_add_column_notice.sql create mode 100644 backend/src/test/java/com/woowacourse/zzimkkong/dto/NoticeCreateRequestTest.java diff --git a/backend/src/docs/asciidoc/map.adoc b/backend/src/docs/asciidoc/map.adoc index e4b7db0fd..a579119a0 100644 --- a/backend/src/docs/asciidoc/map.adoc +++ b/backend/src/docs/asciidoc/map.adoc @@ -46,4 +46,10 @@ include::{snippets}/map/slackPost/http-response.adoc[] ==== Request include::{snippets}/map/slackGet/http-request.adoc[] ==== Response -include::{snippets}/map/slackGet/http-response.adoc[] \ No newline at end of file +include::{snippets}/map/slackGet/http-response.adoc[] + +=== 맵별 공지사항 등록 +==== Request +include::{snippets}/map/noticePost/http-request.adoc[] +==== Response +include::{snippets}/map/noticePost/http-response.adoc[] diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/controller/MapController.java b/backend/src/main/java/com/woowacourse/zzimkkong/controller/MapController.java index df72c7f9f..4a4c46ed0 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/controller/MapController.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/controller/MapController.java @@ -55,6 +55,15 @@ public ResponseEntity delete(@PathVariable final Long mapId, @LoginEmail f return ResponseEntity.noContent().build(); } + @PostMapping("/{mapId}/notice") + public ResponseEntity createNotice( + @PathVariable final Long mapId, + @Valid @RequestBody final NoticeCreateRequest noticeCreateRequest, + @LoginEmail final LoginEmailDto loginEmailDto) { + mapService.saveNotice(mapId, noticeCreateRequest, loginEmailDto); + return ResponseEntity.ok().build(); + } + @PostMapping("/{mapId}/slack") public ResponseEntity createSlackUrl( @PathVariable final Long mapId, diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Map.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Map.java index 9e269aeeb..f09490b01 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Map.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Map.java @@ -31,6 +31,9 @@ public class Map { @Lob private String slackUrl; + @Lob + private String notice; + @ManyToOne @JoinColumn(name = "member_id", foreignKey = @ForeignKey(name = "fk_map_member"), nullable = false) private Member member; @@ -38,7 +41,10 @@ public class Map { @OneToMany(mappedBy = "map", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, orphanRemoval = true) private List spaces = new ArrayList<>(); - public Map(final String name, final String mapDrawing, final String thumbnail, final Member member) { + public Map(final String name, + final String mapDrawing, + final String thumbnail, + final Member member) { this.name = name; this.mapDrawing = mapDrawing; this.thumbnail = thumbnail; @@ -49,7 +55,11 @@ public Map(final String name, final String mapDrawing, final String thumbnail, f } } - public Map(final Long id, final String name, final String mapDrawing, final String thumbnail, final Member member) { + public Map(final Long id, + final String name, + final String mapDrawing, + final String thumbnail, + final Member member) { this(name, mapDrawing, thumbnail, member); this.id = id; } @@ -82,6 +92,10 @@ public void updateSlackUrl(final String slackUrl) { this.slackUrl = slackUrl; } + public void updateNotice(final String notice) { + this.notice = notice; + } + public void addSpace(final Space space) { spaces.add(space); } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/dto/map/MapFindResponse.java b/backend/src/main/java/com/woowacourse/zzimkkong/dto/map/MapFindResponse.java index 381cb3d88..01e2a371c 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/dto/map/MapFindResponse.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/dto/map/MapFindResponse.java @@ -12,17 +12,23 @@ public class MapFindResponse { private String mapDrawing; private String thumbnail; private String sharingMapId; + private String slackUrl; + private String notice; private String managerEmail; private MapFindResponse(final Long mapId, final String mapName, final String mapDrawing, final String thumbnail, + final String slackUrl, + final String notice, final String sharingMapId) { this.mapId = mapId; this.mapName = mapName; this.mapDrawing = mapDrawing; this.thumbnail = thumbnail; + this.slackUrl = slackUrl; + this.notice = notice; this.sharingMapId = sharingMapId; } @@ -30,12 +36,16 @@ private MapFindResponse(final Long mapId, final String mapName, final String mapDrawing, final String thumbnail, + final String slackUrl, + final String notice, final String sharingMapId, final String managerEmail) { this.mapId = mapId; this.mapName = mapName; this.mapDrawing = mapDrawing; this.thumbnail = thumbnail; + this.slackUrl = slackUrl; + this.notice = notice; this.sharingMapId = sharingMapId; this.managerEmail = managerEmail; } @@ -47,6 +57,8 @@ public static MapFindResponse of(final Map map, map.getName(), map.getMapDrawing(), map.getThumbnail(), + map.getSlackUrl(), + map.getNotice(), sharingMapId ); } @@ -58,6 +70,8 @@ public static MapFindResponse ofAdmin(final Map map, map.getName(), map.getMapDrawing(), map.getThumbnail(), + map.getSlackUrl(), + map.getNotice(), sharingMapId, map.getMember().getEmail() ); diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/dto/map/NoticeCreateRequest.java b/backend/src/main/java/com/woowacourse/zzimkkong/dto/map/NoticeCreateRequest.java new file mode 100644 index 000000000..08f75824d --- /dev/null +++ b/backend/src/main/java/com/woowacourse/zzimkkong/dto/map/NoticeCreateRequest.java @@ -0,0 +1,19 @@ +package com.woowacourse.zzimkkong.dto.map; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Size; + +import static com.woowacourse.zzimkkong.dto.ValidatorMessage.DESCRIPTION_MESSAGE; + +@Getter +@NoArgsConstructor +public class NoticeCreateRequest { + @Size(max = 100, message = DESCRIPTION_MESSAGE) + private String notice; + + public NoticeCreateRequest(final String notice) { + this.notice = notice; + } +} diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java b/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java index f006ddf5e..ec8acb361 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java @@ -114,6 +114,15 @@ public void saveSlackUrl(final Long mapId, map.updateSlackUrl(slackCreateRequest.getSlackUrl()); } + public void saveNotice(final Long mapId, + final NoticeCreateRequest noticeCreateRequest, + final LoginEmailDto loginEmailDto) { + Map map = maps.findById(mapId) + .orElseThrow(NoSuchMapException::new); + validateManagerOfMap(map, loginEmailDto.getEmail()); + map.updateNotice(noticeCreateRequest.getNotice()); + } + @Transactional(readOnly = true) public SlackFindResponse findSlackUrl(final Long mapId, final LoginEmailDto loginEmailDto) { Map map = maps.findById(mapId) diff --git a/backend/src/main/resources/db/migration/prod/V15__map_add_column_notice.sql b/backend/src/main/resources/db/migration/prod/V15__map_add_column_notice.sql new file mode 100644 index 000000000..62a7b905d --- /dev/null +++ b/backend/src/main/resources/db/migration/prod/V15__map_add_column_notice.sql @@ -0,0 +1 @@ +ALTER TABLE map ADD COLUMN notice longtext; diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/MapControllerTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/MapControllerTest.java index 81159273b..8929caa8a 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/MapControllerTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/MapControllerTest.java @@ -126,6 +126,16 @@ void delete() { assertThat(response.statusCode()).isEqualTo(HttpStatus.NO_CONTENT.value()); } + @Test + @DisplayName("맵에 공지사항을 추가한다.") + void saveNotice() { + // given, when + ExtractableResponse response = saveNotice(createdMapApi + "/notice", new NoticeCreateRequest("공지사항 입니다.")); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + } + @Test @DisplayName("맵에 슬랙url을 추가한다.") void saveSlackUrl() { @@ -162,6 +172,18 @@ static ExtractableResponse saveMap(final String api, MapCreateUpdateRe .then().log().all().extract(); } + private ExtractableResponse saveNotice(final String api, NoticeCreateRequest noticeCreateRequest) { + return RestAssured + .given(getRequestSpecification()).log().all() + .accept("application/json") + .header("Authorization", AuthorizationExtractor.AUTHENTICATION_TYPE + " " + accessToken) + .filter(document("map/noticePost", getRequestPreprocessor(), getResponsePreprocessor())) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(noticeCreateRequest) + .when().post(api) + .then().log().all().extract(); + } + private ExtractableResponse saveSlackUrl(final String api, SlackCreateRequest slackCreateRequest) { return RestAssured .given(getRequestSpecification()).log().all() diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/dto/NoticeCreateRequestTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/dto/NoticeCreateRequestTest.java new file mode 100644 index 000000000..4c6e59f91 --- /dev/null +++ b/backend/src/test/java/com/woowacourse/zzimkkong/dto/NoticeCreateRequestTest.java @@ -0,0 +1,21 @@ +package com.woowacourse.zzimkkong.dto; + +import com.woowacourse.zzimkkong.dto.map.NoticeCreateRequest; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Description; + +import static com.woowacourse.zzimkkong.dto.ValidatorMessage.DESCRIPTION_MESSAGE; +import static org.assertj.core.api.Assertions.assertThat; + +class NoticeCreateRequestTest extends RequestTest { + @Test + @Description("100자 이상 공지사항이 들어오면 예외를 반환한다.") + void noticeLengthOverSizeLimit() { + NoticeCreateRequest noticeCreateRequest = new NoticeCreateRequest( + "iamtenwordiamtenwordiamtenwordiamtenwordiamtenwordiamtenwordiamtenwordiamtenwordiamtenwordiamtenword1"); + + assertThat(getConstraintViolations(noticeCreateRequest).stream() + .anyMatch(violation -> violation.getMessage().equals(DESCRIPTION_MESSAGE))) + .isTrue(); + } +} \ No newline at end of file From be9d86a7351f126641a0dbc731c339d4ca55d62a Mon Sep 17 00:00:00 2001 From: Jungseok Sung <58401309+sakjung@users.noreply.github.com> Date: Wed, 25 May 2022 19:49:41 +0900 Subject: [PATCH 05/22] =?UTF-8?q?refactor:=20=EC=98=88=EC=95=BD=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EA=B4=80=EB=A0=A8=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=EB=93=A4=20=EC=83=9D=EC=84=B1=20(#796)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: reservation 관련 DTO들에서 datetime 관련 데이터들이 timezone 정보를 갖도록 리팩터링 * chore: indent 컨벤션에 맞게 리포맷팅 * fix: 날짜 관련 로직이 timezone을 고려하도록 수정 * chore: 코드 리포맷팅 및 코드 컨벤션에 맞게 리팩터링 * refactor: 시간 관련 도메인 객체들 추가 * refactor: Setting 필드를 시간관련 Embeddable 객체들로 대체 * refactor: Reservation 시간관련 필드들 ReservationTime embeddable 객체로 대체 * test: Minute test 작성 * test: TimeSlot test 추가 * test: ReservationTime test 추가 * fix: Slack 알람 송신 시 예약 시간 KST로 보내주도록 수정 * refactor: 코드 리뷰 반영 cache ConcurrentHashMap, code reformatting & refactoring --- .../com/woowacourse/zzimkkong/DataLoader.java | 52 +++--- .../woowacourse/zzimkkong/domain/Member.java | 4 +- .../woowacourse/zzimkkong/domain/Preset.java | 12 ++ .../zzimkkong/domain/Reservation.java | 49 ++--- .../zzimkkong/domain/ReservationTime.java | 117 ++++++++++++ .../woowacourse/zzimkkong/domain/Setting.java | 97 +++++----- .../woowacourse/zzimkkong/domain/Space.java | 93 ++++----- .../zzimkkong/domain/TimeSlot.java | 73 ++++++++ .../zzimkkong/domain/TimeUnit.java | 64 +++++++ .../dto/member/PresetFindResponse.java | 6 +- .../zzimkkong/dto/slack/SlackResponse.java | 13 +- .../zzimkkong/dto/space/SettingResponse.java | 6 +- .../IllegalTimeUnitValueException.java | 12 ++ .../ImpossibleEndTimeException.java | 12 -- .../ImpossibleStartEndTimeException.java | 12 ++ ... => NonMatchingStartEndDateException.java} | 4 +- ...java => PastReservationTimeException.java} | 6 +- ...ossibleAvailableStartEndTimeException.java | 12 -- .../repository/ReservationRepository.java | 17 +- .../ReservationRepositoryCustom.java | 4 +- .../repository/ReservationRepositoryImpl.java | 8 +- .../zzimkkong/service/MapService.java | 2 +- .../zzimkkong/service/MemberService.java | 4 +- .../zzimkkong/service/PresetService.java | 16 +- .../zzimkkong/service/ReservationService.java | 108 ++++------- .../zzimkkong/service/SpaceService.java | 18 +- .../com/woowacourse/zzimkkong/Constants.java | 14 +- .../zzimkkong/controller/AcceptanceTest.java | 24 +-- .../controller/AdminControllerTest.java | 12 +- .../GuestReservationControllerTest.java | 87 +++++---- .../controller/GuestSpaceControllerTest.java | 15 +- .../ManagerReservationControllerTest.java | 80 ++++---- .../ManagerSpaceControllerTest.java | 26 +-- .../controller/MemberControllerTest.java | 12 +- .../zzimkkong/domain/MemberTest.java | 5 +- .../zzimkkong/domain/PresetTest.java | 5 +- .../zzimkkong/domain/ReservationTest.java | 17 +- .../zzimkkong/domain/ReservationTimeTest.java | 134 +++++++++++++ .../zzimkkong/domain/SettingTest.java | 65 +++---- .../zzimkkong/domain/SpaceTest.java | 176 ++++-------------- .../zzimkkong/domain/TimeSlotTest.java | 152 +++++++++++++++ .../zzimkkong/domain/TimeUnitTest.java | 63 +++++++ .../dto/PresetCreateRequestTest.java | 6 +- .../zzimkkong/dto/RequestTest.java | 6 +- .../repository/MapRepositoryTest.java | 15 +- .../repository/PresetRepositoryTest.java | 7 +- .../ReservationRepositoryImplTest.java | 26 +-- .../repository/ReservationRepositoryTest.java | 53 +++--- .../repository/SpaceRepositoryTest.java | 15 +- .../zzimkkong/service/AdminServiceTest.java | 17 +- .../service/GuestReservationServiceTest.java | 108 ++++++----- .../ManagerReservationServiceTest.java | 110 ++++++----- .../zzimkkong/service/MapServiceTest.java | 20 +- .../zzimkkong/service/MemberServiceTest.java | 5 +- .../zzimkkong/service/PresetServiceTest.java | 12 +- .../zzimkkong/service/SpaceServiceTest.java | 32 ++-- 56 files changed, 1326 insertions(+), 814 deletions(-) create mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/domain/ReservationTime.java create mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeSlot.java create mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeUnit.java create mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/IllegalTimeUnitValueException.java delete mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleEndTimeException.java create mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleStartEndTimeException.java rename backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/{NonMatchingStartAndEndDateException.java => NonMatchingStartEndDateException.java} (72%) rename backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/{ImpossibleStartTimeException.java => PastReservationTimeException.java} (52%) delete mode 100644 backend/src/main/java/com/woowacourse/zzimkkong/exception/space/ImpossibleAvailableStartEndTimeException.java create mode 100644 backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTimeTest.java create mode 100644 backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeSlotTest.java create mode 100644 backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeUnitTest.java diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/DataLoader.java b/backend/src/main/java/com/woowacourse/zzimkkong/DataLoader.java index 9276ee639..224b63444 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/DataLoader.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/DataLoader.java @@ -53,11 +53,13 @@ public void run(String... args) { ); Setting defaultSetting = Setting.builder() - .availableStartTime(LocalTime.of(9, 0)) - .availableEndTime(LocalTime.of(22, 00)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(700) + .availableTimeSlot( + TimeSlot.of( + LocalTime.of(9, 0), + LocalTime.of(22, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(700)) .reservationEnable(true) .enabledDayOfWeek("monday,tuesday,wednesday,thursday,friday,saturday,sunday") .build(); @@ -175,10 +177,10 @@ public void run(String... args) { LocalDate targetDate = LocalDate.now().plusDays(1L); Reservation reservationBackEndTargetDate0To1 = Reservation.builder() - .date(targetDate) - .startTime(targetDate.atStartOfDay()) - .endTime(targetDate.atTime(1, 0, 0)) - .date(targetDate) + .reservationTime( + ReservationTime.of( + targetDate.atStartOfDay(), + targetDate.atTime(1, 0, 0))) .description("찜꽁 1차 회의") .userName("찜꽁") .password("1234") @@ -186,10 +188,10 @@ public void run(String... args) { .build(); Reservation reservationBackEndTargetDate13To14 = Reservation.builder() - .date(targetDate) - .startTime(targetDate.atTime(13, 0, 0)) - .endTime(targetDate.atTime(14, 0, 0)) - .date(targetDate) + .reservationTime( + ReservationTime.of( + targetDate.atTime(13, 0, 0), + targetDate.atTime(14, 0, 0))) .description("찜꽁 2차 회의") .userName("찜꽁") .password("1234") @@ -197,10 +199,10 @@ public void run(String... args) { .build(); Reservation reservationBackEndTargetDate18To23 = Reservation.builder() - .date(targetDate) - .startTime(targetDate.atTime(18, 0, 0)) - .endTime(targetDate.atTime(23, 59, 59)) - .date(targetDate) + .reservationTime( + ReservationTime.of( + targetDate.atTime(18, 0, 0), + targetDate.atTime(23, 0, 0))) .description("찜꽁 3차 회의") .userName("찜꽁") .password("6789") @@ -208,10 +210,10 @@ public void run(String... args) { .build(); Reservation reservationBackEndTheDayAfterTargetDate = Reservation.builder() - .date(targetDate) - .startTime(targetDate.plusDays(1L).atStartOfDay()) - .endTime(targetDate.plusDays(1L).atTime(1, 0, 0)) - .date(targetDate) + .reservationTime( + ReservationTime.of( + targetDate.plusDays(1L).atStartOfDay(), + targetDate.plusDays(1L).atTime(1, 0, 0))) .description("찜꽁 4차 회의") .userName("찜꽁") .password("1234") @@ -219,10 +221,10 @@ public void run(String... args) { .build(); Reservation reservationFrontEnd1TargetDate0to1 = Reservation.builder() - .date(targetDate) - .startTime(targetDate.atStartOfDay()) - .endTime(targetDate.atTime(1, 0, 0)) - .date(targetDate) + .reservationTime( + ReservationTime.of( + targetDate.atStartOfDay(), + targetDate.atTime(1, 0, 0))) .description("찜꽁 5차 회의") .userName("찜꽁") .password("1234") diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Member.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Member.java index fd7ac1dcd..da60ec1a6 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Member.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Member.java @@ -32,10 +32,10 @@ public class Member { private OauthProvider oauthProvider; @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE, orphanRemoval = true) - private List presets = new ArrayList<>(); + private final List presets = new ArrayList<>(); @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE, orphanRemoval = true) - private List maps = new ArrayList<>(); + private final List maps = new ArrayList<>(); public Member( final String email, diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Preset.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Preset.java index 08786b27d..03b9952a0 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Preset.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Preset.java @@ -17,6 +17,18 @@ public class Preset { private String name; @Embedded + @AttributeOverrides({ + @AttributeOverride(name = "availableTimeSlot.startTime", + column = @Column(name = "available_start_time")), + @AttributeOverride(name = "availableTimeSlot.endTime", + column = @Column(name = "available_end_time")), + @AttributeOverride(name = "reservationTimeUnit.minutes", + column = @Column(name = "reservation_time_unit")), + @AttributeOverride(name = "reservationMinimumTimeUnit.minutes", + column = @Column(name = "reservation_minimum_time_unit")), + @AttributeOverride(name = "reservationMaximumTimeUnit.minutes", + column = @Column(name = "reservation_maximum_time_unit")) + }) private Setting setting; @ManyToOne(fetch = FetchType.LAZY) diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Reservation.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Reservation.java index e01fe8539..2e38322b1 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Reservation.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Reservation.java @@ -1,16 +1,11 @@ package com.woowacourse.zzimkkong.domain; -import com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import javax.persistence.*; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.TimeZone; - -import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.UTC; @Getter @Builder @@ -22,14 +17,8 @@ public class Reservation { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) - private LocalDate date; - - @Column(nullable = false) - private LocalDateTime startTime; - - @Column(nullable = false) - private LocalDateTime endTime; + @Embedded + private ReservationTime reservationTime; @Column(nullable = false, length = 20) private String password; @@ -46,17 +35,13 @@ public class Reservation { protected Reservation( final Long id, - final LocalDate date, - final LocalDateTime startTime, - final LocalDateTime endTime, + final ReservationTime reservationTime, final String password, final String userName, final String description, final Space space) { this.id = id; - this.date = date; - this.startTime = startTime.withSecond(0).withNano(0); - this.endTime = endTime.withSecond(0).withNano(0); + this.reservationTime = reservationTime; this.password = password; this.userName = userName; this.description = description; @@ -67,34 +52,26 @@ protected Reservation( } } - public boolean hasConflictWith(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { - return !(isEarlier(endDateTime) || isLater(startDateTime)); - } - - private boolean isEarlier(final LocalDateTime endDateTime) { - return endDateTime.equals(this.startTime) || endDateTime.isBefore(this.startTime); + public boolean hasConflictWith(final ReservationTime thatReservationTime) { + return this.reservationTime.hasConflictWith(thatReservationTime); } - private boolean isLater(final LocalDateTime startDateTime) { - return startDateTime.equals(this.endTime) || startDateTime.isAfter(this.endTime); + public boolean isWrongPassword(final String password) { + return !this.password.equals(password); } public void update(final Reservation updateReservation, final Space space) { - this.date = updateReservation.date; - this.startTime = updateReservation.startTime; - this.endTime = updateReservation.endTime; + this.reservationTime = updateReservation.reservationTime; this.userName = updateReservation.userName; this.description = updateReservation.description; this.space = space; } - public boolean isWrongPassword(final String password) { - return !this.password.equals(password); + public LocalDateTime getStartTime() { + return reservationTime.getStartTime(); } - public boolean isBookedOn(final LocalDate date, final TimeZone timeZone) { - LocalDate convertedStartTimeDate = TimeZoneUtils.convert(startTime, UTC, timeZone).toLocalDate(); - LocalDate convertedEndTimeDate = TimeZoneUtils.convert(endTime, UTC, timeZone).toLocalDate(); - return date.equals(convertedStartTimeDate) && date.equals(convertedEndTimeDate); + public LocalDateTime getEndTime() { + return reservationTime.getEndTime(); } } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/ReservationTime.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/ReservationTime.java new file mode 100644 index 000000000..e91a7d797 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/ReservationTime.java @@ -0,0 +1,117 @@ +package com.woowacourse.zzimkkong.domain; + +import com.woowacourse.zzimkkong.exception.reservation.NonMatchingStartEndDateException; +import com.woowacourse.zzimkkong.exception.reservation.PastReservationTimeException; +import com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.KST; +import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.UTC; + +@Getter +@NoArgsConstructor +@EqualsAndHashCode +@Embeddable +public class ReservationTime { + /** + * The reservation date in KST (the time zone of the map) + */ + @Column(nullable = false) + private LocalDate date; + + /** + * The reservation start date time in UTC + */ + @Column(nullable = false) + private LocalDateTime startTime; + + /** + * The reservation end date time in UTC + */ + @Column(nullable = false) + private LocalDateTime endTime; + + private ReservationTime(final LocalDate date, final LocalDateTime startTime, final LocalDateTime endTime) { + this.date = date; + this.startTime = startTime; + this.endTime = endTime; + } + + public static ReservationTime of( + final LocalDateTime startDateTime, + final LocalDateTime endDateTime, + final boolean manageable) { + LocalDateTime reservationStartDateTime = startDateTime.withSecond(0).withNano(0); + LocalDateTime reservationEndDateTime = endDateTime.withSecond(0).withNano(0); + validateReservationTime(reservationStartDateTime, reservationEndDateTime, manageable); + + LocalDate date = TimeZoneUtils.convert(reservationStartDateTime, UTC, KST).toLocalDate(); + return new ReservationTime(date, reservationStartDateTime, reservationEndDateTime); + } + + public static ReservationTime of( + final LocalDateTime startDateTime, + final LocalDateTime endDateTime) { + return of(startDateTime, endDateTime, true); + } + + public static void validatePastTime(final LocalDateTime startDateTime) { + if (startDateTime.isBefore(LocalDateTime.now())) { + throw new PastReservationTimeException(); + } + } + + private static void validateReservationTime( + final LocalDateTime startDateTime, + final LocalDateTime endDateTime, + final boolean manageable) { + LocalDateTime startDateTimeKST = TimeZoneUtils.convert(startDateTime, UTC, KST); + LocalDateTime endDateTimeKST = TimeZoneUtils.convert(endDateTime, UTC, KST); + + if (!manageable) { + validatePastTime(startDateTime); + } + validateStartEndDate(startDateTimeKST, endDateTimeKST); + TimeSlot.validateStartEndTime(startDateTimeKST.toLocalTime(), endDateTimeKST.toLocalTime()); + } + + private static void validateStartEndDate(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { + LocalDate startDate = startDateTime.toLocalDate(); + LocalDate endDate = endDateTime.toLocalDate(); + + if (!startDate.isEqual(endDate)) { + throw new NonMatchingStartEndDateException(); + } + } + + public DayOfWeek getDayOfWeekKST() { + return date.getDayOfWeek(); + } + + public TimeSlot asTimeSlotKST() { + LocalDateTime startDateTimeKST = TimeZoneUtils.convert(startTime, UTC, KST); + LocalDateTime endDateTimeKST = TimeZoneUtils.convert(endTime, UTC, KST); + + return TimeSlot.of(startDateTimeKST.toLocalTime(), endDateTimeKST.toLocalTime()); + } + + public boolean hasConflictWith(final ReservationTime that) { + return !(this.isEarlierThan(that) || this.isLaterThan(that)); + } + + private boolean isEarlierThan(final ReservationTime that) { + return this.endTime.equals(that.startTime) || this.endTime.isBefore(that.startTime); + } + + private boolean isLaterThan(final ReservationTime that) { + return this.startTime.equals(that.endTime) || this.startTime.isAfter(that.endTime); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Setting.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Setting.java index 63ff3cef2..57843a503 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Setting.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Setting.java @@ -1,34 +1,36 @@ package com.woowacourse.zzimkkong.domain; -import com.woowacourse.zzimkkong.exception.space.*; +import com.woowacourse.zzimkkong.exception.space.InvalidMinimumMaximumTimeUnitException; +import com.woowacourse.zzimkkong.exception.space.NotEnoughAvailableTimeException; +import com.woowacourse.zzimkkong.exception.space.TimeUnitInconsistencyException; +import com.woowacourse.zzimkkong.exception.space.TimeUnitMismatchException; import lombok.Builder; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import javax.persistence.Column; import javax.persistence.Embeddable; +import javax.persistence.Embedded; import java.time.LocalTime; -import java.time.temporal.ChronoUnit; @Getter -@Builder @NoArgsConstructor +@Builder +@EqualsAndHashCode @Embeddable public class Setting { - @Column(nullable = false) - private LocalTime availableStartTime; + @Embedded + private TimeSlot availableTimeSlot; - @Column(nullable = false) - private LocalTime availableEndTime; + @Embedded + private TimeUnit reservationTimeUnit; - @Column(nullable = false) - private Integer reservationTimeUnit; + @Embedded + private TimeUnit reservationMinimumTimeUnit; - @Column(nullable = false) - private Integer reservationMinimumTimeUnit; - - @Column(nullable = false) - private Integer reservationMaximumTimeUnit; + @Embedded + private TimeUnit reservationMaximumTimeUnit; @Column(nullable = false) private Boolean reservationEnable; @@ -37,15 +39,13 @@ public class Setting { private String enabledDayOfWeek; protected Setting( - final LocalTime availableStartTime, - final LocalTime availableEndTime, - final Integer reservationTimeUnit, - final Integer reservationMinimumTimeUnit, - final Integer reservationMaximumTimeUnit, + final TimeSlot availableTimeSlot, + final TimeUnit reservationTimeUnit, + final TimeUnit reservationMinimumTimeUnit, + final TimeUnit reservationMaximumTimeUnit, final Boolean reservationEnable, final String enabledDayOfWeek) { - this.availableStartTime = availableStartTime; - this.availableEndTime = availableEndTime; + this.availableTimeSlot = availableTimeSlot; this.reservationTimeUnit = reservationTimeUnit; this.reservationMinimumTimeUnit = reservationMinimumTimeUnit; this.reservationMaximumTimeUnit = reservationMaximumTimeUnit; @@ -56,15 +56,11 @@ protected Setting( } private void validateSetting() { - if (availableStartTime.equals(availableEndTime) || availableStartTime.isAfter(availableEndTime)) { - throw new ImpossibleAvailableStartEndTimeException(); - } - - if (isNoneMatchingAvailableTimeAndTimeUnit()) { + if (availableTimeSlot.isNotDivisibleBy(reservationTimeUnit)) { throw new TimeUnitMismatchException(); } - if (reservationMaximumTimeUnit < reservationMinimumTimeUnit) { + if (reservationMaximumTimeUnit.isShorterThan(reservationMinimumTimeUnit)) { throw new InvalidMinimumMaximumTimeUnitException(); } @@ -72,32 +68,49 @@ private void validateSetting() { throw new TimeUnitInconsistencyException(); } - int duration = (int) ChronoUnit.MINUTES.between(availableStartTime, availableEndTime); - if (duration < reservationMaximumTimeUnit) { + if (availableTimeSlot.isDurationShorterThan(reservationMaximumTimeUnit)) { throw new NotEnoughAvailableTimeException(); } } - private boolean isNoneMatchingAvailableTimeAndTimeUnit() { - return isNotDivisibleByTimeUnit(availableStartTime.getMinute()) || isNotDivisibleByTimeUnit(availableEndTime.getMinute()); + public boolean cannotDivideByTimeUnit(final TimeSlot timeSlot) { + return timeSlot.isNotDivisibleBy(reservationTimeUnit); } - public boolean isNotDivisibleByTimeUnit(final int minute) { - return minute % this.reservationTimeUnit != 0; + public boolean hasLongerMinimumTimeUnitThan(final TimeSlot timeSlot) { + return timeSlot.isDurationShorterThan(reservationMinimumTimeUnit); } - private boolean isNotConsistentTimeUnit() { - return !(isMinimumTimeUnitConsistentWithTimeUnit() && isMaximumTimeUnitConsistentWithTimeUnit()); + public boolean hasShorterMaximumTimeUnitThan(final TimeSlot timeSlot) { + return timeSlot.isDurationLongerThan(reservationMaximumTimeUnit); } - private boolean isMinimumTimeUnitConsistentWithTimeUnit() { - int minimumTimeUnitQuotient = reservationMinimumTimeUnit / reservationTimeUnit; - int minimumTimeUnitRemainder = reservationMinimumTimeUnit % reservationTimeUnit; - return minimumTimeUnitRemainder == 0 && 1 <= minimumTimeUnitQuotient; + public boolean hasNotEnoughAvailableTimeToCover(final TimeSlot timeSlot) { + return timeSlot.isNotWithin(availableTimeSlot); } - private boolean isMaximumTimeUnitConsistentWithTimeUnit() { - int maximumTimeUnitRemainder = reservationMaximumTimeUnit % reservationTimeUnit; - return maximumTimeUnitRemainder == 0; + public LocalTime getAvailableStartTime() { + return availableTimeSlot.getStartTime(); + } + + public LocalTime getAvailableEndTime() { + return availableTimeSlot.getEndTime(); + } + + public Integer getReservationTimeUnitAsInt() { + return reservationTimeUnit.getMinutes(); + } + + public Integer getReservationMinimumTimeUnitAsInt() { + return reservationMinimumTimeUnit.getMinutes(); + } + + public Integer getReservationMaximumTimeUnitAsInt() { + return reservationMaximumTimeUnit.getMinutes(); + } + + private boolean isNotConsistentTimeUnit() { + return !(reservationMinimumTimeUnit.isDivisibleBy(reservationTimeUnit) && + reservationMaximumTimeUnit.isDivisibleBy(reservationTimeUnit)); } } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Space.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Space.java index e0d509a51..8dd90b76c 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/domain/Space.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/Space.java @@ -9,7 +9,6 @@ import javax.persistence.*; import java.time.DayOfWeek; -import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.Arrays; @@ -43,6 +42,18 @@ public class Space { private String area; @Embedded + @AttributeOverrides({ + @AttributeOverride(name = "availableTimeSlot.startTime", + column = @Column(name = "available_start_time")), + @AttributeOverride(name = "availableTimeSlot.endTime", + column = @Column(name = "available_end_time")), + @AttributeOverride(name = "reservationTimeUnit.minutes", + column = @Column(name = "reservation_time_unit")), + @AttributeOverride(name = "reservationMinimumTimeUnit.minutes", + column = @Column(name = "reservation_minimum_time_unit")), + @AttributeOverride(name = "reservationMaximumTimeUnit.minutes", + column = @Column(name = "reservation_maximum_time_unit")) + }) private Setting setting; @ManyToOne(fetch = FetchType.LAZY) @@ -84,24 +95,20 @@ public void update(final Space updateSpace) { this.setting = updateSpace.setting; } - public boolean isNotBetweenAvailableTime(final LocalDateTime startDateTime, LocalDateTime endDateTime) { - boolean isEqualOrAfterStartTime = startDateTime.toLocalTime().equals(getAvailableStartTime()) || - startDateTime.toLocalTime().isAfter(getAvailableStartTime()); - boolean isEqualOrBeforeEndTime = endDateTime.toLocalTime().equals(getAvailableEndTime()) || - endDateTime.toLocalTime().isBefore(getAvailableEndTime()); - return !(isEqualOrAfterStartTime && isEqualOrBeforeEndTime); + public boolean cannotAcceptDueToTimeUnit(final TimeSlot timeSlot) { + return setting.cannotDivideByTimeUnit(timeSlot); } - public boolean isNotDivisibleByTimeUnit(final int minute) { - return setting.isNotDivisibleByTimeUnit(minute); + public boolean cannotAcceptDueToMinimumTimeUnit(final TimeSlot timeSlot) { + return setting.hasLongerMinimumTimeUnitThan(timeSlot); } - public boolean isIncorrectMinimumTimeUnit(final int durationMinutes) { - return durationMinutes < getReservationMinimumTimeUnit(); + public boolean cannotAcceptDueToMaximumTimeUnit(final TimeSlot timeSlot) { + return setting.hasShorterMaximumTimeUnitThan(timeSlot); } - public boolean isIncorrectMaximumTimeUnit(final int durationMinutes) { - return durationMinutes > getReservationMaximumTimeUnit(); + public boolean cannotAcceptDueToAvailableTime(final TimeSlot timeSlot) { + return setting.hasNotEnoughAvailableTimeToCover(timeSlot); } public boolean isUnableToReserve() { @@ -113,26 +120,6 @@ public boolean isClosedOn(final DayOfWeek dayOfWeek) { .noneMatch(enabledDayOfWeek -> enabledDayOfWeek.equals(dayOfWeek)); } - private List getEnabledDaysOfWeek() { - String enabledDayOfWeekNames = getEnabledDayOfWeek(); - - if (enabledDayOfWeekNames == null) { - return Collections.emptyList(); - } - - return Arrays.stream(enabledDayOfWeekNames.split(DELIMITER)) - .map(String::trim) - .map(this::convertToDayOfWeek) - .collect(Collectors.toList()); - } - - private DayOfWeek convertToDayOfWeek(final String dayOfWeekName) { - return Arrays.stream(DayOfWeek.values()) - .filter(dayOfWeek -> dayOfWeek.name().equals(dayOfWeekName.toUpperCase())) - .findAny() - .orElseThrow(NoSuchDayOfWeekException::new); - } - public void addReservation(final Reservation reservation) { reservations.add(reservation); } @@ -141,24 +128,24 @@ public boolean hasSameId(final Long spaceId) { return id.equals(spaceId); } - public LocalTime getAvailableEndTime() { - return setting.getAvailableEndTime(); - } - public LocalTime getAvailableStartTime() { return setting.getAvailableStartTime(); } - public Integer getReservationTimeUnit() { - return setting.getReservationTimeUnit(); + public LocalTime getAvailableEndTime() { + return setting.getAvailableEndTime(); + } + + public Integer getReservationTimeUnitAsInt() { + return setting.getReservationTimeUnitAsInt(); } - public Integer getReservationMinimumTimeUnit() { - return setting.getReservationMinimumTimeUnit(); + public Integer getReservationMinimumTimeUnitAsInt() { + return setting.getReservationMinimumTimeUnitAsInt(); } - public Integer getReservationMaximumTimeUnit() { - return setting.getReservationMaximumTimeUnit(); + public Integer getReservationMaximumTimeUnitAsInt() { + return setting.getReservationMaximumTimeUnitAsInt(); } public Boolean getReservationEnable() { @@ -168,4 +155,24 @@ public Boolean getReservationEnable() { public String getEnabledDayOfWeek() { return setting.getEnabledDayOfWeek(); } + + private List getEnabledDaysOfWeek() { + String enabledDayOfWeekNames = getEnabledDayOfWeek(); + + if (enabledDayOfWeekNames == null) { + return Collections.emptyList(); + } + + return Arrays.stream(enabledDayOfWeekNames.split(DELIMITER)) + .map(String::trim) + .map(this::convertToDayOfWeek) + .collect(Collectors.toList()); + } + + private DayOfWeek convertToDayOfWeek(final String dayOfWeekName) { + return Arrays.stream(DayOfWeek.values()) + .filter(dayOfWeek -> dayOfWeek.name().equals(dayOfWeekName.toUpperCase())) + .findAny() + .orElseThrow(NoSuchDayOfWeekException::new); + } } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeSlot.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeSlot.java new file mode 100644 index 000000000..7f7a2b680 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeSlot.java @@ -0,0 +1,73 @@ +package com.woowacourse.zzimkkong.domain; + +import com.woowacourse.zzimkkong.exception.reservation.IllegalTimeUnitValueException; +import com.woowacourse.zzimkkong.exception.reservation.ImpossibleStartEndTimeException; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; + +@Getter +@NoArgsConstructor +@EqualsAndHashCode +@Embeddable +public class TimeSlot { + @Column(nullable = false) + private LocalTime startTime; + + @Column(nullable = false) + private LocalTime endTime; + + private TimeSlot( + final LocalTime startTime, + final LocalTime endTime) { + this.startTime = startTime; + this.endTime = endTime; + validateStartEndTime(startTime, endTime); + } + + public static TimeSlot of(final LocalTime startTime, final LocalTime endTime) { + return new TimeSlot(startTime, endTime); + } + + public static void validateStartEndTime(final LocalTime startTime, final LocalTime endTime) { + if (endTime.isBefore(startTime) || startTime.equals(endTime)) { + throw new ImpossibleStartEndTimeException(); + } + + if (TimeUnit.cannotDivideByMinimumTimeUnit(startTime.getMinute())) { + throw new IllegalTimeUnitValueException(startTime.getMinute()); + } + + if (TimeUnit.cannotDivideByMinimumTimeUnit(endTime.getMinute())) { + throw new IllegalTimeUnitValueException(endTime.getMinute()); + } + } + + public boolean isNotDivisibleBy(final TimeUnit timeUnit) { + return !(timeUnit.canDivide(startTime) && timeUnit.canDivide(endTime)); + } + + public boolean isDurationShorterThan(final TimeUnit timeUnit) { + return getDurationMinute().isShorterThan(timeUnit); + } + + public boolean isDurationLongerThan(final TimeUnit timeUnit) { + return timeUnit.isShorterThan(getDurationMinute()); + } + + public boolean isNotWithin(final TimeSlot that) { + boolean isEqualOrAfterStartTime = this.startTime.equals(that.startTime) || this.startTime.isAfter(that.startTime); + boolean isEqualOrBeforeEndTime = this.endTime.equals(that.endTime) || this.endTime.isBefore(that.endTime); + return !(isEqualOrAfterStartTime && isEqualOrBeforeEndTime); + } + + private TimeUnit getDurationMinute() { + return TimeUnit.from(ChronoUnit.MINUTES.between(startTime, endTime)); + } +} + diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeUnit.java b/backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeUnit.java new file mode 100644 index 000000000..c71736c96 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/zzimkkong/domain/TimeUnit.java @@ -0,0 +1,64 @@ +package com.woowacourse.zzimkkong.domain; + +import com.woowacourse.zzimkkong.exception.reservation.IllegalTimeUnitValueException; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.time.LocalTime; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Getter +@NoArgsConstructor +@EqualsAndHashCode +@Embeddable +public class TimeUnit { + public static final Integer MINIMUM_TIME_UNIT = 5; + private static final Integer MINIMUM_TIME = 0; + private static final Map cache = new ConcurrentHashMap<>(); + + static { + for (int i = 1; i <= 24; i++) { + Integer minutes = i * MINIMUM_TIME_UNIT; + cache.put(minutes, new TimeUnit(minutes)); + } + } + + @Column(nullable = false) + private Integer minutes; + + private TimeUnit(final Integer minutes) { + this.minutes = minutes; + + if (this.minutes <= MINIMUM_TIME || cannotDivideByMinimumTimeUnit(this.minutes)) { + throw new IllegalTimeUnitValueException(this.minutes); + } + } + + public static TimeUnit from(final int minutes) { + return cache.getOrDefault(minutes, new TimeUnit(minutes)); + } + + public static TimeUnit from(final long minutes) { + return cache.getOrDefault((int) minutes, new TimeUnit((int) minutes)); + } + + public static boolean cannotDivideByMinimumTimeUnit(final int minutes) { + return minutes % MINIMUM_TIME_UNIT != 0; + } + + public boolean isDivisibleBy(final TimeUnit that) { + return this.minutes % that.minutes == 0; + } + + public boolean canDivide(final LocalTime time) { + return time.getMinute() % this.minutes == 0; + } + + public boolean isShorterThan(final TimeUnit that) { + return this.minutes < that.minutes; + } +} diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/dto/member/PresetFindResponse.java b/backend/src/main/java/com/woowacourse/zzimkkong/dto/member/PresetFindResponse.java index 47df4faab..20d2545b5 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/dto/member/PresetFindResponse.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/dto/member/PresetFindResponse.java @@ -37,9 +37,9 @@ public static PresetFindResponse from(final Preset preset) { preset.getId(), setting.getAvailableStartTime(), setting.getAvailableEndTime(), - setting.getReservationTimeUnit(), - setting.getReservationMinimumTimeUnit(), - setting.getReservationMaximumTimeUnit(), + setting.getReservationTimeUnitAsInt(), + setting.getReservationMinimumTimeUnitAsInt(), + setting.getReservationMaximumTimeUnitAsInt(), setting.getReservationEnable(), EnabledDayOfWeekDto.from(setting.getEnabledDayOfWeek()), preset.getName()); diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/dto/slack/SlackResponse.java b/backend/src/main/java/com/woowacourse/zzimkkong/dto/slack/SlackResponse.java index d3c5780ed..98a960135 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/dto/slack/SlackResponse.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/dto/slack/SlackResponse.java @@ -7,6 +7,9 @@ import java.time.LocalDateTime; +import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.KST; +import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.UTC; + @Getter @NoArgsConstructor public class SlackResponse { @@ -34,14 +37,8 @@ private SlackResponse( } public static SlackResponse of(final Reservation reservation, final String sharingMapId, final String slackUrl) { - LocalDateTime reservationStartTimeKST = TimeZoneUtils.convert( - reservation.getStartTime(), - TimeZoneUtils.UTC, - TimeZoneUtils.KST); - LocalDateTime reservationEndTimeKST = TimeZoneUtils.convert( - reservation.getEndTime(), - TimeZoneUtils.UTC, - TimeZoneUtils.KST); + LocalDateTime reservationStartTimeKST = TimeZoneUtils.convert(reservation.getStartTime(), UTC, KST); + LocalDateTime reservationEndTimeKST = TimeZoneUtils.convert(reservation.getEndTime(), UTC, KST); return new SlackResponse( reservation.getSpace().getName(), diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/dto/space/SettingResponse.java b/backend/src/main/java/com/woowacourse/zzimkkong/dto/space/SettingResponse.java index 6f3eb007e..9d646293c 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/dto/space/SettingResponse.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/dto/space/SettingResponse.java @@ -49,9 +49,9 @@ public static SettingResponse from(final Space space) { return new SettingResponse( space.getAvailableStartTime(), space.getAvailableEndTime(), - space.getReservationTimeUnit(), - space.getReservationMinimumTimeUnit(), - space.getReservationMaximumTimeUnit(), + space.getReservationTimeUnitAsInt(), + space.getReservationMinimumTimeUnitAsInt(), + space.getReservationMaximumTimeUnitAsInt(), space.getReservationEnable(), EnabledDayOfWeekDto.from(space.getEnabledDayOfWeek()) ); diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/IllegalTimeUnitValueException.java b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/IllegalTimeUnitValueException.java new file mode 100644 index 000000000..3851cf80b --- /dev/null +++ b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/IllegalTimeUnitValueException.java @@ -0,0 +1,12 @@ +package com.woowacourse.zzimkkong.exception.reservation; + +import com.woowacourse.zzimkkong.exception.ZzimkkongException; +import org.springframework.http.HttpStatus; + +public class IllegalTimeUnitValueException extends ZzimkkongException { + public static final String MESSAGE_FORMAT = "'%d'분은 허용되지 않는 시간 단위 입니다"; + + public IllegalTimeUnitValueException(final int minutes) { + super(String.format(MESSAGE_FORMAT, minutes), HttpStatus.BAD_REQUEST); + } +} diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleEndTimeException.java b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleEndTimeException.java deleted file mode 100644 index c432d0490..000000000 --- a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleEndTimeException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.woowacourse.zzimkkong.exception.reservation; - -import com.woowacourse.zzimkkong.exception.InputFieldException; -import org.springframework.http.HttpStatus; - -public class ImpossibleEndTimeException extends InputFieldException { - private static final String MESSAGE = "종료 시간을 확인해주세요."; - - public ImpossibleEndTimeException() { - super(MESSAGE, HttpStatus.BAD_REQUEST, END_DATE_TIME); - } -} diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleStartEndTimeException.java b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleStartEndTimeException.java new file mode 100644 index 000000000..739e3c0a2 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleStartEndTimeException.java @@ -0,0 +1,12 @@ +package com.woowacourse.zzimkkong.exception.reservation; + +import com.woowacourse.zzimkkong.exception.InputFieldException; +import org.springframework.http.HttpStatus; + +public class ImpossibleStartEndTimeException extends InputFieldException { + private static final String MESSAGE = "예약 종료 시간은 예약 시작 시간보다 이후여야 합니다."; + + public ImpossibleStartEndTimeException() { + super(MESSAGE, HttpStatus.BAD_REQUEST, END_DATE_TIME); + } +} diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/NonMatchingStartAndEndDateException.java b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/NonMatchingStartEndDateException.java similarity index 72% rename from backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/NonMatchingStartAndEndDateException.java rename to backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/NonMatchingStartEndDateException.java index 1e1a3bcaa..cfab66805 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/NonMatchingStartAndEndDateException.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/NonMatchingStartEndDateException.java @@ -3,10 +3,10 @@ import com.woowacourse.zzimkkong.exception.InputFieldException; import org.springframework.http.HttpStatus; -public class NonMatchingStartAndEndDateException extends InputFieldException { +public class NonMatchingStartEndDateException extends InputFieldException { private static final String MESSAGE = "시작 날짜와 종료 날짜는 같아야 합니다."; - public NonMatchingStartAndEndDateException() { + public NonMatchingStartEndDateException() { super(MESSAGE, HttpStatus.BAD_REQUEST, START_DATE_TIME); } } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleStartTimeException.java b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/PastReservationTimeException.java similarity index 52% rename from backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleStartTimeException.java rename to backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/PastReservationTimeException.java index b7ad6efa4..62216ab23 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/ImpossibleStartTimeException.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/exception/reservation/PastReservationTimeException.java @@ -3,10 +3,10 @@ import com.woowacourse.zzimkkong.exception.InputFieldException; import org.springframework.http.HttpStatus; -public class ImpossibleStartTimeException extends InputFieldException { - private static final String MESSAGE = "시작 시간을 확인해주세요."; +public class PastReservationTimeException extends InputFieldException { + private static final String MESSAGE = "예약 시작 시간은 현재 시간보다 이후여야 합니다."; - public ImpossibleStartTimeException() { + public PastReservationTimeException() { super(MESSAGE, HttpStatus.BAD_REQUEST, START_DATE_TIME); } } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/exception/space/ImpossibleAvailableStartEndTimeException.java b/backend/src/main/java/com/woowacourse/zzimkkong/exception/space/ImpossibleAvailableStartEndTimeException.java deleted file mode 100644 index 7374e43c7..000000000 --- a/backend/src/main/java/com/woowacourse/zzimkkong/exception/space/ImpossibleAvailableStartEndTimeException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.woowacourse.zzimkkong.exception.space; - -import com.woowacourse.zzimkkong.exception.InputFieldException; -import org.springframework.http.HttpStatus; - -public class ImpossibleAvailableStartEndTimeException extends InputFieldException { - private static final String MESSAGE = "예약이 닫힐 시간은 예약이 열릴 시간보다 이전일 수 없습니다."; - - public ImpossibleAvailableStartEndTimeException() { - super(MESSAGE, HttpStatus.BAD_REQUEST, AVAILABLE_START_END_TIME); - } -} diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepository.java b/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepository.java index ff5da4363..7c56249b9 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepository.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepository.java @@ -6,6 +6,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.time.LocalDate; import java.time.LocalDateTime; @@ -14,12 +15,20 @@ @FindInstanceAndCreateLogProxy(group = "repository") public interface ReservationRepository extends JpaRepository, ReservationRepositoryCustom { - List findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + @Query(value = "SELECT r FROM Reservation r " + + "WHERE r.space.id IN :spaceIds AND " + + "r.reservationTime.date >= :lowerBoundDate AND " + + "r.reservationTime.date <= :upperBoundDate") + List findAllBySpaceIdInAndDateBetween( + @Param("spaceIds") final Collection spaceIds, + @Param("lowerBoundDate") final LocalDate lowerBoundDate, + @Param("upperBoundDate") final LocalDate upperBoundDate); + + List findAllBySpaceIdInAndReservationTimeDate( final Collection spaceIds, - final LocalDate lowerBoundDate, - final LocalDate upperBoundDate); + final LocalDate date); - Boolean existsBySpaceIdAndEndTimeAfter(Long spaceId, LocalDateTime now); + Boolean existsBySpaceIdAndReservationTimeEndTimeAfter(final Long spaceId, final LocalDateTime now); @Query(value = "select r from Reservation r inner join fetch r.space s " + "inner join fetch s.map m " + diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryCustom.java b/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryCustom.java index 41f8f7c49..80f33f7cf 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryCustom.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryCustom.java @@ -2,6 +2,8 @@ import com.woowacourse.zzimkkong.domain.Member; +import java.time.LocalDateTime; + public interface ReservationRepositoryCustom { - boolean existsReservationsByMemberFromToday(Member member); + boolean existsByMemberAndEndTimeAfter(final Member member, final LocalDateTime now); } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImpl.java b/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImpl.java index c28c67ffc..29a9fbd5b 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImpl.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImpl.java @@ -1,6 +1,8 @@ package com.woowacourse.zzimkkong.repository; import com.woowacourse.zzimkkong.domain.Member; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import javax.persistence.EntityManager; import java.time.LocalDateTime; @@ -13,13 +15,13 @@ public ReservationRepositoryImpl(final EntityManager entityManager) { } @Override - public boolean existsReservationsByMemberFromToday(Member member) { + public boolean existsByMemberAndEndTimeAfter(final Member member, final LocalDateTime now) { return entityManager.createQuery( "SELECT COUNT(r) > 0 FROM Reservation r " + "JOIN r.space s JOIN s.map m " + - "WHERE m.member = :member AND r.endTime >= :currentTime", Boolean.class) + "WHERE m.member = :member AND r.reservationTime.endTime >= :currentTime", Boolean.class) .setParameter("member", member) - .setParameter("currentTime", LocalDateTime.now()) + .setParameter("currentTime", now) .getSingleResult(); } } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java b/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java index ec8acb361..d1b219ac4 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/service/MapService.java @@ -135,7 +135,7 @@ private void validateExistReservations(final Map map) { List findSpaces = map.getSpaces(); boolean isExistReservationInAnySpace = findSpaces.stream() - .anyMatch(space -> reservations.existsBySpaceIdAndEndTimeAfter(space.getId(), LocalDateTime.now())); + .anyMatch(space -> reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(space.getId(), LocalDateTime.now())); if (isExistReservationInAnySpace) { throw new ReservationExistOnSpaceException(); diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/service/MemberService.java b/backend/src/main/java/com/woowacourse/zzimkkong/service/MemberService.java index 19cd0886e..f9759e433 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/service/MemberService.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/service/MemberService.java @@ -13,6 +13,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; + @Service @Transactional public class MemberService { @@ -79,7 +81,7 @@ public void updateMember(final LoginEmailDto loginEmailDto, final MemberUpdateRe public void deleteMember(final LoginEmailDto loginEmailDto) { Member member = members.findByEmail(loginEmailDto.getEmail()) .orElseThrow(NoSuchMemberException::new); - boolean hasAnyReservations = reservations.existsReservationsByMemberFromToday(member); + boolean hasAnyReservations = reservations.existsByMemberAndEndTimeAfter(member, LocalDateTime.now()); if (hasAnyReservations) { throw new ReservationExistsOnMemberException(); } diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/service/PresetService.java b/backend/src/main/java/com/woowacourse/zzimkkong/service/PresetService.java index a5809a4b2..e9985a5ba 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/service/PresetService.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/service/PresetService.java @@ -1,8 +1,6 @@ package com.woowacourse.zzimkkong.service; -import com.woowacourse.zzimkkong.domain.Member; -import com.woowacourse.zzimkkong.domain.Preset; -import com.woowacourse.zzimkkong.domain.Setting; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.dto.member.PresetCreateResponse; import com.woowacourse.zzimkkong.dto.member.PresetFindAllResponse; import com.woowacourse.zzimkkong.dto.space.SettingsRequest; @@ -33,11 +31,13 @@ public PresetService( public PresetCreateResponse savePreset(final PresetCreateRequest presetCreateRequest, final LoginEmailDto loginEmailDto) { SettingsRequest settingsRequest = presetCreateRequest.getSettingsRequest(); Setting setting = Setting.builder() - .availableStartTime(settingsRequest.getAvailableStartTime()) - .availableEndTime(settingsRequest.getAvailableEndTime()) - .reservationTimeUnit(settingsRequest.getReservationTimeUnit()) - .reservationMinimumTimeUnit(settingsRequest.getReservationMinimumTimeUnit()) - .reservationMaximumTimeUnit(settingsRequest.getReservationMaximumTimeUnit()) + .availableTimeSlot( + TimeSlot.of( + settingsRequest.getAvailableStartTime(), + settingsRequest.getAvailableEndTime())) + .reservationTimeUnit(TimeUnit.from(settingsRequest.getReservationTimeUnit())) + .reservationMinimumTimeUnit(TimeUnit.from(settingsRequest.getReservationMinimumTimeUnit())) + .reservationMaximumTimeUnit(TimeUnit.from(settingsRequest.getReservationMaximumTimeUnit())) .reservationEnable(settingsRequest.getReservationEnable()) .enabledDayOfWeek(settingsRequest.enabledDayOfWeekAsString()) .build(); diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/service/ReservationService.java b/backend/src/main/java/com/woowacourse/zzimkkong/service/ReservationService.java index f9d62f9b8..6221e2b35 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/service/ReservationService.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/service/ReservationService.java @@ -1,14 +1,11 @@ package com.woowacourse.zzimkkong.service; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Reservation; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.dto.reservation.*; import com.woowacourse.zzimkkong.dto.slack.SlackResponse; import com.woowacourse.zzimkkong.exception.map.NoSuchMapException; import com.woowacourse.zzimkkong.exception.reservation.*; import com.woowacourse.zzimkkong.exception.space.NoSuchSpaceException; -import com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils; import com.woowacourse.zzimkkong.infrastructure.sharingid.SharingIdGenerator; import com.woowacourse.zzimkkong.repository.MapRepository; import com.woowacourse.zzimkkong.repository.ReservationRepository; @@ -19,17 +16,13 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.DayOfWeek; import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.TimeZone; import java.util.stream.Collectors; -import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.*; - @Service @Transactional public class ReservationService { @@ -60,16 +53,16 @@ public ReservationCreateResponse saveReservation( Space space = map.findSpaceById(spaceId) .orElseThrow(NoSuchSpaceException::new); - validateTime(reservationCreateDto, reservationStrategy.isManager()); + ReservationTime reservationTime = ReservationTime.of( + reservationCreateDto.getStartDateTime(), + reservationCreateDto.getEndDateTime(), + reservationStrategy.isManager()); - validateAvailability(space, reservationCreateDto, new ExcludeReservationCreateStrategy()); + validateAvailability(space, reservationTime, new ExcludeReservationCreateStrategy()); - LocalDate date = TimeZoneUtils.convert(reservationCreateDto.getStartDateTime(), UTC, KST).toLocalDate(); Reservation reservation = reservations.save( Reservation.builder() - .startTime(reservationCreateDto.getStartDateTime()) - .endTime(reservationCreateDto.getEndDateTime()) - .date(date) + .reservationTime(reservationTime) .password(reservationCreateDto.getPassword()) .userName(reservationCreateDto.getName()) .description(reservationCreateDto.getDescription()) @@ -155,7 +148,10 @@ public SlackResponse updateReservation( Space space = map.findSpaceById(spaceId) .orElseThrow(NoSuchSpaceException::new); - validateTime(reservationUpdateDto, reservationStrategy.isManager()); + ReservationTime reservationTime = ReservationTime.of( + reservationUpdateDto.getStartDateTime(), + reservationUpdateDto.getEndDateTime(), + reservationStrategy.isManager()); Long reservationId = reservationUpdateDto.getReservationId(); String password = reservationUpdateDto.getPassword(); @@ -164,13 +160,10 @@ public SlackResponse updateReservation( .orElseThrow(NoSuchReservationException::new); reservationStrategy.checkCorrectPassword(reservation, password); - validateAvailability(space, reservationUpdateDto, new ExcludeReservationUpdateStrategy(reservation)); + validateAvailability(space, reservationTime, new ExcludeReservationUpdateStrategy(reservation)); - LocalDate date = TimeZoneUtils.convert(reservationUpdateDto.getStartDateTime(), UTC, KST).toLocalDate(); Reservation updateReservation = Reservation.builder() - .startTime(reservationUpdateDto.getStartDateTime()) - .endTime(reservationUpdateDto.getEndDateTime()) - .date(date) + .reservationTime(reservationTime) .userName(reservationUpdateDto.getName()) .description(reservationUpdateDto.getDescription()) .space(space) @@ -201,7 +194,10 @@ public SlackResponse deleteReservation( .findById(reservationId) .orElseThrow(NoSuchReservationException::new); reservationStrategy.checkCorrectPassword(reservation, password); - validatePastTimeAndManager(reservation.getStartTime(), reservationStrategy.isManager()); + + if (!reservationStrategy.isManager()) { + ReservationTime.validatePastTime(reservation.getStartTime()); + } reservations.delete(reservation); @@ -209,67 +205,37 @@ public SlackResponse deleteReservation( return SlackResponse.of(reservation, sharingMapId, map.getSlackUrl()); } - private void validateTime(final ReservationCreateDto reservationCreateDto, final boolean managerFlag) { - LocalDateTime startDateTime = reservationCreateDto.getStartDateTime().withSecond(0).withNano(0); - LocalDateTime endDateTime = reservationCreateDto.getEndDateTime().withSecond(0).withNano(0); - - validatePastTimeAndManager(startDateTime, managerFlag); - - if (endDateTime.isBefore(startDateTime) || startDateTime.equals(endDateTime)) { - throw new ImpossibleEndTimeException(); - } - - LocalDate startDateKST = TimeZoneUtils.convert(startDateTime, UTC, KST).toLocalDate(); - LocalDate endDateKST = TimeZoneUtils.convert(endDateTime, UTC, KST).toLocalDate(); - if (!startDateKST.isEqual(endDateKST)) { - throw new NonMatchingStartAndEndDateException(); - } - } - - private void validatePastTimeAndManager(final LocalDateTime startDateTime, final boolean managerFlag) { - if (startDateTime.isBefore(LocalDateTime.now()) && !managerFlag) { - throw new ImpossibleStartTimeException(); - } - } - private void validateAvailability( final Space space, - final ReservationCreateDto reservationCreateDto, + final ReservationTime reservationTime, final ExcludeReservationStrategy excludeReservationStrategy) { - LocalDateTime startDateTime = reservationCreateDto.getStartDateTime(); - LocalDateTime endDateTime = reservationCreateDto.getEndDateTime(); - - validateSpaceSetting(space, startDateTime, endDateTime); + validateSpaceSetting(space, reservationTime); List reservationsOnDate = getReservations( Collections.singletonList(space), - startDateTime.toLocalDate()); + reservationTime.getDate()); excludeReservationStrategy.apply(space, reservationsOnDate); - validateTimeConflicts(startDateTime, endDateTime, reservationsOnDate); + validateTimeConflicts(reservationTime, reservationsOnDate); } - private void validateSpaceSetting( - final Space space, - final LocalDateTime startDateTime, - final LocalDateTime endDateTime) { - LocalDateTime startDateTimeKST = TimeZoneUtils.convert(startDateTime, UTC, KST); - LocalDateTime endDateTimeKST = TimeZoneUtils.convert(endDateTime, UTC, KST); - int durationMinutes = (int) ChronoUnit.MINUTES.between(startDateTimeKST, endDateTimeKST); + private void validateSpaceSetting(final Space space, final ReservationTime reservationTime) { + TimeSlot timeSlot = reservationTime.asTimeSlotKST(); + DayOfWeek dayOfWeek = reservationTime.getDayOfWeekKST(); - if (space.isNotDivisibleByTimeUnit(startDateTimeKST.getMinute()) || space.isNotDivisibleByTimeUnit(durationMinutes)) { + if (space.cannotAcceptDueToTimeUnit(timeSlot)) { throw new InvalidTimeUnitException(); } - if (space.isIncorrectMinimumTimeUnit(durationMinutes)) { + if (space.cannotAcceptDueToMinimumTimeUnit(timeSlot)) { throw new InvalidMinimumDurationTimeException(); } - if (space.isIncorrectMaximumTimeUnit(durationMinutes)) { + if (space.cannotAcceptDueToMaximumTimeUnit(timeSlot)) { throw new InvalidMaximumDurationTimeException(); } - if (space.isNotBetweenAvailableTime(startDateTimeKST, endDateTimeKST)) { + if (space.cannotAcceptDueToAvailableTime(timeSlot)) { throw new InvalidStartEndTimeException(); } @@ -277,17 +243,16 @@ private void validateSpaceSetting( throw new InvalidReservationEnableException(); } - if (space.isClosedOn(startDateTimeKST.getDayOfWeek())) { + if (space.isClosedOn(dayOfWeek)) { throw new InvalidDayOfWeekException(); } } private void validateTimeConflicts( - final LocalDateTime startDateTime, - final LocalDateTime endDateTime, + final ReservationTime reservationTime, final List reservationsOnDate) { for (Reservation existingReservation : reservationsOnDate) { - if (existingReservation.hasConflictWith(startDateTime, endDateTime)) { + if (existingReservation.hasConflictWith(reservationTime)) { throw new ReservationAlreadyExistsException(); } } @@ -298,14 +263,7 @@ private List getReservations(final Collection findSpaces, fi .map(Space::getId) .collect(Collectors.toList()); - List reservationsWithinDateRange = reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( - spaceIds, - date.minusDays(ONE_DAY_OFFSET), - date.plusDays(ONE_DAY_OFFSET)); - - return reservationsWithinDateRange.stream() - .filter(reservation -> reservation.isBookedOn(date, KST)) - .collect(Collectors.toList()); + return reservations.findAllBySpaceIdInAndReservationTimeDate(spaceIds, date); } private void validateSpaceExistence(final Map map, final Long spaceId) { diff --git a/backend/src/main/java/com/woowacourse/zzimkkong/service/SpaceService.java b/backend/src/main/java/com/woowacourse/zzimkkong/service/SpaceService.java index 7f40b9ebf..285026d70 100644 --- a/backend/src/main/java/com/woowacourse/zzimkkong/service/SpaceService.java +++ b/backend/src/main/java/com/woowacourse/zzimkkong/service/SpaceService.java @@ -1,8 +1,6 @@ package com.woowacourse.zzimkkong.service; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Setting; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.dto.member.LoginEmailDto; import com.woowacourse.zzimkkong.dto.space.*; import com.woowacourse.zzimkkong.exception.authorization.NoAuthorityOnMapException; @@ -143,18 +141,20 @@ private Setting getSetting(final SpaceCreateUpdateRequest spaceCreateUpdateReque SettingsRequest settingsRequest = spaceCreateUpdateRequest.getSettingsRequest(); return Setting.builder() - .availableStartTime(settingsRequest.getAvailableStartTime()) - .availableEndTime(settingsRequest.getAvailableEndTime()) - .reservationTimeUnit(settingsRequest.getReservationTimeUnit()) + .availableTimeSlot( + TimeSlot.of( + settingsRequest.getAvailableStartTime(), + settingsRequest.getAvailableEndTime())) + .reservationTimeUnit(TimeUnit.from(settingsRequest.getReservationTimeUnit())) + .reservationMinimumTimeUnit(TimeUnit.from(settingsRequest.getReservationMinimumTimeUnit())) + .reservationMaximumTimeUnit(TimeUnit.from(settingsRequest.getReservationMaximumTimeUnit())) .reservationEnable(settingsRequest.getReservationEnable()) - .reservationMinimumTimeUnit(settingsRequest.getReservationMinimumTimeUnit()) - .reservationMaximumTimeUnit(settingsRequest.getReservationMaximumTimeUnit()) .enabledDayOfWeek(settingsRequest.enabledDayOfWeekAsString()) .build(); } private void validateReservationExistence(final Long spaceId) { - if (reservations.existsBySpaceIdAndEndTimeAfter(spaceId, LocalDateTime.now())) { + if (reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(spaceId, LocalDateTime.now())) { throw new ReservationExistOnSpaceException(); } } diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/Constants.java b/backend/src/test/java/com/woowacourse/zzimkkong/Constants.java index 11c58d29b..1bee48b42 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/Constants.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/Constants.java @@ -1,5 +1,7 @@ package com.woowacourse.zzimkkong; +import com.woowacourse.zzimkkong.domain.TimeUnit; + import java.time.LocalDate; import java.time.LocalTime; import java.time.ZonedDateTime; @@ -32,17 +34,17 @@ private Constants() { public static final LocalTime BE_AVAILABLE_START_TIME = LocalTime.of(10, 0); public static final LocalTime BE_AVAILABLE_END_TIME = LocalTime.of(22, 0); - public static final Integer BE_RESERVATION_TIME_UNIT = 10; - public static final Integer BE_RESERVATION_MINIMUM_TIME_UNIT = 60; - public static final Integer BE_RESERVATION_MAXIMUM_TIME_UNIT = 120; + public static final TimeUnit BE_RESERVATION_TIME_UNIT = TimeUnit.from(10); + public static final TimeUnit BE_RESERVATION_MINIMUM_TIME_UNIT = TimeUnit.from(60); + public static final TimeUnit BE_RESERVATION_MAXIMUM_TIME_UNIT = TimeUnit.from(120); public static final Boolean BE_RESERVATION_ENABLE = true; public static final String BE_ENABLED_DAY_OF_WEEK = "monday,tuesday,wednesday,thursday,friday,saturday,sunday"; public static final LocalTime FE_AVAILABLE_START_TIME = LocalTime.of(10, 0); public static final LocalTime FE_AVAILABLE_END_TIME = LocalTime.of(22, 0); - public static final Integer FE_RESERVATION_TIME_UNIT = 10; - public static final Integer FE_RESERVATION_MINIMUM_TIME_UNIT = 60; - public static final Integer FE_RESERVATION_MAXIMUM_TIME_UNIT = 120; + public static final TimeUnit FE_RESERVATION_TIME_UNIT = TimeUnit.from(10); + public static final TimeUnit FE_RESERVATION_MINIMUM_TIME_UNIT = TimeUnit.from(60); + public static final TimeUnit FE_RESERVATION_MAXIMUM_TIME_UNIT = TimeUnit.from(120); public static final Boolean FE_RESERVATION_ENABLE = true; public static final String FE_ENABLED_DAY_OF_WEEK = "monday,tuesday,wednesday,thursday,friday,saturday,sunday"; diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/AcceptanceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/AcceptanceTest.java index 4c98cb85d..76645ea44 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/AcceptanceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/AcceptanceTest.java @@ -1,7 +1,6 @@ package com.woowacourse.zzimkkong.controller; import com.woowacourse.zzimkkong.DatabaseCleaner; -import com.woowacourse.zzimkkong.domain.Reservation; import com.woowacourse.zzimkkong.dto.map.MapCreateUpdateRequest; import com.woowacourse.zzimkkong.dto.member.LoginRequest; import com.woowacourse.zzimkkong.dto.member.MemberSaveRequest; @@ -27,15 +26,10 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Collectors; - import static com.woowacourse.zzimkkong.Constants.*; import static com.woowacourse.zzimkkong.DocumentUtils.setRequestSpecification; import static com.woowacourse.zzimkkong.controller.AuthControllerTest.getToken; import static com.woowacourse.zzimkkong.controller.MemberControllerTest.saveMember; -import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.KST; import static org.mockito.ArgumentMatchers.any; import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; @@ -51,9 +45,9 @@ class AcceptanceTest { protected final SettingsRequest beSettingsRequest = new SettingsRequest( BE_AVAILABLE_START_TIME, BE_AVAILABLE_END_TIME, - BE_RESERVATION_TIME_UNIT, - BE_RESERVATION_MINIMUM_TIME_UNIT, - BE_RESERVATION_MAXIMUM_TIME_UNIT, + BE_RESERVATION_TIME_UNIT.getMinutes(), + BE_RESERVATION_MINIMUM_TIME_UNIT.getMinutes(), + BE_RESERVATION_MAXIMUM_TIME_UNIT.getMinutes(), BE_RESERVATION_ENABLE, EnabledDayOfWeekDto.from(BE_ENABLED_DAY_OF_WEEK) ); @@ -68,9 +62,9 @@ class AcceptanceTest { protected final SettingsRequest feSettingsRequest = new SettingsRequest( FE_AVAILABLE_START_TIME, FE_AVAILABLE_END_TIME, - FE_RESERVATION_TIME_UNIT, - FE_RESERVATION_MINIMUM_TIME_UNIT, - FE_RESERVATION_MAXIMUM_TIME_UNIT, + FE_RESERVATION_TIME_UNIT.getMinutes(), + FE_RESERVATION_MINIMUM_TIME_UNIT.getMinutes(), + FE_RESERVATION_MAXIMUM_TIME_UNIT.getMinutes(), FE_RESERVATION_ENABLE, EnabledDayOfWeekDto.from(FE_ENABLED_DAY_OF_WEEK) ); @@ -114,10 +108,4 @@ void setUp(RestDocumentationContextProvider restDocumentation) { void deleteAll() { databaseCleaner.execute(); } - - protected List filterReservationsByKST(List reservations, LocalDate date) { - return reservations.stream() - .filter(reservation -> reservation.isBookedOn(date, KST)) - .collect(Collectors.toList()); - } } diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/AdminControllerTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/AdminControllerTest.java index 512d68893..8f99bd9c6 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/AdminControllerTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/AdminControllerTest.java @@ -33,6 +33,7 @@ import static com.woowacourse.zzimkkong.controller.ManagerSpaceControllerTest.saveSpace; import static com.woowacourse.zzimkkong.controller.MapControllerTest.saveMap; import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.KST; +import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.UTC; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -43,8 +44,9 @@ class AdminControllerTest extends AcceptanceTest { private static final Member POBI = new Member(memberSaveRequest.getEmail(), memberSaveRequest.getPassword(), memberSaveRequest.getOrganization()); private static final Map LUTHER = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, POBI); private static final Setting BE_SETTING = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -160,8 +162,10 @@ void getReservations() { SALLY_DESCRIPTION); saveReservation(beReservationApi, newReservationCreateUpdateWithPasswordRequest); Reservation reservation = Reservation.builder() - .startTime(newReservationCreateUpdateWithPasswordRequest.localStartDateTime()) - .endTime(newReservationCreateUpdateWithPasswordRequest.localEndDateTime()) + .reservationTime( + ReservationTime.of( + newReservationCreateUpdateWithPasswordRequest.localStartDateTime(), + newReservationCreateUpdateWithPasswordRequest.localEndDateTime())) .userName(newReservationCreateUpdateWithPasswordRequest.getName()) .password(newReservationCreateUpdateWithPasswordRequest.getPassword()) .description(newReservationCreateUpdateWithPasswordRequest.getDescription()) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestReservationControllerTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestReservationControllerTest.java index a118cd3a2..146b786c0 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestReservationControllerTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestReservationControllerTest.java @@ -68,8 +68,9 @@ void setUp() { Map luther = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -87,8 +88,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -109,8 +111,10 @@ void setUp() { saveExampleReservations(); savedReservationId = getReservationIdAfterSave(beReservationApi, reservationCreateUpdateWithPasswordRequest); savedReservation = Reservation.builder() - .startTime(reservationCreateUpdateWithPasswordRequest.localStartDateTime()) - .endTime(reservationCreateUpdateWithPasswordRequest.localEndDateTime()) + .reservationTime( + ReservationTime.of( + reservationCreateUpdateWithPasswordRequest.localStartDateTime(), + reservationCreateUpdateWithPasswordRequest.localEndDateTime())) .password(reservationCreateUpdateWithPasswordRequest.getPassword()) .userName(reservationCreateUpdateWithPasswordRequest.getName()) .description(reservationCreateUpdateWithPasswordRequest.getDescription()) @@ -144,11 +148,11 @@ void find() { ReservationFindResponse actualResponse = response.as(ReservationFindResponse.class); - List expectedFindReservations = filterReservationsByKST( - Arrays.asList(savedReservation, - beAmZeroOne, - bePmOneTwo), - THE_DAY_AFTER_TOMORROW); + List expectedFindReservations = Arrays.asList( + savedReservation, + beAmZeroOne, + bePmOneTwo); + ReservationFindResponse expectedResponse = ReservationFindResponse.from(expectedFindReservations); //then @@ -168,13 +172,11 @@ void findAll() { ReservationFindAllResponse actualResponse = response.as(ReservationFindAllResponse.class); - List expectedFindReservations = filterReservationsByKST( - Arrays.asList( - savedReservation, - beAmZeroOne, - bePmOneTwo, - fe1ZeroOne), - THE_DAY_AFTER_TOMORROW); + List expectedFindReservations = Arrays.asList( + savedReservation, + beAmZeroOne, + bePmOneTwo, + fe1ZeroOne); ReservationFindAllResponse expectedResponse = ReservationFindAllResponse.of( Arrays.asList(be, fe), expectedFindReservations); @@ -209,8 +211,10 @@ void update_sameSpace() { ReservationResponse expectedResponse = ReservationResponse.from( Reservation.builder() .id(savedReservationId) - .startTime(reservationCreateUpdateWithPasswordRequestSameSpace.localStartDateTime()) - .endTime(reservationCreateUpdateWithPasswordRequestSameSpace.localEndDateTime()) + .reservationTime( + ReservationTime.of( + reservationCreateUpdateWithPasswordRequestSameSpace.localStartDateTime(), + reservationCreateUpdateWithPasswordRequestSameSpace.localEndDateTime())) .description(reservationCreateUpdateWithPasswordRequestSameSpace.getDescription()) .userName(reservationCreateUpdateWithPasswordRequestSameSpace.getName()) .space(be) @@ -243,18 +247,19 @@ void update_spaceUpdate() { ReservationFindResponse actualResponse = findResponse.as(ReservationFindResponse.class); - List expectedFindReservations = filterReservationsByKST( - Arrays.asList( - Reservation.builder() - .startTime(reservationCreateUpdateWithPasswordRequestDifferentSpace.localStartDateTime()) - .endTime(reservationCreateUpdateWithPasswordRequestDifferentSpace.localEndDateTime()) - .description(reservationCreateUpdateWithPasswordRequestDifferentSpace.getDescription()) - .userName(reservationCreateUpdateWithPasswordRequestDifferentSpace.getName()) - .password(reservationCreateUpdateWithPasswordRequestDifferentSpace.getPassword()) - .space(fe) - .build(), - fe1ZeroOne), - THE_DAY_AFTER_TOMORROW); + List expectedFindReservations = Arrays.asList( + Reservation.builder() + .reservationTime( + ReservationTime.of( + reservationCreateUpdateWithPasswordRequestDifferentSpace.localStartDateTime(), + reservationCreateUpdateWithPasswordRequestDifferentSpace.localEndDateTime())) + .description(reservationCreateUpdateWithPasswordRequestDifferentSpace.getDescription()) + .userName(reservationCreateUpdateWithPasswordRequestDifferentSpace.getName()) + .password(reservationCreateUpdateWithPasswordRequestDifferentSpace.getPassword()) + .space(fe) + .build(), + fe1ZeroOne); + ReservationFindResponse expectedResponse = ReservationFindResponse.from(expectedFindReservations); //then @@ -326,8 +331,10 @@ private void saveExampleReservations() { beAmZeroOne = Reservation.builder() .id(getReservationIdAfterSave(beReservationApi, beAmZeroOneRequest)) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -336,8 +343,10 @@ private void saveExampleReservations() { bePmOneTwo = Reservation.builder() .id(getReservationIdAfterSave(beReservationApi, bePmOneTwoRequest)) - .startTime(BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_PM_ONE_TWO_DESCRIPTION) .userName(BE_PM_ONE_TWO_USERNAME) .password(BE_PM_ONE_TWO_PW) @@ -348,8 +357,10 @@ private void saveExampleReservations() { fe1ZeroOne = Reservation.builder() .id(getReservationIdAfterSave(fe1ReservationApi, feZeroOneRequest)) - .startTime(FE1_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(FE1_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + FE1_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + FE1_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(FE1_AM_TEN_ELEVEN_DESCRIPTION) .userName(FE1_AM_TEN_ELEVEN_USERNAME) .password(FE1_AM_TEN_ELEVEN_PW) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestSpaceControllerTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestSpaceControllerTest.java index 76404468f..c83913b12 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestSpaceControllerTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/GuestSpaceControllerTest.java @@ -1,10 +1,7 @@ package com.woowacourse.zzimkkong.controller; import com.woowacourse.zzimkkong.Constants; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Member; -import com.woowacourse.zzimkkong.domain.Setting; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.dto.space.SpaceFindAllResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; @@ -42,8 +39,9 @@ void setUp() { Member pobi = new Member(EMAIL, passwordEncoder.encode(PW), ORGANIZATION); Map luther = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -52,8 +50,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerReservationControllerTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerReservationControllerTest.java index 832329a15..fb541a543 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerReservationControllerTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerReservationControllerTest.java @@ -66,8 +66,9 @@ void setUp() { Map luther = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -85,8 +86,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -107,8 +109,10 @@ void setUp() { saveExampleReservations(); savedReservationId = getReservationIdAfterSave(beReservationApi, reservationCreateUpdateWithPasswordRequest); savedReservation = Reservation.builder() - .startTime(reservationCreateUpdateWithPasswordRequest.localStartDateTime()) - .endTime(reservationCreateUpdateWithPasswordRequest.localEndDateTime()) + .reservationTime( + ReservationTime.of( + reservationCreateUpdateWithPasswordRequest.localStartDateTime(), + reservationCreateUpdateWithPasswordRequest.localEndDateTime())) .password(reservationCreateUpdateWithPasswordRequest.getPassword()) .userName(reservationCreateUpdateWithPasswordRequest.getName()) .description(reservationCreateUpdateWithPasswordRequest.getDescription()) @@ -141,9 +145,11 @@ void find() { ExtractableResponse response = findReservations(beReservationApi, THE_DAY_AFTER_TOMORROW.toString()); ReservationFindResponse actualResponse = response.as(ReservationFindResponse.class); - List expectedFindReservations = filterReservationsByKST( - Arrays.asList(savedReservation, beAmZeroOne, bePmOneTwo), - THE_DAY_AFTER_TOMORROW); + List expectedFindReservations = Arrays.asList( + savedReservation, + beAmZeroOne, + bePmOneTwo); + ReservationFindResponse expectedResponse = ReservationFindResponse.from(expectedFindReservations); //then @@ -163,9 +169,11 @@ void findAll() { ReservationFindAllResponse actualResponse = response.as(ReservationFindAllResponse.class); - List expectedFindReservations = filterReservationsByKST( - Arrays.asList(savedReservation, beAmZeroOne, bePmOneTwo, fe1ZeroOne), - THE_DAY_AFTER_TOMORROW); + List expectedFindReservations = Arrays.asList( + savedReservation, + beAmZeroOne, + bePmOneTwo, + fe1ZeroOne); ReservationFindAllResponse expectedResponse = ReservationFindAllResponse.of( Arrays.asList(be, fe), expectedFindReservations); @@ -215,8 +223,10 @@ void update_sameSpace() { ReservationResponse expectedResponse = ReservationResponse.from( Reservation.builder() .id(savedReservationId) - .startTime(reservationCreateUpdateRequestSameSpace.localStartDateTime()) - .endTime(reservationCreateUpdateRequestSameSpace.localEndDateTime()) + .reservationTime( + ReservationTime.of( + reservationCreateUpdateRequestSameSpace.localStartDateTime(), + reservationCreateUpdateRequestSameSpace.localEndDateTime())) .description(reservationCreateUpdateRequestSameSpace.getDescription()) .userName(reservationCreateUpdateRequestSameSpace.getName()) .space(be) @@ -252,18 +262,18 @@ void update_spaceUpdate() { ReservationFindResponse actualResponse = findResponse.as(ReservationFindResponse.class); - List expectedFindReservations = filterReservationsByKST( - Arrays.asList( - Reservation.builder() - .startTime(reservationCreateUpdateWithPasswordRequestDifferentSpace.localStartDateTime()) - .endTime(reservationCreateUpdateWithPasswordRequestDifferentSpace.localEndDateTime()) - .description(reservationCreateUpdateWithPasswordRequestDifferentSpace.getDescription()) - .userName(reservationCreateUpdateWithPasswordRequestDifferentSpace.getName()) - .password(reservationCreateUpdateWithPasswordRequestDifferentSpace.getPassword()) - .space(fe) - .build(), - fe1ZeroOne), - THE_DAY_AFTER_TOMORROW); + List expectedFindReservations = Arrays.asList( + Reservation.builder() + .reservationTime( + ReservationTime.of( + reservationCreateUpdateWithPasswordRequestDifferentSpace.localStartDateTime(), + reservationCreateUpdateWithPasswordRequestDifferentSpace.localEndDateTime())) + .description(reservationCreateUpdateWithPasswordRequestDifferentSpace.getDescription()) + .userName(reservationCreateUpdateWithPasswordRequestDifferentSpace.getName()) + .password(reservationCreateUpdateWithPasswordRequestDifferentSpace.getPassword()) + .space(fe) + .build(), + fe1ZeroOne); ReservationFindResponse expectedResponse = ReservationFindResponse.from(expectedFindReservations); //then @@ -318,8 +328,10 @@ private void saveExampleReservations() { beAmZeroOne = Reservation.builder() .id(getReservationIdAfterSave(beReservationApi, beAmZeroOneRequest)) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -328,8 +340,10 @@ private void saveExampleReservations() { bePmOneTwo = Reservation.builder() .id(getReservationIdAfterSave(beReservationApi, bePmOneTwoRequest)) - .startTime(BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_PM_ONE_TWO_DESCRIPTION) .userName(BE_PM_ONE_TWO_USERNAME) .password(BE_PM_ONE_TWO_PW) @@ -340,8 +354,10 @@ private void saveExampleReservations() { fe1ZeroOne = Reservation.builder() .id(getReservationIdAfterSave(fe1ReservationApi, feZeroOneRequest)) - .startTime(FE1_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(FE1_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + FE1_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + FE1_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(FE1_AM_TEN_ELEVEN_DESCRIPTION) .userName(FE1_AM_TEN_ELEVEN_USERNAME) .password(FE1_AM_TEN_ELEVEN_PW) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerSpaceControllerTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerSpaceControllerTest.java index 5464241b3..918ea0223 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerSpaceControllerTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/ManagerSpaceControllerTest.java @@ -1,9 +1,6 @@ package com.woowacourse.zzimkkong.controller; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Member; -import com.woowacourse.zzimkkong.domain.Setting; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.dto.space.*; import com.woowacourse.zzimkkong.infrastructure.auth.AuthorizationExtractor; import io.restassured.RestAssured; @@ -43,8 +40,9 @@ void setUp() { Member pobi = new Member(EMAIL, passwordEncoder.encode(PW), ORGANIZATION); Map luther = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -53,8 +51,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -137,11 +136,12 @@ void save_default() { ); Setting defaultSetting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(true) .enabledDayOfWeek("monday, tuesday, wednesday, thursday, friday, saturday, sunday") .build(); diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/controller/MemberControllerTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/controller/MemberControllerTest.java index 42bcf0ba5..8f98b135a 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/controller/MemberControllerTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/controller/MemberControllerTest.java @@ -3,6 +3,7 @@ import com.woowacourse.zzimkkong.domain.Member; import com.woowacourse.zzimkkong.domain.Preset; import com.woowacourse.zzimkkong.domain.Setting; +import com.woowacourse.zzimkkong.domain.TimeSlot; import com.woowacourse.zzimkkong.dto.ErrorResponse; import com.woowacourse.zzimkkong.dto.InputFieldErrorResponse; import com.woowacourse.zzimkkong.dto.member.*; @@ -39,8 +40,9 @@ class MemberControllerTest extends AcceptanceTest { void setUp() { pobi = new Member(EMAIL, passwordEncoder.encode(PW), ORGANIZATION); setting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -51,9 +53,9 @@ void setUp() { settingsRequest = new SettingsRequest( BE_AVAILABLE_START_TIME, BE_AVAILABLE_END_TIME, - BE_RESERVATION_TIME_UNIT, - BE_RESERVATION_MINIMUM_TIME_UNIT, - BE_RESERVATION_MAXIMUM_TIME_UNIT, + BE_RESERVATION_TIME_UNIT.getMinutes(), + BE_RESERVATION_MINIMUM_TIME_UNIT.getMinutes(), + BE_RESERVATION_MAXIMUM_TIME_UNIT.getMinutes(), BE_RESERVATION_ENABLE, EnabledDayOfWeekDto.from(BE_ENABLED_DAY_OF_WEEK) ); diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/MemberTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/MemberTest.java index eef52bd62..f73ab3d68 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/domain/MemberTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/MemberTest.java @@ -17,8 +17,9 @@ void findPresetById() { //given, when Member member = new Member(1L, EMAIL, PW, ORGANIZATION); Setting setting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/PresetTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/PresetTest.java index 6eb284183..2ad328f0d 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/domain/PresetTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/PresetTest.java @@ -8,8 +8,9 @@ class PresetTest { private final Setting setting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTest.java index e69198878..04eaed288 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTest.java @@ -19,23 +19,14 @@ class ReservationTest { @BeforeEach void setUp() { reservation = Reservation.builder() - .startTime(THE_DAY_AFTER_TOMORROW.atTime(8, 0)) - .endTime(THE_DAY_AFTER_TOMORROW.atTime(9, 0)) + .reservationTime( + ReservationTime.of( + THE_DAY_AFTER_TOMORROW.atTime(8, 0), + THE_DAY_AFTER_TOMORROW.atTime(9, 0))) .password("1234") .build(); } - @ParameterizedTest - @CsvSource(value = {"08:01+08:59+true", "07:59+08:01+true", "08:59+09:01+true", - "07:59+09:01+true", "08:00+09:00+true", "07:59+08:00+false", - "09:00+09:01+false", "07:00+08:00+false", "09:00+10:00+false", "07:00+07:50+false"}, delimiter = '+') - @DisplayName("겹치는 시간 정보가 주어지면 true, 예약 가능한 시간대면 false") - void hasConflictWith(String startTime, String endTime, Boolean result) { - LocalDateTime start = THE_DAY_AFTER_TOMORROW.atTime(LocalTime.parse(startTime, DateTimeFormatter.ofPattern("HH:mm"))); - LocalDateTime end = THE_DAY_AFTER_TOMORROW.atTime(LocalTime.parse(endTime, DateTimeFormatter.ofPattern("HH:mm"))); - assertThat(reservation.hasConflictWith(start, end)).isEqualTo(result); - } - @Test @DisplayName("예약 비밀번호가 잘못되었으면 true, 정확하면 false") void isWrongPassword() { diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTimeTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTimeTest.java new file mode 100644 index 000000000..b2c23203c --- /dev/null +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/ReservationTimeTest.java @@ -0,0 +1,134 @@ +package com.woowacourse.zzimkkong.domain; + +import com.woowacourse.zzimkkong.exception.reservation.ImpossibleStartEndTimeException; +import com.woowacourse.zzimkkong.exception.reservation.NonMatchingStartEndDateException; +import com.woowacourse.zzimkkong.exception.reservation.PastReservationTimeException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.stream.Stream; + +import static com.woowacourse.zzimkkong.Constants.THE_DAY_AFTER_TOMORROW; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class ReservationTimeTest { + private final LocalDateTime fourPmUTC = THE_DAY_AFTER_TOMORROW.atTime(16, 0); // next day KST 01:00 + private final LocalDateTime sixPmUTC = THE_DAY_AFTER_TOMORROW.atTime(18, 0); // next day KST 03:00 + private final ReservationTime reservationTime = ReservationTime.of(fourPmUTC, sixPmUTC); + + @Test + @DisplayName("startTime과 endTime의 KST date가 동일하지 않으면 에러를 반환한다") + void of_notSameDate() { + LocalDateTime twoPmUTC = THE_DAY_AFTER_TOMORROW.atTime(14, 0);// KST 23:00 + assertThatThrownBy(() -> ReservationTime.of(twoPmUTC, fourPmUTC)) + .isInstanceOf(NonMatchingStartEndDateException.class); + } + + @Test + @DisplayName("endTime이 startTime과 동일하거나 더 이르면 에러를 반환한다") + void of_invalidStartAndEndTime() { + assertThatThrownBy(() -> ReservationTime.of(sixPmUTC, fourPmUTC)) + .isInstanceOf(ImpossibleStartEndTimeException.class); + } + + @Test + @DisplayName("주어진 시간이 현재 시간보다 과거의 시간이면 에러를 반환한다.") + void validatePastTime() { + LocalDateTime pastTime = LocalDateTime.now().withSecond(0).withNano(0).minusHours(1); + LocalDateTime futureTime = LocalDateTime.now().withSecond(0).withNano(0).plusHours(1); + + assertThatThrownBy(() -> ReservationTime.validatePastTime(pastTime)) + .isInstanceOf(PastReservationTimeException.class); + assertDoesNotThrow(() -> ReservationTime.validatePastTime(futureTime)); + } + + @Test + @DisplayName("UTC 시간이 주어질 때, 한국 시간으로 변환(+9시간) 했을 때의 요일을 반환한다") + void getDayOfWeekKST() { + DayOfWeek dayOfWeekKST = reservationTime.getDayOfWeekKST(); + DayOfWeek dayOfWeekUTC = fourPmUTC.getDayOfWeek(); + + assertThat(dayOfWeekUTC).isNotEqualTo(dayOfWeekKST); + assertThat(dayOfWeekUTC.plus(1)).isEqualTo(dayOfWeekKST); + } + + @Test + @DisplayName("UTC 시간이 주어질 때, 한국 시간으로 변환(+9시간) 했을 때의 TimeSlot을 반환한다") + void asTimeSlotKST() { + TimeSlot actualTimeSlot = reservationTime.asTimeSlotKST(); + TimeSlot expectedTimeSlot = TimeSlot.of( + fourPmUTC.plusHours(9).toLocalTime(), + sixPmUTC.plusHours(9).toLocalTime()); + + assertThat(actualTimeSlot).isEqualTo(expectedTimeSlot); + } + + @ParameterizedTest + @DisplayName("주어진 ReservaitonTime이 다른 ReservationTime과 시간대가 겹치면 true, 아니면 false") + @MethodSource("provideReservationTimes") + void hasConflictWith( + final ReservationTime thisReservationTime, + final ReservationTime thatReservationTime, + final boolean expectedResult) { + assertThat(thisReservationTime.hasConflictWith(thatReservationTime)).isEqualTo(expectedResult); + assertThat(thatReservationTime.hasConflictWith(thisReservationTime)).isEqualTo(expectedResult); + } + + @Test + @DisplayName("KST 기준으로 date를 가져온다") + void getDate() { + LocalDate actualDate = reservationTime.getDate(); + LocalDate expectedDate = fourPmUTC.toLocalDate().plusDays(1); + + assertThat(actualDate).isEqualTo(expectedDate); + } + + private static Stream provideReservationTimes() { + return Stream.of( + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(10, 0), THE_DAY_AFTER_TOMORROW.atTime(10, 5)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(10, 0), THE_DAY_AFTER_TOMORROW.atTime(10, 5)), + true), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 5), THE_DAY_AFTER_TOMORROW.atTime(12, 15)), + true), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 15), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + true), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 15), THE_DAY_AFTER_TOMORROW.atTime(12, 25)), + true), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 30)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 15), THE_DAY_AFTER_TOMORROW.atTime(12, 25)), + true), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 0), THE_DAY_AFTER_TOMORROW.atTime(12, 5)), + false), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 25), THE_DAY_AFTER_TOMORROW.atTime(12, 35)), + false), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 5), THE_DAY_AFTER_TOMORROW.atTime(12, 10)), + false), + Arguments.of( + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 10), THE_DAY_AFTER_TOMORROW.atTime(12, 20)), + ReservationTime.of(THE_DAY_AFTER_TOMORROW.atTime(12, 20), THE_DAY_AFTER_TOMORROW.atTime(12, 30)), + false) + ); + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/SettingTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/SettingTest.java index 9d47b6ce1..bce09a891 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/domain/SettingTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/SettingTest.java @@ -17,8 +17,9 @@ class SettingTest { @DisplayName("setting의 입력값이 모두 올바르면 setting을 생성한다") void name() { assertDoesNotThrow(() -> Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -27,30 +28,16 @@ void name() { .build()); } - @ParameterizedTest - @CsvSource(value = {"10,9", "10,10"}) - @DisplayName("setting 생성 시 예약이 열릴 시간이 예약 닫힐 시간 이후거나 같으면 예외를 던진다") - void invalidAvailableStartEndTime(int availableStartTimeHour, int availableEndTimeHour) { - final Setting.SettingBuilder settingBuilder = Setting.builder() - .availableStartTime(LocalTime.of(availableStartTimeHour, 0)) - .availableEndTime(LocalTime.of(availableEndTimeHour, 0)) - .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) - .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) - .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) - .reservationEnable(FE_RESERVATION_ENABLE) - .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK); - assertThatThrownBy(settingBuilder::build).isInstanceOf(ImpossibleAvailableStartEndTimeException.class); - } - @Test @DisplayName("setting 생성 시 최대 예약 가능 시간이 최소 예약 가능시간 보다 작으면 예외를 던진다") void invalidMinimumMaximumTimeUnit() { final Setting.SettingBuilder settingBuilder = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) - .reservationMinimumTimeUnit(20) - .reservationMaximumTimeUnit(10) + .reservationMinimumTimeUnit(TimeUnit.from(20)) + .reservationMaximumTimeUnit(TimeUnit.from(10)) .reservationEnable(FE_RESERVATION_ENABLE) .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK); assertThatThrownBy(settingBuilder::build).isInstanceOf(InvalidMinimumMaximumTimeUnitException.class); @@ -60,11 +47,12 @@ void invalidMinimumMaximumTimeUnit() { @DisplayName("setting 생성 시 예약이 가능한 시간 범위가 최대 예약 가능 시간 보다 작으면 예외를 던진다") void notEnoughTimeAvailable() { final Setting.SettingBuilder settingBuilder = Setting.builder() - .availableStartTime(LocalTime.of(10, 0)) - .availableEndTime(LocalTime.of(11, 0)) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(10, 0), + LocalTime.of(11, 0))) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) - .reservationMaximumTimeUnit(70) + .reservationMaximumTimeUnit(TimeUnit.from(70)) .reservationEnable(FE_RESERVATION_ENABLE) .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK); assertThatThrownBy(settingBuilder::build).isInstanceOf(NotEnoughAvailableTimeException.class); @@ -75,9 +63,10 @@ void notEnoughTimeAvailable() { @DisplayName("setting 생성 시 예약이 시작되는 시간과 닫히는 시간이 time unit단위와 맞으면 예외를 던지지 않는다") void timeUnitMismatch_ok(int startMinute, int endMinute, int timeUnit) { assertDoesNotThrow(() -> Setting.builder() - .availableStartTime(LocalTime.of(10, startMinute)) - .availableEndTime(LocalTime.of(20, endMinute)) - .reservationTimeUnit(timeUnit) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(10, startMinute), + LocalTime.of(20, endMinute))) + .reservationTimeUnit(TimeUnit.from(timeUnit)) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) .reservationEnable(FE_RESERVATION_ENABLE) @@ -86,13 +75,14 @@ void timeUnitMismatch_ok(int startMinute, int endMinute, int timeUnit) { } @ParameterizedTest - @CsvSource(value = {"22,27,5", "0,15,10", "15,0,10", "10,40,30", "5,5,60"}) + @CsvSource(value = {"0,15,10", "15,0,10", "10,40,30", "5,5,60"}) @DisplayName("setting 생성 시 예약이 시작되는 시간과 닫히는 시간이 time unit단위와 맞지 않으면 예외를 던진다") void timeUnitMismatch_fail(int startMinute, int endMinute, int timeUnit) { final Setting.SettingBuilder settingBuilder = Setting.builder() - .availableStartTime(LocalTime.of(10, startMinute)) - .availableEndTime(LocalTime.of(20, endMinute)) - .reservationTimeUnit(timeUnit) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(10, startMinute), + LocalTime.of(20, endMinute))) + .reservationTimeUnit(TimeUnit.from(timeUnit)) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) .reservationEnable(FE_RESERVATION_ENABLE) @@ -101,15 +91,16 @@ void timeUnitMismatch_fail(int startMinute, int endMinute, int timeUnit) { } @ParameterizedTest - @CsvSource(value = {"0,5", "5,10", "9,20", "10,25", "15,30", "25,45"}) + @CsvSource(value = {"5,10", "15,20", "10,25", "15,30", "25,45"}) @DisplayName("setting 생성 시 최소,최대 예약 가능 시간의 단위가 예약 시간 단위와 일치하지 않으면 예외를 던진다") void timeUnitInconsistency_fail(int minimumMinute, int maximumMinute) { final Setting.SettingBuilder settingBuilder = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(minimumMinute) - .reservationMaximumTimeUnit(maximumMinute) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(minimumMinute)) + .reservationMaximumTimeUnit(TimeUnit.from(maximumMinute)) .reservationEnable(FE_RESERVATION_ENABLE) .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK); assertThatThrownBy(settingBuilder::build).isInstanceOf(TimeUnitInconsistencyException.class); diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/SpaceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/SpaceTest.java index 88285baf9..0d5b893ba 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/domain/SpaceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/SpaceTest.java @@ -21,8 +21,9 @@ void update() { Map map = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, member); Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(10, 0)) - .availableEndTime(LocalTime.of(18, 0)) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(10, 0), + LocalTime.of(18, 0))) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -39,8 +40,9 @@ void update() { .build(); Setting updateSetting = Setting.builder() - .availableStartTime(LocalTime.of(10, 0)) - .availableEndTime(LocalTime.of(18, 0)) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(10, 0), + LocalTime.of(18, 0))) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -76,8 +78,9 @@ void hasSameId() { @DisplayName("예약하려는 시간이 공간의 예약 가능한 시간 내에 있다면 false를 반환한다") void isNotBetweenAvailableTime(int startHour, int endHour) { Setting availableTimeSetting = Setting.builder() - .availableStartTime(LocalTime.of(10, 0)) - .availableEndTime(LocalTime.of(18, 0)) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(10, 0), + LocalTime.of(18, 0))) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -88,7 +91,8 @@ void isNotBetweenAvailableTime(int startHour, int endHour) { LocalDateTime startDateTime = THE_DAY_AFTER_TOMORROW.atTime(startHour, 0); LocalDateTime endDateTime = THE_DAY_AFTER_TOMORROW.atTime(endHour, 0); - boolean actual = availableTimeSpace.isNotBetweenAvailableTime(startDateTime, endDateTime); + TimeSlot timeSlot = TimeSlot.of(startDateTime.toLocalTime(), endDateTime.toLocalTime()); + boolean actual = availableTimeSpace.cannotAcceptDueToAvailableTime(timeSlot); assertThat(actual).isFalse(); } @@ -97,8 +101,9 @@ void isNotBetweenAvailableTime(int startHour, int endHour) { @DisplayName("예약하려는 시간이 공간의 예약 가능한 시간 외에 있다면 true를 반환한다") void isNotBetweenAvailableTimeFail() { Setting availableTimeSetting = Setting.builder() - .availableStartTime(LocalTime.of(10, 0)) - .availableEndTime(LocalTime.of(18, 0)) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(10, 0), + LocalTime.of(18, 0))) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -107,131 +112,11 @@ void isNotBetweenAvailableTimeFail() { .build(); Space availableTimeSpace = Space.builder().setting(availableTimeSetting).build(); - LocalDateTime startDateTime = THE_DAY_AFTER_TOMORROW.atTime(9, 59); - LocalDateTime endDateTime = THE_DAY_AFTER_TOMORROW.atTime(18, 1); - boolean actual = availableTimeSpace.isNotBetweenAvailableTime(startDateTime, endDateTime); + LocalDateTime startDateTime = THE_DAY_AFTER_TOMORROW.atTime(9, 50); + LocalDateTime endDateTime = THE_DAY_AFTER_TOMORROW.atTime(18, 10); + TimeSlot timeSlot = TimeSlot.of(startDateTime.toLocalTime(), endDateTime.toLocalTime()); - assertThat(actual).isTrue(); - } - - @ParameterizedTest - @ValueSource(ints = {0, 10}) - @DisplayName("예약 시작 시간의 단위가 타당하면 false를 반환한다.") - void isCorrectTimeUnit(int minute) { - Setting availableTimeSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) - .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) - .reservationEnable(FE_RESERVATION_ENABLE) - .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK) - .build(); - Space availableTimeSpace = Space.builder().setting(availableTimeSetting).build(); - - boolean actual = availableTimeSpace.isNotDivisibleByTimeUnit(minute); - - assertThat(actual).isFalse(); - } - - @ParameterizedTest - @ValueSource(ints = {9, 11}) - @DisplayName("예약 시작 시간의 단위가 타당하지 않다면 true를 반환한다.") - void isCorrectTimeUnitFail(int minute) { - Setting availableTimeSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) - .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) - .reservationEnable(FE_RESERVATION_ENABLE) - .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK) - .build(); - Space availableTimeSpace = Space.builder().setting(availableTimeSetting).build(); - - boolean actual = availableTimeSpace.isNotDivisibleByTimeUnit(minute); - - assertThat(actual).isTrue(); - } - - @Test - @DisplayName("예약 시간의 단위가 최소/최대 예약시간단위 내에 있다면 false를 반환한다.") - void isCorrectMinimumMaximumTimeUnit() { - Setting availableTimeSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) - .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) - .reservationEnable(FE_RESERVATION_ENABLE) - .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK) - .build(); - Space availableTimeSpace = Space.builder().setting(availableTimeSetting).build(); - - boolean minActual = availableTimeSpace.isIncorrectMinimumTimeUnit(10); - boolean maxActual = availableTimeSpace.isIncorrectMinimumTimeUnit(120); - - assertThat(minActual).isFalse(); - assertThat(maxActual).isFalse(); - } - - @Test - @DisplayName("예약 시간의 단위가 최소/최대 시간단위보다 작다면 true를 반환한다.") - void isCorrectMinimumMaximumTimeUnitFail() { - Setting availableTimeSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) - .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) - .reservationEnable(FE_RESERVATION_ENABLE) - .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK) - .build(); - Space availableTimeSpace = Space.builder().setting(availableTimeSetting).build(); - - boolean minActual = availableTimeSpace.isIncorrectMinimumTimeUnit(9); - boolean maxActual = availableTimeSpace.isIncorrectMaximumTimeUnit(121); - - assertThat(minActual).isTrue(); - assertThat(maxActual).isTrue(); - } - - @Test - @DisplayName("예약 시간의 단위가 공간의 timeUnit으로 나누어떨어지면 false를 반환한다.") - void isNotDivideBy() { - Setting availableTimeSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) - .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) - .reservationEnable(FE_RESERVATION_ENABLE) - .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK) - .build(); - Space availableTimeSpace = Space.builder().setting(availableTimeSetting).build(); - - int minute = 100; - boolean actual = availableTimeSpace.isNotDivisibleByTimeUnit(minute); - - assertThat(actual).isFalse(); - } - - @Test - @DisplayName("예약 시간의 단위가 공간의 timeUnit으로 나누어떨어지지 않으면 true를 반환한다.") - void isNotDivideByFail() { - Setting availableTimeSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) - .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) - .reservationEnable(FE_RESERVATION_ENABLE) - .enabledDayOfWeek(FE_ENABLED_DAY_OF_WEEK) - .build(); - Space availableTimeSpace = Space.builder().setting(availableTimeSetting).build(); - - int minute = 12; - boolean actual = availableTimeSpace.isNotDivisibleByTimeUnit(minute); + boolean actual = availableTimeSpace.cannotAcceptDueToAvailableTime(timeSlot); assertThat(actual).isTrue(); } @@ -240,8 +125,9 @@ void isNotDivideByFail() { @DisplayName("예약이 가능한 공간이면 false를 반환한다") void isUnableToReserve() { Setting reservationEnableSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -257,8 +143,9 @@ void isUnableToReserve() { @DisplayName("예약이 불가능한 공간이면 true를 반환한다") void isUnableToReserveFail() { Setting reservationUnableSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -275,8 +162,9 @@ void isUnableToReserveFail() { @DisplayName("해당 요일에 예약이 가능하면 false를 반환한다") void isClosedOn(DayOfWeek dayOfWeek) { Setting setting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -293,8 +181,9 @@ void isClosedOn(DayOfWeek dayOfWeek) { @DisplayName("해당 요일에 예약이 불가능하면 true를 반환한다") void isClosedOnFail(DayOfWeek dayOfWeek) { Setting setting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -311,8 +200,9 @@ void isClosedOnFail(DayOfWeek dayOfWeek) { @DisplayName("예약 가능한 요일이 null이면 모든 요일에 대해서 true를 반환한다") void isClosedOn_nullEnabledDayOfWeek(DayOfWeek dayOfWeek) { Setting setting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeSlotTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeSlotTest.java new file mode 100644 index 000000000..560725b21 --- /dev/null +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeSlotTest.java @@ -0,0 +1,152 @@ +package com.woowacourse.zzimkkong.domain; + +import com.woowacourse.zzimkkong.exception.reservation.IllegalTimeUnitValueException; +import com.woowacourse.zzimkkong.exception.reservation.ImpossibleStartEndTimeException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.time.LocalTime; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class TimeSlotTest { + @ParameterizedTest + @DisplayName("endTime이 startTime 보다 작거나 같으면 에러를 반환한다") + @MethodSource("provideStartAndEndTime_endTimeEqualOrShorterThanStartTime") + void validateStartEndTime_endTimeEqualOrShorterThanStartTime(final LocalTime startTime, final LocalTime endTime) { + assertThatThrownBy(() -> TimeSlot.validateStartEndTime(startTime, endTime)) + .isInstanceOf(ImpossibleStartEndTimeException.class); + } + + @ParameterizedTest + @DisplayName("startTime이나 endTime의 분 단위가 5의 배수가 아니면 에러를 반환한다") + @MethodSource("provideStartAndEndTime_notDivisibleByMinimumTimeUnit") + void validateStartEndTime_startTimeAndEndTimeNotDivisibleByMinimumTimeUnit(final LocalTime startTime, final LocalTime endTime) { + assertThatThrownBy(() -> TimeSlot.validateStartEndTime(startTime, endTime)) + .isInstanceOf(IllegalTimeUnitValueException.class); + } + + @ParameterizedTest + @DisplayName("startTime과 endTime 중 하나라도 TimeUnit으로 나누어 떨어지지 않으면 true, 아니면 false") + @MethodSource("provideTimeSlotArguments_isNotDivisible") + void isNotDivisibleBy( + final TimeSlot timeSlot, + final TimeUnit timeUnit, + final boolean expectedResult) { + assertThat(timeSlot.isNotDivisibleBy(timeUnit)).isEqualTo(expectedResult); + } + + @Test + @DisplayName("TimeSlot의 duration이 TimeUnit보다 짧으면 true, 아니면 false") + void isDurationShorterThan() { + TimeSlot shortTimeSlot = TimeSlot.of(LocalTime.of(10, 0), LocalTime.of(10, 5)); + TimeSlot equalTimeSlot = TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)); + TimeSlot longTimeSlot = TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 30)); + TimeUnit timeUnit = TimeUnit.from(10); + + assertThat(shortTimeSlot.isDurationShorterThan(timeUnit)).isTrue(); + assertThat(equalTimeSlot.isDurationShorterThan(timeUnit)).isFalse(); + assertThat(longTimeSlot.isDurationShorterThan(timeUnit)).isFalse(); + } + + @Test + @DisplayName("TimeSlot의 duration이 TimeUnit보다 길면 true, 아니면 false") + void isDurationLongerThan() { + TimeSlot shortTimeSlot = TimeSlot.of(LocalTime.of(10, 0), LocalTime.of(10, 5)); + TimeSlot equalTimeSlot = TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)); + TimeSlot longTimeSlot = TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 30)); + TimeUnit timeUnit = TimeUnit.from(10); + + assertThat(shortTimeSlot.isDurationLongerThan(timeUnit)).isFalse(); + assertThat(equalTimeSlot.isDurationLongerThan(timeUnit)).isFalse(); + assertThat(longTimeSlot.isDurationLongerThan(timeUnit)).isTrue(); + } + + @ParameterizedTest + @DisplayName("TimeSlot이 다른 TimeSlot과 안 겹치면 true, 겹치면 false") + @MethodSource("provideTimeSlotArguments_isNotWithin") + void isNotWithin( + final TimeSlot thisTimeSlot, + final TimeSlot thatTimeSlot, + final boolean expectedResult) { + assertThat(thisTimeSlot.isNotWithin(thatTimeSlot)).isEqualTo(expectedResult); + } + + private static Stream provideStartAndEndTime_endTimeEqualOrShorterThanStartTime() { + return Stream.of( + Arguments.of(LocalTime.of(10, 0), LocalTime.of(9, 0)), + Arguments.of(LocalTime.of(10, 0), LocalTime.of(10, 0)) + ); + } + + private static Stream provideStartAndEndTime_notDivisibleByMinimumTimeUnit() { + return Stream.of( + Arguments.of(LocalTime.of(10, 0), LocalTime.of(10, 1)), + Arguments.of(LocalTime.of(12, 4), LocalTime.of(12, 5)), + Arguments.of(LocalTime.of(13, 6), LocalTime.of(13, 11)) + ); + } + + private static Stream provideTimeSlotArguments_isNotDivisible() { + return Stream.of( + Arguments.of( + TimeSlot.of(LocalTime.of(10, 0), LocalTime.of(10, 5)), + TimeUnit.from(10), + true), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + TimeUnit.from(5), + false), + Arguments.of( + TimeSlot.of(LocalTime.of(13, 10), LocalTime.of(13, 30)), + TimeUnit.from(20), + true) + ); + } + + private static Stream provideTimeSlotArguments_isNotWithin() { + return Stream.of( + Arguments.of( + TimeSlot.of(LocalTime.of(12, 5), LocalTime.of(12, 15)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + true), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 15), LocalTime.of(12, 25)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + true), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 0), LocalTime.of(12, 5)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + true), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 25), LocalTime.of(12, 35)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + true), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 5), LocalTime.of(12, 10)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + true), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 20), LocalTime.of(12, 30)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + true), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 15), LocalTime.of(12, 25)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 30)), + false), + Arguments.of( + TimeSlot.of(LocalTime.of(12, 15), LocalTime.of(12, 20)), + TimeSlot.of(LocalTime.of(12, 10), LocalTime.of(12, 20)), + false), + Arguments.of( + TimeSlot.of(LocalTime.of(10, 0), LocalTime.of(10, 5)), + TimeSlot.of(LocalTime.of(10, 0), LocalTime.of(10, 5)), + false) + ); + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeUnitTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeUnitTest.java new file mode 100644 index 000000000..6ef96ed30 --- /dev/null +++ b/backend/src/test/java/com/woowacourse/zzimkkong/domain/TimeUnitTest.java @@ -0,0 +1,63 @@ +package com.woowacourse.zzimkkong.domain; + +import com.woowacourse.zzimkkong.exception.reservation.IllegalTimeUnitValueException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static com.woowacourse.zzimkkong.domain.TimeUnit.MINIMUM_TIME_UNIT; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class TimeUnitTest { + @ParameterizedTest + @DisplayName("TimeUnit 생성시 0 이하의 시간 혹은 5의 배수가 아닌 시간이 들어오면 에러를 반환한다") + @ValueSource(ints = {-5, 0, 1, 4}) + void timeUnitValueNotDivisibleByMinimumTimeUnit(final int minutes) { + String message = String.format(IllegalTimeUnitValueException.MESSAGE_FORMAT, minutes); + + assertThatThrownBy(() -> TimeUnit.from(minutes)) + .isInstanceOf(IllegalTimeUnitValueException.class) + .hasMessage(message); + } + + @Test + @DisplayName("5분 부터 120분 까지는 TimeUnit 객체가 캐싱된다") + void timeUnitCache() { + for (int i = 1; i <= 24; i++) { + int minutes = i * MINIMUM_TIME_UNIT; + + TimeUnit thisTimeUnit = TimeUnit.from(minutes); + TimeUnit thatTimeUnit = TimeUnit.from(minutes); + assertThat(thisTimeUnit).isSameAs(thatTimeUnit); + } + + TimeUnit thisTimeUnit = TimeUnit.from(125); + TimeUnit thatTimeUnit = TimeUnit.from(125); + assertThat(thisTimeUnit).isNotSameAs(thatTimeUnit); + } + + @ParameterizedTest + @DisplayName("TimeUnit이 다른 TimeUnit으로 나누어 떨어지면 true 아니면 false") + @CsvSource(value = {"5,5,true", "5,10,false", "10,5,true", "25,10,false", "25,5,true"}) + void isDivisibleBy(final int minutes1, final int minutes2, final boolean expectedResult) { + TimeUnit thisTimeUnit = TimeUnit.from(minutes1); + TimeUnit thatTimeUnit = TimeUnit.from(minutes2); + + boolean actualResult = thisTimeUnit.isDivisibleBy(thatTimeUnit); + assertThat(actualResult).isEqualTo(expectedResult); + } + + @ParameterizedTest + @DisplayName("TimeUnit이 다른 TimeUnit보다 시간이 짧으면 true, 아니면 false") + @CsvSource(value = {"5,5,false", "5,10,true", "10,5,false", "25,10,false", "15,20,true"}) + void isShorterThan(final int minutes1, final int minutes2, final boolean expectedResult) { + TimeUnit thisTimeUnit = TimeUnit.from(minutes1); + TimeUnit thatTimeUnit = TimeUnit.from(minutes2); + + boolean actualResult = thisTimeUnit.isShorterThan(thatTimeUnit); + assertThat(actualResult).isEqualTo(expectedResult); + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/dto/PresetCreateRequestTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/dto/PresetCreateRequestTest.java index 6700250df..32b176b09 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/dto/PresetCreateRequestTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/dto/PresetCreateRequestTest.java @@ -16,9 +16,9 @@ class PresetCreateRequestTest extends RequestTest { private final SettingsRequest settingsRequest = new SettingsRequest( BE_AVAILABLE_START_TIME, BE_AVAILABLE_END_TIME, - BE_RESERVATION_TIME_UNIT, - BE_RESERVATION_MINIMUM_TIME_UNIT, - BE_RESERVATION_MAXIMUM_TIME_UNIT, + BE_RESERVATION_TIME_UNIT.getMinutes(), + BE_RESERVATION_MINIMUM_TIME_UNIT.getMinutes(), + BE_RESERVATION_MAXIMUM_TIME_UNIT.getMinutes(), BE_RESERVATION_ENABLE, EnabledDayOfWeekDto.from(BE_ENABLED_DAY_OF_WEEK) ); diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/dto/RequestTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/dto/RequestTest.java index e4717f70e..10b87853a 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/dto/RequestTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/dto/RequestTest.java @@ -17,9 +17,9 @@ class RequestTest { protected final SettingsRequest beSettingsRequest = new SettingsRequest( BE_AVAILABLE_START_TIME, BE_AVAILABLE_END_TIME, - BE_RESERVATION_TIME_UNIT, - BE_RESERVATION_MINIMUM_TIME_UNIT, - BE_RESERVATION_MAXIMUM_TIME_UNIT, + BE_RESERVATION_TIME_UNIT.getMinutes(), + BE_RESERVATION_MINIMUM_TIME_UNIT.getMinutes(), + BE_RESERVATION_MAXIMUM_TIME_UNIT.getMinutes(), BE_RESERVATION_ENABLE, EnabledDayOfWeekDto.from(BE_ENABLED_DAY_OF_WEEK) ); diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/repository/MapRepositoryTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/repository/MapRepositoryTest.java index 8cad84689..c1b6f9b0b 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/repository/MapRepositoryTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/repository/MapRepositoryTest.java @@ -1,10 +1,7 @@ package com.woowacourse.zzimkkong.repository; import com.woowacourse.zzimkkong.Constants; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Member; -import com.woowacourse.zzimkkong.domain.Setting; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.exception.map.NoSuchMapException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -95,8 +92,9 @@ void findByIdFetchJoinSpace() { Map savedMap = maps.save(luther); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -114,8 +112,9 @@ void findByIdFetchJoinSpace() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/repository/PresetRepositoryTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/repository/PresetRepositoryTest.java index fdf4f384a..2c73f32b7 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/repository/PresetRepositoryTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/repository/PresetRepositoryTest.java @@ -3,6 +3,7 @@ import com.woowacourse.zzimkkong.domain.Member; import com.woowacourse.zzimkkong.domain.Preset; import com.woowacourse.zzimkkong.domain.Setting; +import com.woowacourse.zzimkkong.domain.TimeSlot; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -23,8 +24,10 @@ void setUp() { members.save(pobi); Setting setting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot( + TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImplTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImplTest.java index 20a22dbcf..a394e32f8 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImplTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryImplTest.java @@ -6,9 +6,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import java.time.LocalDate; -import java.time.LocalDateTime; - import static com.woowacourse.zzimkkong.Constants.*; import static com.woowacourse.zzimkkong.infrastructure.datetime.TimeZoneUtils.UTC; @@ -25,8 +22,9 @@ void existsReservationsByMember(boolean isReservationExists) { maps.save(luther); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -46,9 +44,10 @@ void existsReservationsByMember(boolean isReservationExists) { spaces.save(be); Reservation beAmZeroOneYesterday = Reservation.builder() - .date(LocalDate.now().minusDays(1)) - .startTime(LocalDateTime.now().minusDays(1)) - .endTime(LocalDateTime.now().minusDays(1).plusHours(1)) + .reservationTime( + ReservationTime.of( + THE_DAY_AFTER_TOMORROW.minusDays(1).atTime(0, 0), + THE_DAY_AFTER_TOMORROW.minusDays(1).atTime(1, 0))) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -59,9 +58,10 @@ void existsReservationsByMember(boolean isReservationExists) { if (isReservationExists) { Reservation beAmZeroOne = Reservation.builder() - .date(BE_AM_TEN_ELEVEN_START_TIME_KST.toLocalDate()) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -72,7 +72,9 @@ void existsReservationsByMember(boolean isReservationExists) { } // when - Boolean hasAnyReservations = reservations.existsReservationsByMemberFromToday(savedMember); + Boolean hasAnyReservations = reservations.existsByMemberAndEndTimeAfter( + savedMember, + THE_DAY_AFTER_TOMORROW.atTime(0, 0)); // then AssertionsForClassTypes.assertThat(hasAnyReservations).isEqualTo(isReservationExists); diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryTest.java index bf87338d3..327674302 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/repository/ReservationRepositoryTest.java @@ -37,8 +37,9 @@ void setUp() { Map luther = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -56,8 +57,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -80,9 +82,10 @@ void setUp() { spaces.save(fe); beAmZeroOne = Reservation.builder() - .date(BE_AM_TEN_ELEVEN_START_TIME_KST.toLocalDate()) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -90,9 +93,10 @@ void setUp() { .build(); bePmOneTwo = Reservation.builder() - .date(BE_PM_ONE_TWO_START_TIME_KST.toLocalDate()) - .startTime(BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_PM_ONE_TWO_DESCRIPTION) .userName(BE_PM_ONE_TWO_USERNAME) .password(BE_PM_ONE_TWO_PW) @@ -100,9 +104,10 @@ void setUp() { .build(); beNextDayAmSixTwelve = Reservation.builder() - .date(BE_NEXT_DAY_PM_FOUR_TO_SIX_START_TIME_KST.toLocalDate()) - .startTime(BE_NEXT_DAY_PM_FOUR_TO_SIX_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_NEXT_DAY_PM_FOUR_TO_SIX_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_NEXT_DAY_PM_FOUR_TO_SIX_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_NEXT_DAY_PM_FOUR_TO_SIX_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_NEXT_DAY_PM_FOUR_TO_SIX_DESCRIPTION) .userName(BE_NEXT_DAY_PM_FOUR_TO_SIX_USERNAME) .password(BE_NEXT_DAY_PM_FOUR_TO_SIX_PW) @@ -110,9 +115,10 @@ void setUp() { .build(); fe1ZeroOne = Reservation.builder() - .date(FE1_AM_TEN_ELEVEN_START_TIME_KST.toLocalDate()) - .startTime(FE1_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(FE1_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + FE1_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + FE1_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(FE1_AM_TEN_ELEVEN_DESCRIPTION) .userName(FE1_AM_TEN_ELEVEN_USERNAME) .password(FE1_AM_TEN_ELEVEN_PW) @@ -130,9 +136,10 @@ void setUp() { void save() { //given Reservation be_two_three = Reservation.builder() - .date(THE_DAY_AFTER_TOMORROW) - .startTime(THE_DAY_AFTER_TOMORROW.atTime(2, 0)) - .endTime(THE_DAY_AFTER_TOMORROW.atTime(3, 0)) + .reservationTime( + ReservationTime.of( + THE_DAY_AFTER_TOMORROW.atTime(2, 0), + THE_DAY_AFTER_TOMORROW.atTime(3, 0))) .description("찜꽁 4차 회의") .userName("찜꽁") .password("1234") @@ -188,10 +195,10 @@ void delete() { @DisplayName("해당 공간에 대한 예약 존재여부를 확인한다.") void existsBySpace() { // given, when, then - assertThat(reservations.existsBySpaceIdAndEndTimeAfter(fe.getId(), LocalDateTime.now())).isTrue(); + assertThat(reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(fe.getId(), LocalDateTime.now())).isTrue(); reservations.delete(fe1ZeroOne); - assertThat(reservations.existsBySpaceIdAndEndTimeAfter(fe.getId(), LocalDateTime.now())).isFalse(); + assertThat(reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(fe.getId(), LocalDateTime.now())).isFalse(); } @ParameterizedTest @@ -199,7 +206,7 @@ void existsBySpace() { @DisplayName("특정 시간 이후의 예약이 존재하는지 확인한다.") void existsBySpaceIdAndDateGreaterThanEqual(int minusMinute, boolean expected) { //given, when - Boolean actual = reservations.existsBySpaceIdAndEndTimeAfter( + Boolean actual = reservations.existsBySpaceIdAndReservationTimeEndTimeAfter( be.getId(), BE_NEXT_DAY_PM_FOUR_TO_SIX_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime().minusMinutes(minusMinute)); @@ -222,7 +229,7 @@ void findAllByPaging() { } private List getReservations(List spaceIds, LocalDate date) { - return reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + return reservations.findAllBySpaceIdInAndDateBetween( spaceIds, date.minusDays(ONE_DAY_OFFSET), date.plusDays(ONE_DAY_OFFSET)); diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/repository/SpaceRepositoryTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/repository/SpaceRepositoryTest.java index 6659d135d..093c4b079 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/repository/SpaceRepositoryTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/repository/SpaceRepositoryTest.java @@ -1,10 +1,7 @@ package com.woowacourse.zzimkkong.repository; import com.woowacourse.zzimkkong.Constants; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Member; -import com.woowacourse.zzimkkong.domain.Setting; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -28,8 +25,9 @@ void setUp() { luther = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -47,8 +45,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/service/AdminServiceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/service/AdminServiceTest.java index 9ed8cbe78..ff6d84de9 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/service/AdminServiceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/service/AdminServiceTest.java @@ -109,8 +109,9 @@ void findSpaces() { //given Map luther = new Map(LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -150,8 +151,9 @@ void findReservations() { //given Map luther = new Map(1L, LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -169,9 +171,10 @@ void findReservations() { .build(); Reservation beAmZeroOne = Reservation.builder() - .date(BE_AM_TEN_ELEVEN_START_TIME_KST.toLocalDate()) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/service/GuestReservationServiceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/service/GuestReservationServiceTest.java index 931f61bfc..5fbd6f05f 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/service/GuestReservationServiceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/service/GuestReservationServiceTest.java @@ -66,8 +66,9 @@ void setUp() { luther = new Map(1L, LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -85,8 +86,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -106,8 +108,10 @@ void setUp() { beAmZeroOne = Reservation.builder() .id(1L) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -116,8 +120,10 @@ void setUp() { bePmOneTwo = Reservation.builder() .id(2L) - .startTime(BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_PM_ONE_TWO_DESCRIPTION) .userName(BE_PM_ONE_TWO_USERNAME) .password(BE_PM_ONE_TWO_PW) @@ -221,7 +227,7 @@ void saveStartTimeBeforeNow() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, guestReservationStrategy)) - .isInstanceOf(ImpossibleStartTimeException.class); + .isInstanceOf(PastReservationTimeException.class); } @Test @@ -247,7 +253,7 @@ void saveEndTimeBeforeNow() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, guestReservationStrategy)) - .isInstanceOf(ImpossibleEndTimeException.class); + .isInstanceOf(ImpossibleStartEndTimeException.class); } @Test @@ -273,7 +279,7 @@ void saveStartTimeEqualsEndTime() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, guestReservationStrategy)) - .isInstanceOf(ImpossibleEndTimeException.class); + .isInstanceOf(ImpossibleStartEndTimeException.class); } @Test @@ -299,7 +305,7 @@ void saveStartTimeDateNotEqualsEndTimeDate() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, guestReservationStrategy)) - .isInstanceOf(NonMatchingStartAndEndDateException.class); + .isInstanceOf(NonMatchingStartEndDateException.class); } @ParameterizedTest @@ -337,9 +343,8 @@ void saveAvailabilityException(int startMinute, int endMinute) { //given, when given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(List.of(makeReservation( reservationCreateUpdateWithPasswordRequest.localStartDateTime().minusMinutes(startMinute), @@ -363,11 +368,12 @@ void saveAvailabilityException(int startMinute, int endMinute) { void saveReservationUnable() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(false) .enabledDayOfWeek(null) .build(); @@ -403,11 +409,12 @@ void saveReservationUnable() { void saveIllegalDayOfWeek() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(true) .enabledDayOfWeek(THE_DAY_AFTER_TOMORROW.plusDays(1L).getDayOfWeek().name()) .build(); @@ -445,7 +452,7 @@ void saveSameThresholdTime(int duration) { //given, when given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndDateBetween( anyList(), any(LocalDate.class), any(LocalDate.class))) @@ -475,7 +482,7 @@ void saveSameThresholdTime(int duration) { } @ParameterizedTest - @CsvSource({"1,61","10,55","5,65","20,89"}) + @CsvSource({"5,60","10,55","5,65","20,85"}) @DisplayName("예약 생성/수정 요청 시, space setting의 reservationTimeUnit이 일치하지 않으면 예외가 발생한다.") void saveReservationTimeUnitException(int additionalStartMinute, int additionalEndMinute) { //given @@ -617,12 +624,12 @@ void pastReservationSaveUpdateException() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, guestReservationStrategy)) - .isInstanceOf(ImpossibleStartTimeException.class); + .isInstanceOf(PastReservationTimeException.class); assertThatThrownBy(() -> reservationService.updateReservation( reservationUpdateDto, guestReservationStrategy)) - .isInstanceOf(ImpossibleStartTimeException.class); + .isInstanceOf(PastReservationTimeException.class); } @Test @@ -642,9 +649,8 @@ void findReservations() { given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(foundReservations); @@ -710,7 +716,7 @@ void findEmptyReservations() { .willReturn(Optional.of(luther)); given(maps.existsById(anyLong())) .willReturn(true); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndDateBetween( anyList(), any(LocalDate.class), any(LocalDate.class))) @@ -766,9 +772,8 @@ void findAllReservation() { given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(foundReservations); @@ -916,7 +921,7 @@ void updateInvalidEndTimeException(int endTime) { assertThatThrownBy(() -> reservationService.updateReservation( reservationUpdateDto, guestReservationStrategy)) - .isInstanceOf(ImpossibleEndTimeException.class); + .isInstanceOf(ImpossibleStartEndTimeException.class); } @Test @@ -945,7 +950,7 @@ void updateInvalidDateException() { assertThatThrownBy(() -> reservationService.updateReservation( reservationUpdateDto, guestReservationStrategy)) - .isInstanceOf(NonMatchingStartAndEndDateException.class); + .isInstanceOf(NonMatchingStartEndDateException.class); } @Test @@ -988,9 +993,8 @@ void updateImpossibleTimeException(int startTime, int endTime) { .willReturn(Optional.of(luther)); given(reservations.findById(anyLong())) .willReturn(Optional.of(reservation)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(Arrays.asList( beAmZeroOne, @@ -1054,11 +1058,12 @@ void updateInvalidTimeSetting(int startTime, int endTime) { void updateReservationUnable() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(false) .enabledDayOfWeek(null) .build(); @@ -1098,11 +1103,12 @@ void updateReservationUnable() { void updateIllegalDayOfWeek() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(true) .enabledDayOfWeek(THE_DAY_AFTER_TOMORROW.plusDays(1L).getDayOfWeek().name()) .build(); @@ -1245,14 +1251,16 @@ void deletePastReservationException() { assertThatThrownBy(() -> reservationService.deleteReservation( reservationAuthenticationDto, guestReservationStrategy)) - .isInstanceOf(ImpossibleStartTimeException.class); + .isInstanceOf(PastReservationTimeException.class); } private Reservation makeReservation(final LocalDateTime startTime, final LocalDateTime endTime, final Space space) { return Reservation.builder() .id(3L) - .startTime(startTime) - .endTime(endTime) + .reservationTime( + ReservationTime.of( + startTime, + endTime)) .password(reservationCreateUpdateWithPasswordRequest.getPassword()) .userName(reservationCreateUpdateWithPasswordRequest.getName()) .description(reservationCreateUpdateWithPasswordRequest.getDescription()) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/service/ManagerReservationServiceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/service/ManagerReservationServiceTest.java index 831fda344..8aef9d587 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/service/ManagerReservationServiceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/service/ManagerReservationServiceTest.java @@ -80,8 +80,9 @@ void setUp() { luther = new Map(1L, LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -99,8 +100,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -120,8 +122,10 @@ void setUp() { beAmZeroOne = Reservation.builder() .id(1L) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -130,8 +134,10 @@ void setUp() { bePmOneTwo = Reservation.builder() .id(2L) - .startTime(BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_PM_ONE_TWO_START_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_PM_ONE_TWO_END_TIME_KST.withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_PM_ONE_TWO_DESCRIPTION) .userName(BE_PM_ONE_TWO_USERNAME) .password(BE_PM_ONE_TWO_PW) @@ -180,8 +186,10 @@ void savePastReservation() { //given Reservation pastReservation = Reservation.builder() .id(1L) - .startTime(BE_AM_TEN_ELEVEN_START_TIME_KST.minusDays(5).withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) - .endTime(BE_AM_TEN_ELEVEN_END_TIME_KST.minusDays(5).withZoneSameInstant(UTC.toZoneId()).toLocalDateTime()) + .reservationTime( + ReservationTime.of( + BE_AM_TEN_ELEVEN_START_TIME_KST.minusDays(5).withZoneSameInstant(UTC.toZoneId()).toLocalDateTime(), + BE_AM_TEN_ELEVEN_END_TIME_KST.minusDays(5).withZoneSameInstant(UTC.toZoneId()).toLocalDateTime())) .description(BE_AM_TEN_ELEVEN_DESCRIPTION) .userName(BE_AM_TEN_ELEVEN_USERNAME) .password(BE_AM_TEN_ELEVEN_PW) @@ -303,7 +311,7 @@ void saveEndTimeBeforeNow() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, managerReservationStrategy)) - .isInstanceOf(ImpossibleEndTimeException.class); + .isInstanceOf(ImpossibleStartEndTimeException.class); } @Test @@ -331,7 +339,7 @@ void saveStartTimeEqualsEndTime() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, managerReservationStrategy)) - .isInstanceOf(ImpossibleEndTimeException.class); + .isInstanceOf(ImpossibleStartEndTimeException.class); } @Test @@ -359,7 +367,7 @@ void saveStartTimeDateNotEqualsEndTimeDate() { assertThatThrownBy(() -> reservationService.saveReservation( reservationCreateDto, managerReservationStrategy)) - .isInstanceOf(NonMatchingStartAndEndDateException.class); + .isInstanceOf(NonMatchingStartEndDateException.class); } @ParameterizedTest @@ -398,9 +406,8 @@ void saveAvailabilityException(int startMinute, int endMinute) { //given, when given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(List.of(makeReservation( reservationCreateUpdateWithPasswordRequest.localStartDateTime().minusMinutes(startMinute), @@ -426,11 +433,12 @@ void saveAvailabilityException(int startMinute, int endMinute) { void saveReservationUnable() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(false) .enabledDayOfWeek(null) .build(); @@ -468,11 +476,12 @@ void saveReservationUnable() { void saveIllegalDayOfWeek() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(true) .enabledDayOfWeek(THE_DAY_AFTER_TOMORROW.plusDays(1L).getDayOfWeek().name()) .build(); @@ -511,7 +520,7 @@ void saveSameThresholdTime(int duration) { //given, when given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndDateBetween( anyList(), any(LocalDate.class), any(LocalDate.class))) @@ -542,7 +551,7 @@ void saveSameThresholdTime(int duration) { } @ParameterizedTest - @CsvSource({"1,61", "10,55", "5,65", "20,89"}) + @CsvSource({"5,60", "10,55", "5,65", "20,85"}) @DisplayName("예약 생성/수정 요청 시, space setting의 reservationTimeUnit이 일치하지 않으면 예외가 발생한다.") void saveReservationTimeUnitException(int additionalStartMinute, int additionalEndMinute) { //given @@ -732,9 +741,8 @@ void findReservations() { given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(foundReservations); @@ -829,7 +837,7 @@ void findEmptyReservations() { .willReturn(Optional.of(luther)); given(maps.existsById(anyLong())) .willReturn(true); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndDateBetween( anyList(), any(LocalDate.class), any(LocalDate.class))) @@ -887,9 +895,8 @@ void findAllReservation() { given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(foundReservations); @@ -915,7 +922,7 @@ void findAllReservationsNotOwner() { .willReturn(Optional.of(sakjung)); given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndDateBetween( anyList(), any(LocalDate.class), any(LocalDate.class))) @@ -942,7 +949,7 @@ void findReservationsNotOwner() { .willReturn(Optional.of(sakjung)); given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndDateBetween( anyList(), any(LocalDate.class), any(LocalDate.class))) @@ -1130,7 +1137,7 @@ void updateInvalidEndTimeException(int endTime) { assertThatThrownBy(() -> reservationService.updateReservation( reservationUpdateDto, managerReservationStrategy)) - .isInstanceOf(ImpossibleEndTimeException.class); + .isInstanceOf(ImpossibleStartEndTimeException.class); } @Test @@ -1160,7 +1167,7 @@ void updateInvalidDateException() { assertThatThrownBy(() -> reservationService.updateReservation( reservationUpdateDto, managerReservationStrategy)) - .isInstanceOf(NonMatchingStartAndEndDateException.class); + .isInstanceOf(NonMatchingStartEndDateException.class); } @ParameterizedTest @@ -1173,9 +1180,8 @@ void updateImpossibleTimeException(int startTime, int endTime) { .willReturn(Optional.of(luther)); given(reservations.findById(anyLong())) .willReturn(Optional.of(reservation)); - given(reservations.findAllBySpaceIdInAndDateGreaterThanEqualAndDateLessThanEqual( + given(reservations.findAllBySpaceIdInAndReservationTimeDate( anyList(), - any(LocalDate.class), any(LocalDate.class))) .willReturn(Arrays.asList( beAmZeroOne, @@ -1241,11 +1247,12 @@ void updateInvalidTimeSetting(int startTime, int endTime) { void updateReservationUnable() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(false) .enabledDayOfWeek(null) .build(); @@ -1287,11 +1294,12 @@ void updateReservationUnable() { void updateIllegalDayOfWeek() { // given, when Setting setting = Setting.builder() - .availableStartTime(LocalTime.of(0, 0)) - .availableEndTime(LocalTime.of(18, 0)) - .reservationTimeUnit(10) - .reservationMinimumTimeUnit(10) - .reservationMaximumTimeUnit(120) + .availableTimeSlot(TimeSlot.of( + LocalTime.of(0, 0), + LocalTime.of(18, 0))) + .reservationTimeUnit(TimeUnit.from(10)) + .reservationMinimumTimeUnit(TimeUnit.from(10)) + .reservationMaximumTimeUnit(TimeUnit.from(120)) .reservationEnable(true) .enabledDayOfWeek(THE_DAY_AFTER_TOMORROW.plusDays(1L).getDayOfWeek().name()) .build(); @@ -1411,8 +1419,10 @@ void deleteReservationException() { private Reservation makeReservation(final LocalDateTime startTime, final LocalDateTime endTime, final Space space) { return Reservation.builder() .id(3L) - .startTime(startTime) - .endTime(endTime) + .reservationTime( + ReservationTime.of( + startTime, + endTime)) .password(reservationCreateUpdateWithPasswordRequest.getPassword()) .userName(reservationCreateUpdateWithPasswordRequest.getName()) .description(reservationCreateUpdateWithPasswordRequest.getDescription()) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/service/MapServiceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/service/MapServiceTest.java index ad9c2cf02..6b4386e5b 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/service/MapServiceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/service/MapServiceTest.java @@ -1,10 +1,6 @@ package com.woowacourse.zzimkkong.service; -import com.woowacourse.zzimkkong.Constants; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Member; -import com.woowacourse.zzimkkong.domain.Setting; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.dto.map.MapCreateResponse; import com.woowacourse.zzimkkong.dto.map.MapCreateUpdateRequest; import com.woowacourse.zzimkkong.dto.map.MapFindAllResponse; @@ -50,8 +46,9 @@ void setUp() { lutherId = luther.getId(); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -69,8 +66,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -174,7 +172,7 @@ void delete() { //given given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.existsBySpaceIdAndEndTimeAfter(anyLong(), any(LocalDateTime.class))) + given(reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(anyLong(), any(LocalDateTime.class))) .willReturn(false); //when, then @@ -189,7 +187,7 @@ void deleteExistReservationException() { .willReturn(Optional.of(pobi)); given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.existsBySpaceIdAndEndTimeAfter(anyLong(), any(LocalDateTime.class))) + given(reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(anyLong(), any(LocalDateTime.class))) .willReturn(true); //when, then diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/service/MemberServiceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/service/MemberServiceTest.java index 9fe69f122..6deb9065c 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/service/MemberServiceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/service/MemberServiceTest.java @@ -16,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; +import java.time.LocalDateTime; import java.util.Optional; import static com.woowacourse.zzimkkong.Constants.*; @@ -146,7 +147,7 @@ void deleteMember() { Member pobi = new Member(EMAIL, PW, ORGANIZATION); given(members.findByEmail(anyString())) .willReturn(Optional.of(pobi)); - given(reservations.existsReservationsByMemberFromToday(any(Member.class))) + given(reservations.existsByMemberAndEndTimeAfter(any(Member.class), any(LocalDateTime.class))) .willReturn(false); // when, then @@ -161,7 +162,7 @@ void deleteMemberFailWhenAnyReservationsExists() { Member pobi = new Member(EMAIL, PW, ORGANIZATION); given(members.findByEmail(anyString())) .willReturn(Optional.of(pobi)); - given(reservations.existsReservationsByMemberFromToday(any(Member.class))) + given(reservations.existsByMemberAndEndTimeAfter(any(Member.class), any(LocalDateTime.class))) .willReturn(true); // when, then diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/service/PresetServiceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/service/PresetServiceTest.java index 45c23f99e..a15bf0a08 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/service/PresetServiceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/service/PresetServiceTest.java @@ -3,6 +3,7 @@ import com.woowacourse.zzimkkong.domain.Member; import com.woowacourse.zzimkkong.domain.Preset; import com.woowacourse.zzimkkong.domain.Setting; +import com.woowacourse.zzimkkong.domain.TimeSlot; import com.woowacourse.zzimkkong.dto.member.PresetCreateRequest; import com.woowacourse.zzimkkong.dto.member.PresetCreateResponse; import com.woowacourse.zzimkkong.dto.member.PresetFindAllResponse; @@ -38,16 +39,17 @@ class PresetServiceTest extends ServiceTest { private final SettingsRequest settingsRequest = new SettingsRequest( BE_AVAILABLE_START_TIME, BE_AVAILABLE_END_TIME, - BE_RESERVATION_TIME_UNIT, - BE_RESERVATION_MINIMUM_TIME_UNIT, - BE_RESERVATION_MAXIMUM_TIME_UNIT, + BE_RESERVATION_TIME_UNIT.getMinutes(), + BE_RESERVATION_MINIMUM_TIME_UNIT.getMinutes(), + BE_RESERVATION_MAXIMUM_TIME_UNIT.getMinutes(), BE_RESERVATION_ENABLE, EnabledDayOfWeekDto.from(BE_ENABLED_DAY_OF_WEEK) ); private final Setting setting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) diff --git a/backend/src/test/java/com/woowacourse/zzimkkong/service/SpaceServiceTest.java b/backend/src/test/java/com/woowacourse/zzimkkong/service/SpaceServiceTest.java index 603607c99..acc938a33 100644 --- a/backend/src/test/java/com/woowacourse/zzimkkong/service/SpaceServiceTest.java +++ b/backend/src/test/java/com/woowacourse/zzimkkong/service/SpaceServiceTest.java @@ -1,9 +1,6 @@ package com.woowacourse.zzimkkong.service; -import com.woowacourse.zzimkkong.domain.Map; -import com.woowacourse.zzimkkong.domain.Member; -import com.woowacourse.zzimkkong.domain.Setting; -import com.woowacourse.zzimkkong.domain.Space; +import com.woowacourse.zzimkkong.domain.*; import com.woowacourse.zzimkkong.dto.member.LoginEmailDto; import com.woowacourse.zzimkkong.dto.space.*; import com.woowacourse.zzimkkong.exception.authorization.NoAuthorityOnMapException; @@ -34,9 +31,9 @@ class SpaceServiceTest extends ServiceTest { private final SettingsRequest settingsRequest = new SettingsRequest( BE_AVAILABLE_START_TIME, BE_AVAILABLE_END_TIME, - BE_RESERVATION_TIME_UNIT, - BE_RESERVATION_MINIMUM_TIME_UNIT, - BE_RESERVATION_MAXIMUM_TIME_UNIT, + BE_RESERVATION_TIME_UNIT.getMinutes(), + BE_RESERVATION_MINIMUM_TIME_UNIT.getMinutes(), + BE_RESERVATION_MAXIMUM_TIME_UNIT.getMinutes(), BE_RESERVATION_ENABLE, EnabledDayOfWeekDto.from(BE_ENABLED_DAY_OF_WEEK) ); @@ -81,8 +78,9 @@ void setUp() { luther = new Map(1L, LUTHER_NAME, MAP_DRAWING_DATA, MAP_SVG, pobi); Setting beSetting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -100,8 +98,9 @@ void setUp() { .build(); Setting feSetting = Setting.builder() - .availableStartTime(FE_AVAILABLE_START_TIME) - .availableEndTime(FE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + FE_AVAILABLE_START_TIME, + FE_AVAILABLE_END_TIME)) .reservationTimeUnit(FE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(FE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(FE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -130,8 +129,9 @@ void setUp() { void save() { // given Setting setting = Setting.builder() - .availableStartTime(BE_AVAILABLE_START_TIME) - .availableEndTime(BE_AVAILABLE_END_TIME) + .availableTimeSlot(TimeSlot.of( + BE_AVAILABLE_START_TIME, + BE_AVAILABLE_END_TIME)) .reservationTimeUnit(BE_RESERVATION_TIME_UNIT) .reservationMinimumTimeUnit(BE_RESERVATION_MINIMUM_TIME_UNIT) .reservationMaximumTimeUnit(BE_RESERVATION_MAXIMUM_TIME_UNIT) @@ -283,7 +283,7 @@ void update() { updateSpaceCreateUpdateRequest, pobiEmail)); - assertThat(be.getReservationTimeUnit()).isEqualTo(settingsRequest.getReservationTimeUnit()); + assertThat(be.getReservationTimeUnitAsInt()).isEqualTo(settingsRequest.getReservationTimeUnit()); assertThat(be.getEnabledDayOfWeek()).isEqualTo(settingsRequest.enabledDayOfWeekAsString()); } @@ -309,7 +309,7 @@ void deleteReservation() { //given given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.existsBySpaceIdAndEndTimeAfter(anyLong(), any(LocalDateTime.class))) + given(reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(anyLong(), any(LocalDateTime.class))) .willReturn(false); SpaceDeleteRequest spaceDeleteRequest = new SpaceDeleteRequest(MAP_SVG); @@ -349,7 +349,7 @@ void deleteReservationExistException() { //given given(maps.findByIdFetch(anyLong())) .willReturn(Optional.of(luther)); - given(reservations.existsBySpaceIdAndEndTimeAfter(anyLong(), any(LocalDateTime.class))) + given(reservations.existsBySpaceIdAndReservationTimeEndTimeAfter(anyLong(), any(LocalDateTime.class))) .willReturn(true); SpaceDeleteRequest spaceDeleteRequest = new SpaceDeleteRequest(MAP_SVG); From 02a850b0c2300e90cfde21ab2637d15e2872e945 Mon Sep 17 00:00:00 2001 From: Shim MunSeong Date: Tue, 7 Jun 2022 20:25:15 +0900 Subject: [PATCH 06/22] =?UTF-8?q?[FE]=20=EB=A7=B5=EB=B3=84=20=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=EC=82=AC=ED=95=AD=EC=9D=84=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8A=94=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20(#826)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: `ManagerMain`에서 여러 종류의 모달을 표시할 수 있도록 로직 변경 * feat: `TextArea` 컴포넌트 구현 * feat: `TextArea` 컴포넌트에 value state 지정 없이도 현재 텍스트 길이를 표시하도록 수정 * feat: 맵별 공지사항 추가 UI 구현 * feat: 관리자 페이지에서 공지사항을 설정할 수 있는 기능 구현 및 API 연동 * feat: 맵 예약 페이지에서 공지사항을 보여주는 기능 구현 * feat: 공지사항이 설정되어 있지 않을 때 공지사항 블록이 렌더되지 않도록 수정 --- frontend/src/__mocks__/mockData.ts | 1 + frontend/src/api/managerMap.ts | 8 ++ frontend/src/assets/svg/notice.svg | 3 + .../components/DateInput/DateInput.styles.ts | 8 +- .../src/components/DateInput/DateInput.tsx | 5 +- .../components/TextArea/TextArea.stories.tsx | 23 +++++ .../components/TextArea/TextArea.styles.ts | 54 +++++++++++ frontend/src/components/TextArea/TextArea.tsx | 30 ++++++ frontend/src/constants/message.ts | 3 + frontend/src/hooks/useInput.ts | 8 +- .../src/pages/GuestMap/GuestMap.styles.ts | 47 ++++++++- frontend/src/pages/GuestMap/GuestMap.tsx | 16 +++- .../pages/ManagerMain/ManagerMain.styles.ts | 2 +- .../src/pages/ManagerMain/ManagerMain.tsx | 95 +++++++++++++++---- frontend/src/types/common.ts | 1 + 15 files changed, 275 insertions(+), 29 deletions(-) create mode 100644 frontend/src/assets/svg/notice.svg create mode 100644 frontend/src/components/TextArea/TextArea.stories.tsx create mode 100644 frontend/src/components/TextArea/TextArea.styles.ts create mode 100644 frontend/src/components/TextArea/TextArea.tsx diff --git a/frontend/src/__mocks__/mockData.ts b/frontend/src/__mocks__/mockData.ts index c440be244..908ceb68c 100644 --- a/frontend/src/__mocks__/mockData.ts +++ b/frontend/src/__mocks__/mockData.ts @@ -32,6 +32,7 @@ export const guestMaps: GuestMaps = { '{"width":800,"height":600,"mapElements":[{"id":2,"type":"rect","stroke":"#333333","points":["210,90","650,230"]},{"id":3,"type":"rect","stroke":"#333333","width":440,"height":140,"x":210,"y":90,"points":["210, 90","650, 230"]}]}', thumbnail: '', sharingMapId: 'JMTGR', + notice: null, }, }; diff --git a/frontend/src/api/managerMap.ts b/frontend/src/api/managerMap.ts index a6f3243c1..0e150cf77 100644 --- a/frontend/src/api/managerMap.ts +++ b/frontend/src/api/managerMap.ts @@ -37,6 +37,11 @@ interface PostSlackWebhookURLParams { slackUrl: string; } +interface PostNotice { + mapId: number; + notice: string; +} + export const queryManagerMaps: QueryFunction> = () => api.get('/managers/maps'); @@ -83,3 +88,6 @@ export const postSlackWebhookUrl = ({ slackUrl, }: PostSlackWebhookURLParams): Promise> => api.post(`/managers/maps/${mapId}/slack`, { slackUrl }); + +export const postNotice = ({ mapId, notice }: PostNotice): Promise> => + api.post(`/managers/maps/${mapId}/notice`, { notice }); diff --git a/frontend/src/assets/svg/notice.svg b/frontend/src/assets/svg/notice.svg new file mode 100644 index 000000000..31314ec4b --- /dev/null +++ b/frontend/src/assets/svg/notice.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/src/components/DateInput/DateInput.styles.ts b/frontend/src/components/DateInput/DateInput.styles.ts index 14a063755..6668f65a9 100644 --- a/frontend/src/components/DateInput/DateInput.styles.ts +++ b/frontend/src/components/DateInput/DateInput.styles.ts @@ -3,12 +3,16 @@ import { ReactComponent as ArrowLeftIcon } from 'assets/svg/arrow-left.svg'; import { ReactComponent as ArrowRightIcon } from 'assets/svg/arrow-right.svg'; import { ReactComponent as CalendarIcon } from 'assets/svg/calendar.svg'; -export const Container = styled.div` +interface ContainerProps { + hasBackground: boolean; +} + +export const Container = styled.div` display: flex; justify-content: space-between; align-items: center; border-radius: 0.25rem; - background-color: ${({ theme }) => theme.gray[100]}; + background-color: ${({ hasBackground, theme }) => (hasBackground ? theme.gray[100] : 'none')}; padding: 0.75rem 0.25rem; `; diff --git a/frontend/src/components/DateInput/DateInput.tsx b/frontend/src/components/DateInput/DateInput.tsx index ce9c81f1a..a1e2c5481 100644 --- a/frontend/src/components/DateInput/DateInput.tsx +++ b/frontend/src/components/DateInput/DateInput.tsx @@ -6,10 +6,11 @@ import * as Styled from './DateInput.styles'; export interface Props extends Omit, 'type' | 'value'> { date: Dayjs; + hasBackground?: boolean; setDate: Dispatch>; } -const DateInput = ({ date, setDate, ...props }: Props): JSX.Element => { +const DateInput = ({ date, hasBackground = true, setDate, ...props }: Props): JSX.Element => { const onChange: ChangeEventHandler = (event) => { setDate(dayjs(event.target.value).tz()); }; @@ -23,7 +24,7 @@ const DateInput = ({ date, setDate, ...props }: Props): JSX.Element => { }; return ( - + diff --git a/frontend/src/components/TextArea/TextArea.stories.tsx b/frontend/src/components/TextArea/TextArea.stories.tsx new file mode 100644 index 000000000..9a0327457 --- /dev/null +++ b/frontend/src/components/TextArea/TextArea.stories.tsx @@ -0,0 +1,23 @@ +import { Story } from '@storybook/react'; +import React, { useState } from 'react'; +import TextArea, { Props } from './TextArea'; + +export default { + title: 'shared/TextArea', + component: TextArea, +}; + +const Template: Story = (args) => { + const [value, setValue] = useState(''); + + const handleChange = (event: React.ChangeEvent) => + setValue(event.target.value); + + return