Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] - 여행 계획, 여행기 하위 도메인 조회 명세 변경 #244

Merged
merged 8 commits into from
Aug 7, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

@Builder
public record TraveloguePositionResponse(
@Schema(description = "여행기 장소 상세 ID", example = "1")
Long id,
@Schema(description = "여행기 장소 위도", example = "37.5175896")
String lat,
@Schema(description = "여행기 장소 설명", example = "127.0867236")
Expand All @@ -14,6 +16,7 @@ public record TraveloguePositionResponse(

public static TraveloguePositionResponse from(TraveloguePlace place) {
return TraveloguePositionResponse.builder()
.id(place.getPlace().getId())
.lat(place.getLatitude())
.lng(place.getLongitude())
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
package kr.touroot.travelogue.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.List;
import kr.touroot.travelogue.domain.Travelogue;
import lombok.Builder;

@Builder
public record TravelogueResponse(
@Schema(description = "여행기 ID", example = "1")
@NotNull(message = "ID는 비어있을 수 없습니다.")
Long id,
@Schema(description = "여행기 제목", example = "서울 강남 여행기")
@NotNull(message = "여행기 제목은 비어있을 수 없습니다.")
String title,
@Schema(description = "여행기 썸네일 링크", example = "https://썸네일.png")
@NotNull(message = "여행기 썸네일 링크는 비어있을 수 없습니다.")
String thumbnail,
@Schema(description = "작성 날짜")
LocalDate createdAt,
@Schema(description = "여행기 일자 목록")
@NotNull(message = "여행기 일자 목록은 비어있을 수 없습니다.")
@Valid
List<TravelogueDayResponse> days
) {

public static TravelogueResponse of(Travelogue travelogue, List<TravelogueDayResponse> days) {
return TravelogueResponse.builder()
.id(travelogue.getId())
.createdAt(travelogue.getCreatedAt().toLocalDate())
.title(travelogue.getTitle())
.thumbnail(travelogue.getThumbnail())
.days(days)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,8 @@ private void validateTitleLength(String title) {
}
}

public void validateStartDate() {
if (startDate.isBefore(LocalDate.now())) {
throw new BadRequestException("지난 날짜에 대한 계획은 작성할 수 없습니다.");
}
}

public boolean isValidStartDate() {
return startDate.isAfter(LocalDate.now());
public boolean isStartDateBefore(LocalDate date) {
return startDate.isBefore(date);
Comment on lines -86 to +87
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제어할 수 없는 영역을 도메인 외부로 빼신 부분 정말 좋네요!!

}

public boolean isAuthor(Member member) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package kr.touroot.travelplan.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import kr.touroot.travelplan.domain.TravelPlanDay;

import java.time.LocalDate;
import java.util.List;
import kr.touroot.travelplan.domain.TravelPlanDay;
import lombok.Builder;

@Builder
public record TravelPlanDayResponse(
@Schema(description = "여행 날짜 Id") Long id,
@Schema(description = "여행 일자") LocalDate date,
@Schema(description = "여행 장소별 정보") List<TravelPlanPlaceResponse> places
) {
Expand All @@ -18,6 +18,7 @@ public static TravelPlanDayResponse of(
List<TravelPlanPlaceResponse> places
) {
return TravelPlanDayResponse.builder()
.id(planDay.getId())
.date(planDay.getCurrentDate())
.places(places)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

@Builder
public record TravelPlanPlaceResponse(
@Schema(description = "여행 장소 Id", example = "1") Long id,
@Schema(description = "여행 장소 이름", example = "잠실한강공원") String placeName,
@Schema(description = "여행 장소 위치") TravelPlanPositionResponse position,
@Schema(description = "여행 장소 설명", example = "신나는 여행 장소") String description
Expand All @@ -17,6 +18,7 @@ public static TravelPlanPlaceResponse from(TravelPlanPlace planPlace) {
TravelPlanPositionResponse locationResponse = TravelPlanPositionResponse.from(place);

return TravelPlanPlaceResponse.builder()
.id(planPlace.getId())
.placeName(place.getName())
.position(locationResponse)
.description(planPlace.getDescription())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

@Builder
public record TravelPlanPositionResponse(
@Schema(description = "여행 게획 장소 상세 Id", example = "1") Long id,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사소한 오타를 발견해버렸습니다 😢

@Schema(description = "여행 장소 위도", example = "37.5175896") String lat,
@Schema(description = "여행 계획 경도", example = "127.0867236") String lng
) {

public static TravelPlanPositionResponse from(Place place) {
return TravelPlanPositionResponse.builder()
.id(place.getId())
.lat(place.getLatitude())
.lng(place.getLongitude())
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.touroot.travelplan.service;

import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
Expand Down Expand Up @@ -43,16 +44,16 @@ public class TravelPlanService {
public TravelPlanCreateResponse createTravelPlan(TravelPlanCreateRequest request, MemberAuth memberAuth) {
Member author = getMemberByMemberAuth(memberAuth);
TravelPlan travelPlan = request.toTravelPlan(author, UUID.randomUUID());
validStartDate(travelPlan);
validateTravelPlan(travelPlan);

TravelPlan savedTravelPlan = travelPlanRepository.save(travelPlan);
createPlanDay(request.days(), savedTravelPlan);

return new TravelPlanCreateResponse(savedTravelPlan.getId());
}

private void validStartDate(TravelPlan travelPlan) {
if (!travelPlan.isValidStartDate()) {
private void validateTravelPlan(TravelPlan travelPlan) {
if (travelPlan.isStartDateBefore(LocalDate.now())) {
throw new BadRequestException("지난 날짜에 대한 계획은 작성할 수 없습니다.");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.touroot.travelogue.fixture;

import java.time.LocalDate;
import java.util.List;
import kr.touroot.travelogue.dto.response.TravelogueDayResponse;
import kr.touroot.travelogue.dto.response.TraveloguePlaceResponse;
Expand All @@ -19,6 +20,7 @@ public static TravelogueResponse getTravelogueResponse() {
return TravelogueResponse.builder()
.id(1L)
.title("제주에 하영 옵서")
.createdAt(LocalDate.now())
.thumbnail("https://dev.touroot.kr/temporary/jeju_thumbnail.png")
.days(getTravelogueDayResponses())
.build();
Expand All @@ -28,6 +30,7 @@ public static Page<TravelogueResponse> getTravelogueResponses() {
return new PageImpl<>(List.of(TravelogueResponse.builder()
.id(1L)
.title("제주에 하영 옵서")
.createdAt(LocalDate.now())
.thumbnail("https://dev.touroot.kr/temporary/jeju_thumbnail.png")
.days(getTravelogueDayResponses())
.build()));
Expand All @@ -54,6 +57,7 @@ public static List<TraveloguePlaceResponse> getTraveloguePlaceResponses() {

public static TraveloguePositionResponse getTraveloguePositionResponse() {
return TraveloguePositionResponse.builder()
.id(1L)
.lat("34.54343")
.lng("126.66977")
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;

import java.time.LocalDate;
import java.util.UUID;
Expand Down Expand Up @@ -74,27 +75,30 @@ void createTravelPlanWithInvalidLengthTitle() {
.hasMessage("여행 계획은 1자 이상, 20자 이하여야 합니다");
}

@DisplayName("여행 계획은 지난 날짜를 검증할 시 예외가 발생한다.")
@DisplayName("여행 계획의 시작날짜와 특정 날짜를 비교할 수 있다.")
@Test
void validateStartDate() {
TravelPlan travelPlan = new TravelPlan(VALID_TITLE, LocalDate.MIN, VALID_UUID, VALID_AUTHOR);
// given
LocalDate yesterday = LocalDate.now().minusDays(1);
LocalDate today = LocalDate.now();
LocalDate tommorow = LocalDate.now().plusDays(1);

assertThatCode(travelPlan::validateStartDate)
.isInstanceOf(BadRequestException.class)
.hasMessage("지난 날짜에 대한 계획은 작성할 수 없습니다.");
// when
boolean actual = travelPlan.isValidStartDate();
Member author = new Member(1L, 1L, null, null, "tester", "http://url.com", LoginType.KAKAO);
TravelPlan todayPlan = new TravelPlan("test", today, VALID_UUID, author);

// then
assertThat(actual).isFalse();
// when & then
assertAll(
() -> assertThat(todayPlan.isStartDateBefore(tommorow)).isTrue(),
() -> assertThat(todayPlan.isStartDateBefore(yesterday)).isFalse()
);
}

@DisplayName("여행 계획은 작성자가 아닌 사용자가 검증을 시도하면 예외가 발생한다.")
@Test
void validateAuthor() {
// given
Member author = new Member(1L, 1L, null, null, "tester", "http://url.com", LoginType.KAKAO);
TravelPlan travelPlan = new TravelPlan("test", LocalDate.MIN, VALID_UUID, author);
TravelPlan travelPlan = new TravelPlan("test", LocalDate.now(), VALID_UUID, author);
Member notAuthor = new Member(2L, 2L, null, null, "tester2", "http://url.com", LoginType.KAKAO);

// when
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kr.touroot.travelplan.service;

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

import java.time.LocalDate;
Expand Down Expand Up @@ -108,6 +109,28 @@ void createTravelPlanWithInvalidStartDate() {
.hasMessage("지난 날짜에 대한 계획은 작성할 수 없습니다.");
}

@DisplayName("당일에 시작하는 여행 계획을 생성할 수 있다")
@Test
void createTravelPlanStartsAtToday() {
// given
PlanPositionCreateRequest locationRequest = new PlanPositionCreateRequest("37.5175896", "127.0867236");
PlanPlaceCreateRequest planPlaceCreateRequest = PlanPlaceCreateRequest.builder()
.placeName("잠실한강공원")
.description("신나는 여행 장소")
.position(locationRequest)
.build();
PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(List.of(planPlaceCreateRequest));
TravelPlanCreateRequest request = TravelPlanCreateRequest.builder()
.title("신나는 한강 여행")
.startDate(LocalDate.now())
.days(List.of(planDayCreateRequest))
.build();

// when & then=
assertThatCode(() -> travelPlanService.createTravelPlan(request, memberAuth))
.doesNotThrowAnyException();
}

@DisplayName("여행 계획 서비스는 여행 계획 조회 시 상세 정보를 반환한다.")
@Test
void readTravelPlan() {
Expand Down
Loading