Skip to content

Commit

Permalink
Merge pull request #49 from Route-Box/feature/#47
Browse files Browse the repository at this point in the history
Feature/#47 루트 생성, 루트 경로 기록 API
  • Loading branch information
suyeoniii authored Aug 21, 2024
2 parents bb32c74 + 0e122e3 commit d53e5bb
Show file tree
Hide file tree
Showing 20 changed files with 376 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.routebox.routebox.application.route

import com.routebox.routebox.application.route.dto.CreateRoutePointCommand
import com.routebox.routebox.application.route.dto.CreateRoutePointResult
import com.routebox.routebox.domain.route.RouteService
import org.springframework.stereotype.Component

@Component
class CreateRoutePointUseCase(
private val routeService: RouteService,
) {
/**
* 루트 위치 기록
*
* @param command user id, route id, latitude, longitude, point order
* @return 루트 point id
* @throws
*/
operator fun invoke(command: CreateRoutePointCommand): CreateRoutePointResult {
// TODO: 루트 소유자와 요청자가 같은지 확인
val routePoint = routeService.createRoutePoint(
routeId = command.routeId,
latitude = command.latitude,
longitude = command.longitude,
pointOrder = command.pointOrder,
)
return CreateRoutePointResult.from(routePoint)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.routebox.routebox.application.route

import com.routebox.routebox.application.route.dto.CreateRouteCommand
import com.routebox.routebox.application.route.dto.CreateRouteResult
import com.routebox.routebox.domain.route.RouteService
import com.routebox.routebox.domain.user.UserService
import org.springframework.stereotype.Component

@Component
class CreateRouteUseCase(
private val routeService: RouteService,
private val userService: UserService,
) {
/**
* 루트 등록
*
* @param command user id, startTime, endTime
* @return 루트 id
* @throws
*/
operator fun invoke(command: CreateRouteCommand): CreateRouteResult {
val user = userService.getUserById(command.userId)
val route = routeService.createRoute(user = user, startTime = command.startTime, endTime = command.endTime)
return CreateRouteResult.from(route)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.routebox.routebox.application.route.dto

import java.time.LocalDateTime

data class CreateRouteCommand(
val userId: Long,
val startTime: LocalDateTime,
val endTime: LocalDateTime,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.routebox.routebox.application.route.dto

data class CreateRoutePointCommand(
val userId: Long,
val routeId: Long,
val latitude: String,
val longitude: String,
val pointOrder: Int,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.routebox.routebox.application.route.dto

import com.routebox.routebox.domain.route.RoutePoint

data class CreateRoutePointResult(
val pointId: Long,
) {
companion object {
fun from(point: RoutePoint): CreateRoutePointResult = CreateRoutePointResult(
pointId = point.id,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.routebox.routebox.application.route.dto

import com.routebox.routebox.domain.route.Route

data class CreateRouteResult(
val routeId: Long,
) {
companion object {
fun from(route: Route): CreateRouteResult = CreateRouteResult(
routeId = route.id,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ data class GetRouteDetailResult(
val userId: Long,
val nickname: String,
val profileImageUrl: String,
val routeName: String,
val routeDescription: String,
val routeName: String?,
val routeDescription: String?,
val routeImageUrls: List<String>,
val isPurchased: Boolean,
val purchaseCount: Int,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.routebox.routebox.controller.route

import com.routebox.routebox.application.route.CreateRoutePointUseCase
import com.routebox.routebox.application.route.CreateRouteUseCase
import com.routebox.routebox.controller.route.dto.CreateRoutePointRequest
import com.routebox.routebox.controller.route.dto.CreateRoutePointResponse
import com.routebox.routebox.controller.route.dto.CreateRouteRequest
import com.routebox.routebox.controller.route.dto.CreateRouteResponse
import com.routebox.routebox.security.UserPrincipal
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.PathVariable
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

@Tag(name = "내루트 관련 API")
@RestController
@Validated
@RequestMapping("/api")
class RouteCommandController(
private val createRouteUseCase: CreateRouteUseCase,
private val createRoutePointUseCase: CreateRoutePointUseCase,
) {
@Operation(
summary = "루트 생성 (루트 기록 시작)",
description = "루트 기록 시작일시, 종료일시 등록",
security = [SecurityRequirement(name = "access-token")],
)
@ApiResponses(
ApiResponse(responseCode = "200"),
)
@PostMapping("/v1/routes/start")
fun createRoute(
@AuthenticationPrincipal userPrincipal: UserPrincipal,
@RequestBody @Valid request: CreateRouteRequest,
): CreateRouteResponse {
val routeResponse = createRouteUseCase(request.toCommand(userId = userPrincipal.userId))
return CreateRouteResponse.from(routeResponse.routeId)
}

@Operation(
summary = "루트 경로(점) 기록",
description = "1분마다 현재 위치 보내서 루트 경로의 점 찍는데 사용",
security = [SecurityRequirement(name = "access-token")],
)
@ApiResponses(
ApiResponse(responseCode = "200"),
)
@PostMapping("/v1/routes/{routeId}/point")
fun createRoutePoint(
@AuthenticationPrincipal userPrincipal: UserPrincipal,
@PathVariable routeId: Long,
@RequestBody @Valid request: CreateRoutePointRequest,
): CreateRoutePointResponse {
val routeResponse = createRoutePointUseCase(request.toCommand(userId = userPrincipal.userId, routeId = routeId))
return CreateRoutePointResponse.from(routeResponse.pointId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.routebox.routebox.controller.route.dto

import com.routebox.routebox.application.route.dto.CreateRoutePointCommand
import io.swagger.v3.oas.annotations.media.Schema

data class CreateRoutePointRequest(
@Schema(description = "위도", example = "37.123456")
val latitude: String,
@Schema(description = "경도", example = "127.123456")
val longitude: String,
@Schema(description = "경로 순서, 1부터 시작, 위치 기록할 때마다 +1 해서 전송", example = "1")
val pointOrder: Int,
) {
fun toCommand(userId: Long, routeId: Long): CreateRoutePointCommand =
CreateRoutePointCommand(
userId = userId,
routeId = routeId,
latitude = latitude,
longitude = longitude,
pointOrder = pointOrder,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.routebox.routebox.controller.route.dto

import io.swagger.v3.oas.annotations.media.Schema

data class CreateRoutePointResponse(
@Schema(description = "위치 점 id", example = "1")
val pointId: Long,
) {
companion object {
fun from(pointId: Long): CreateRoutePointResponse = CreateRoutePointResponse(
pointId = pointId,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.routebox.routebox.controller.route.dto

import com.routebox.routebox.application.route.dto.CreateRouteCommand
import com.routebox.routebox.util.DateTimeUtil
import io.swagger.v3.oas.annotations.media.Schema
import org.springframework.format.annotation.DateTimeFormat

data class CreateRouteRequest(
@Schema(description = "루트 기록 시작일시", example = "2024-08-01T00:00:00")
@field:DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val startTime: String,
@Schema(description = "루트 기록 종료일시", example = "2024-08-01T00:00:00")
@field:DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val endTime: String,
) {
fun toCommand(userId: Long): CreateRouteCommand =
CreateRouteCommand(
userId = userId,
startTime = DateTimeUtil.parseToLocalDateTime(startTime),
endTime = DateTimeUtil.parseToLocalDateTime(endTime),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.routebox.routebox.controller.route.dto

import io.swagger.v3.oas.annotations.media.Schema

data class CreateRouteResponse(
@Schema(description = "루트 id", example = "1")
val routeId: Long,
) {
companion object {
fun from(routeId: Long): CreateRouteResponse = CreateRouteResponse(
routeId = routeId,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ data class RouteResponse(
val nickname: String,

@Schema(description = "루트 제목", example = "서울의 작가들")
val routeName: String,
val routeName: String?,

@Schema(description = "루트 설명", example = "서울의 작가들을 만나보세요.")
val routeDescription: String,
val routeDescription: String?,

@Schema(description = "루트 이미지들", example = "[\"https://route-image1\", \"https://route-image2\"]")
val routeImageUrls: List<String>,
Expand Down
18 changes: 11 additions & 7 deletions src/main/kotlin/com/routebox/routebox/domain/route/Route.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.OneToMany
import jakarta.persistence.Table
import java.time.LocalDateTime

@Table(name = "routes")
@Entity
class Route(
id: Long = 0,
name: String,
description: String,
name: String?,
description: String?,
startTime: LocalDateTime,
endTime: LocalDateTime,
whoWith: String,
numberOfPeople: Int,
numberOfDays: String,
whoWith: String?,
numberOfPeople: Int?,
numberOfDays: String?,
style: Array<String>,
transportation: Array<String>,
isPublic: Boolean = false,
Expand All @@ -40,9 +41,9 @@ class Route(
@JoinColumn(name = "user_id")
val user: User? = user

var name: String = name
var name: String? = name

var description: String = description
var description: String? = description

var startTime: LocalDateTime = startTime

Expand All @@ -63,4 +64,7 @@ class Route(
var transportation: Array<String> = transportation

var isPublic: Boolean = isPublic

@OneToMany(mappedBy = "route")
var routePoints: List<RoutePoint> = mutableListOf()
}
40 changes: 40 additions & 0 deletions src/main/kotlin/com/routebox/routebox/domain/route/RoutePoint.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.routebox.routebox.domain.route

import com.routebox.routebox.domain.common.TimeTrackedBaseEntity
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.FetchType
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.Table

@Table(name = "route_points")
@Entity
class RoutePoint(
id: Long = 0,
route: Route,
latitude: String,
longitude: String,
pointOrder: Int,
) : TimeTrackedBaseEntity() {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "point_id")
val id: Long = id

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "route_id", nullable = false)
val route: Route = route

@Column(name = "latitude", nullable = false)
var latitude: String = latitude

@Column(name = "longitude", nullable = false)
var longitude: String = longitude

@Column(name = "point_order", nullable = false)
var pointOrder: Int = pointOrder
}
Loading

0 comments on commit d53e5bb

Please sign in to comment.