-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: TravelPlan 관련 Entity 추가 * feat: 여행기 작성 API 구현 * feat: swagger 설명 추가 * feat: 여행 계획 작성 시 지난 날짜에 대한 검증 추가 * refactor: TravelPlanService method 분리 * refactor: PlanPlaceRequest에 toPlace 추가 * style: TravelPlanControllere 개행 정리
- Loading branch information
Showing
17 changed files
with
376 additions
and
5 deletions.
There are no files selected for viewing
8 changes: 8 additions & 0 deletions
8
backend/src/main/java/woowacourse/touroot/global/exception/BadRequestException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package woowacourse.touroot.global.exception; | ||
|
||
public class BadRequestException extends RuntimeException { | ||
|
||
public BadRequestException(String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
backend/src/main/java/woowacourse/touroot/travelplan/controller/TravelPlanController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package woowacourse.touroot.travelplan.controller; | ||
|
||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import woowacourse.touroot.travelplan.dto.TravelPlanCreateRequest; | ||
import woowacourse.touroot.travelplan.dto.TravelPlanCreateResponse; | ||
import woowacourse.touroot.travelplan.service.TravelPlanService; | ||
|
||
@Tag(name = "여행기") | ||
@RequiredArgsConstructor | ||
@RestController | ||
@RequestMapping("/api/v1/travel-plans") | ||
public class TravelPlanController { | ||
|
||
private final TravelPlanService travelPlanService; | ||
|
||
@Operation(summary = "여행기 생성") | ||
@PostMapping | ||
public ResponseEntity<TravelPlanCreateResponse> createTravelPlan(@Valid @RequestBody TravelPlanCreateRequest request) { | ||
TravelPlanCreateResponse data = travelPlanService.createTravelPlan(request); | ||
return ResponseEntity.ok() | ||
.body(data); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
backend/src/main/java/woowacourse/touroot/travelplan/domain/TravelPlan.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package woowacourse.touroot.travelplan.domain; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import woowacourse.touroot.entity.BaseEntity; | ||
import woowacourse.touroot.global.exception.BadRequestException; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
|
||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
@Entity | ||
public class TravelPlan extends BaseEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(nullable = false) | ||
private String title; | ||
|
||
@Column(nullable = false) | ||
private LocalDate startDate; | ||
|
||
@OneToMany(mappedBy = "plan") | ||
private List<TravelPlanDay> days; | ||
|
||
public TravelPlan(String title, LocalDate startDate) { | ||
this(null, title, startDate, null); | ||
} | ||
|
||
public void validateStartDate() { | ||
if (startDate.isBefore(LocalDate.now())) { | ||
throw new BadRequestException("지난 날짜에 대한 계획은 작성할 수 없습니다."); | ||
} | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
backend/src/main/java/woowacourse/touroot/travelplan/domain/TravelPlanDay.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package woowacourse.touroot.travelplan.domain; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import woowacourse.touroot.entity.BaseEntity; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
@Entity | ||
public class TravelPlanDay extends BaseEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(name = "plan_day_order", nullable = false) | ||
Integer order; | ||
|
||
@JoinColumn(name = "plan_id", nullable = false) | ||
@ManyToOne(fetch = FetchType.LAZY) | ||
private TravelPlan plan; | ||
|
||
@OneToMany(mappedBy = "day") | ||
private List<TravelPlanPlace> places; | ||
|
||
public TravelPlanDay(int order, TravelPlan plan) { | ||
this(null, order, plan, null); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
backend/src/main/java/woowacourse/touroot/travelplan/domain/TravelPlanPlace.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package woowacourse.touroot.travelplan.domain; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import woowacourse.touroot.entity.BaseEntity; | ||
import woowacourse.touroot.place.domain.Place; | ||
|
||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
@Entity | ||
public class TravelPlanPlace extends BaseEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
private String description; | ||
|
||
@Column(name = "plan_place_order", nullable = false) | ||
private Integer order; | ||
|
||
@JoinColumn(name = "plan_day_id", nullable = false) | ||
@ManyToOne(fetch = FetchType.LAZY) | ||
private TravelPlanDay day; | ||
|
||
@JoinColumn(name = "place_id", nullable = false) | ||
@ManyToOne(fetch = FetchType.LAZY) | ||
private Place place; | ||
|
||
public TravelPlanPlace(String description, int order, TravelPlanDay day, Place place) { | ||
this(null, description, order, day, place); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
backend/src/main/java/woowacourse/touroot/travelplan/dto/PlanDayCreateRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package woowacourse.touroot.travelplan.dto; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import jakarta.validation.constraints.Min; | ||
import jakarta.validation.constraints.NotNull; | ||
import woowacourse.touroot.travelplan.domain.TravelPlan; | ||
import woowacourse.touroot.travelplan.domain.TravelPlanDay; | ||
|
||
import java.util.List; | ||
|
||
public record PlanDayCreateRequest( | ||
@Schema(description = "여행 계획 날짜", example = "1") | ||
@NotNull(message = "날짜는 비어있을 수 없습니다.") | ||
@Min(value = 0, message = "날짜는 1 이상이어야 합니다.") | ||
int day, | ||
@Schema(description = "여행 장소 정보") | ||
@NotNull(message = "여행 장소 정보는 비어있을 수 없습니다.") List<PlanPlaceCreateRequest> places | ||
) { | ||
|
||
public TravelPlanDay toPlanDay(TravelPlan plan) { | ||
return new TravelPlanDay(day, plan); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
backend/src/main/java/woowacourse/touroot/travelplan/dto/PlanLocationCreateRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package woowacourse.touroot.travelplan.dto; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import jakarta.validation.constraints.NotNull; | ||
|
||
public record PlanLocationCreateRequest( | ||
@Schema(description = "여행 장소 위도", example = "37.5175896") | ||
@NotNull(message = "위도는 비어있을 수 없습니다.") | ||
String lat, | ||
@Schema(description = "여행 장소 경도", example = "127.0867236") | ||
@NotNull(message = "경도는 비어있을 수 없습니다.") | ||
String lng | ||
) { | ||
} |
30 changes: 30 additions & 0 deletions
30
backend/src/main/java/woowacourse/touroot/travelplan/dto/PlanPlaceCreateRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package woowacourse.touroot.travelplan.dto; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import jakarta.validation.constraints.Min; | ||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.NotNull; | ||
import woowacourse.touroot.place.domain.Place; | ||
import woowacourse.touroot.travelplan.domain.TravelPlanDay; | ||
import woowacourse.touroot.travelplan.domain.TravelPlanPlace; | ||
|
||
public record PlanPlaceCreateRequest( | ||
@Schema(description = "여행 장소 이름", example = "신나는 여행 장소") | ||
@NotBlank(message = "장소명은 비어있을 수 없습니다.") String placeName, | ||
@Schema(description = "여행 장소 설명", example = "잠실한강공원") | ||
String description, | ||
@Schema(description = "여행 장소 순서", example = "1") | ||
@NotNull | ||
@Min(value = 0, message = "순서는 1 이상이어야 합니다.") | ||
int order, | ||
@NotNull PlanLocationCreateRequest location | ||
) { | ||
|
||
public TravelPlanPlace toPlanPlace(TravelPlanDay day, Place place) { | ||
return new TravelPlanPlace(description, order, day, place); | ||
} | ||
|
||
public Place toPlace() { | ||
return new Place(placeName, location.lat(), location.lng()); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
backend/src/main/java/woowacourse/touroot/travelplan/dto/TravelPlanCreateRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package woowacourse.touroot.travelplan.dto; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.NotNull; | ||
import woowacourse.touroot.travelplan.domain.TravelPlan; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
|
||
public record TravelPlanCreateRequest( | ||
@Schema(description = "여행 계획 제목", example = "신나는 잠실 한강 여행") | ||
@NotBlank(message = "여행 계획 제목은 비어있을 수 없습니다.") | ||
String title, | ||
@Schema(description = "여행 계획 시작일", example = "2024-11-16") | ||
@NotNull(message = "시작일은 비어있을 수 없습니다.") | ||
LocalDate startDate, | ||
@Schema(description = "여행 날짜 정보") | ||
@NotNull(message = "여행 날짜 정보는 비어있을 수 없습니다.") | ||
List<PlanDayCreateRequest> days | ||
) { | ||
|
||
public TravelPlan toTravelPlan() { | ||
return new TravelPlan(title, startDate); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
backend/src/main/java/woowacourse/touroot/travelplan/dto/TravelPlanCreateResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package woowacourse.touroot.travelplan.dto; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
|
||
public record TravelPlanCreateResponse( | ||
@Schema(description = "생성된 여행 계획 id") | ||
Long id | ||
) { | ||
} |
7 changes: 7 additions & 0 deletions
7
backend/src/main/java/woowacourse/touroot/travelplan/repository/TravelPlanDayRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package woowacourse.touroot.travelplan.repository; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import woowacourse.touroot.travelplan.domain.TravelPlanDay; | ||
|
||
public interface TravelPlanDayRepository extends JpaRepository<TravelPlanDay, Long> { | ||
} |
7 changes: 7 additions & 0 deletions
7
...nd/src/main/java/woowacourse/touroot/travelplan/repository/TravelPlanPlaceRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package woowacourse.touroot.travelplan.repository; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import woowacourse.touroot.travelplan.domain.TravelPlanPlace; | ||
|
||
public interface TravelPlanPlaceRepository extends JpaRepository<TravelPlanPlace, Long> { | ||
} |
7 changes: 7 additions & 0 deletions
7
backend/src/main/java/woowacourse/touroot/travelplan/repository/TravelPlanRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package woowacourse.touroot.travelplan.repository; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import woowacourse.touroot.travelplan.domain.TravelPlan; | ||
|
||
public interface TravelPlanRepository extends JpaRepository<TravelPlan, Long> { | ||
} |
61 changes: 61 additions & 0 deletions
61
backend/src/main/java/woowacourse/touroot/travelplan/service/TravelPlanService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package woowacourse.touroot.travelplan.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import woowacourse.touroot.place.domain.Place; | ||
import woowacourse.touroot.place.repository.PlaceRepository; | ||
import woowacourse.touroot.travelplan.domain.TravelPlan; | ||
import woowacourse.touroot.travelplan.domain.TravelPlanDay; | ||
import woowacourse.touroot.travelplan.dto.PlanDayCreateRequest; | ||
import woowacourse.touroot.travelplan.dto.PlanPlaceCreateRequest; | ||
import woowacourse.touroot.travelplan.dto.TravelPlanCreateRequest; | ||
import woowacourse.touroot.travelplan.dto.TravelPlanCreateResponse; | ||
import woowacourse.touroot.travelplan.repository.TravelPlanDayRepository; | ||
import woowacourse.touroot.travelplan.repository.TravelPlanPlaceRepository; | ||
import woowacourse.touroot.travelplan.repository.TravelPlanRepository; | ||
|
||
import java.util.List; | ||
|
||
@RequiredArgsConstructor | ||
@Service | ||
public class TravelPlanService { | ||
|
||
private final TravelPlanRepository travelPlanRepository; | ||
private final TravelPlanDayRepository travelPlanDayRepository; | ||
private final TravelPlanPlaceRepository travelPlanPlaceRepository; | ||
private final PlaceRepository placeRepository; | ||
|
||
@Transactional | ||
public TravelPlanCreateResponse createTravelPlan(TravelPlanCreateRequest request) { | ||
TravelPlan travelPlan = request.toTravelPlan(); | ||
travelPlan.validateStartDate(); | ||
|
||
TravelPlan savedTravelPlan = travelPlanRepository.save(travelPlan); | ||
createPlanDay(request, savedTravelPlan); | ||
|
||
return new TravelPlanCreateResponse(savedTravelPlan.getId()); | ||
} | ||
|
||
private void createPlanDay(TravelPlanCreateRequest request, TravelPlan savedTravelPlan) { | ||
for (PlanDayCreateRequest dayRequest : request.days()) { | ||
TravelPlanDay travelPlanDay = travelPlanDayRepository.save(dayRequest.toPlanDay(savedTravelPlan)); | ||
createPlanPlace(dayRequest.places(), travelPlanDay); | ||
} | ||
} | ||
|
||
private void createPlanPlace(List<PlanPlaceCreateRequest> request, TravelPlanDay travelPlanDay) { | ||
for (PlanPlaceCreateRequest planRequest : request) { | ||
Place place = getPlace(planRequest); | ||
travelPlanPlaceRepository.save(planRequest.toPlanPlace(travelPlanDay, place)); | ||
} | ||
} | ||
|
||
private Place getPlace(PlanPlaceCreateRequest planRequest) { | ||
return placeRepository.findByNameAndLatitudeAndLongitude( | ||
planRequest.placeName(), | ||
planRequest.location().lat(), | ||
planRequest.location().lng() | ||
).orElseGet(() -> placeRepository.save(planRequest.toPlace())); | ||
} | ||
} |
Oops, something went wrong.