Skip to content

Commit

Permalink
Merge branch 'develop' into feature/#3-order-tosspayments
Browse files Browse the repository at this point in the history
  • Loading branch information
citycozy authored Jan 27, 2025
2 parents f0b67d7 + da47c8a commit 316805b
Show file tree
Hide file tree
Showing 23 changed files with 546 additions and 211 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ out/
.vscode/

env
.env
.env
9 changes: 9 additions & 0 deletions backend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
DB_USERNAME=root
DB_PASSWORD=!123456
DB_URL=jdbc:mariadb://localhost:3306/ttukttak_parking?serverTimezone\=Asia/Seoul

FRONTEND_URL=http://localhost:3000

KAKAO_API_KEY=0314d8afcdad5de6365ef17c1d0ab606

SECRET_KEY=4d9715cf62ea78542329e546846afdbe01fe82abc1d06c37b7131d97836b42740fe28ee7c322500563d6a828f3659c13ce5b5666082e80cbc139e902b76fd21d8493a94283239d14577f6ee4aeb655651488e8fe9cdf772021c6fbaf4b6ab43daacb0a6ed6cdc170a995c108dcf0063d339970960c816147fe789a98931bfc74235b7fd2d3299cd9e83ef3a1a9400f950e0eb70c14004e5a566aa16b776a847c56d687809da1e8ea5c4b612b9a1185efe68570bd18fd1d39ae5119d2d239a409054190d0550bdb7eb96704af63ce3a834d808e2fe5136db025e3494236a645236cf41f2816154fff131175bc650fbb5b2964188f43b390a32a98e4f9ee75ff4cf8a4f8fbe1f8d44148c83b907d50fbbf9da30ece7918fa9024c98501e42c574932921ab2f583a7da9d4aa5e32620476dc210f53c1bf0ae1c9e47461f2341f26944dba471706f06646e312b0fc537c7788751928abb8c7cff2915f76c66bf2d48b599d755ee8d7a1d80bbb11c9e9c4379c1f0dba3026f5f4dc6ab1ea711e6938d73d60de53f6e89aef60eeb0bc5a79f7ceece7be906f2f9dc2e6d5cc6242d239515023733faf254af3fb4e6235bb02b9e7c859efcbb112e1ceba472ad6ee286477f85219dcc765d614395c618829d0b905fc88839bf22a96905c8edaee812492e4a6de5a6de56df104da0d4a73effae2e13c3f0594c6689f753ee64965d12a6f5
3 changes: 3 additions & 0 deletions backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ dependencies {
implementation ("org.json:json:20210307")

implementation ("org.springframework.boot:spring-boot-starter-thymeleaf:3.3.6")

// Kotlin reflection features
implementation ("org.jetbrains.kotlin:kotlin-reflect:1.9.10")
}


Expand Down
2 changes: 1 addition & 1 deletion backend/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pluginManagement {
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.9.0'
id 'org.jetbrains.kotlin.jvm' version '1.9.24'
}
}
rootProject.name = 'ttukttak_parking'
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.nbe2_3_3_team4.backend.controller

import com.nbe2_3_3_team4.backend.domain.order.dto.OrderRequest
import com.nbe2_3_3_team4.backend.domain.order.dto.OrderResponse
import com.nbe2_3_3_team4.backend.domain.order.service.OrderService
import com.nbe2_3_3_team4.backend.global.response.ApiResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.*


@RestController
@RequestMapping("/api/orders")
@Tag(name = "Order API", description = "주차권 주문 관련 API")
class OrderController(
private val orderService: OrderService
) {

@Operation(summary = "주차권 주문 요청 API", description = "주차권 구매를 요청합니다.")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공"))
@PostMapping("/tickets")
fun createOrder(
@RequestBody dto: OrderRequest.CreateOrder,
@AuthenticationPrincipal user: User
): ResponseEntity<ApiResponse<OrderResponse.CreateOrder>> {
val response = orderService.createOrder(dto, user.username)
return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.createSuccess(response))
}

@Operation(summary = "주차권 주문 결제 성공 API", description = "주차권 결제 성공 시 상태 변경합니다")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공"))
@PutMapping("/{payId}/success")
fun completePay(@PathVariable payId: String): ResponseEntity<ApiResponse<String>> {
val response = orderService.completePay(payId)
return ResponseEntity.ok(ApiResponse.createSuccess(response))
}

@Operation(summary = "주차권 구매 기록 상세 조회 API", description = "주차권 구매 세부 기록을 조회합니다.")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공"))
@GetMapping("/{orderId}")
fun getOrder(@PathVariable orderId: String): ResponseEntity<ApiResponse<OrderResponse>> {
val response = orderService.getOrder(orderId)
return ResponseEntity.ok(ApiResponse.createSuccess(response))
}

@Operation(summary = "주차권 취소 요청 API", description = "주차권 취소를 요청합니다.")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공"))
@PutMapping("/{orderId}/cancel")
fun cancelTicket(
@AuthenticationPrincipal user: User,
@PathVariable orderId: String
): ResponseEntity<ApiResponse<String>> {
val response = orderService.cancelTicket(user.username, orderId)
return ResponseEntity.ok(ApiResponse.createSuccess(response))
}

@DeleteMapping("/{payId}")
fun deleteOrder(@PathVariable payId: String): ResponseEntity<ApiResponse<Void?>> {
return ResponseEntity.ok(ApiResponse.createSuccess(orderService.deleteOrder(payId)))
}

@Operation(summary = "주차권 구매 기록 조회 API", description = "주차권 구매 기록을 조회합니다.")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공"))
@GetMapping("/order-history")
fun getOrderHistory(@AuthenticationPrincipal user: User): ResponseEntity<ApiResponse<List<OrderResponse.GetOrderHistory>>> {
val response = orderService.getOrderHistory(user.username)
return ResponseEntity.ok(ApiResponse.createSuccess(response))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.*
@Tag(name = "🚗 Parking", description = "주차장 관련 API")
class ParkingController(val parkingService: ParkingService) {


@Operation(summary = "좌표 근처 주차장 정보 조회 API", description = "좌표 근처 주차장 정보를 조회합니다.")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공"))
@GetMapping("/search")
Expand All @@ -29,19 +28,15 @@ class ParkingController(val parkingService: ParkingService) {
@Operation(summary = "주차장 조회 API", description = "주차장을 조회합니다.")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공"))
@GetMapping("/{parkingId}")
fun getNearbyParking(
@PathVariable parkingId: Long
): ResponseEntity<ApiResponse<GetParking>> {
fun getNearbyParking(@PathVariable parkingId: Long): ResponseEntity<ApiResponse<GetParking>> {
return ResponseEntity.ok()
.body(ApiResponse.createSuccess(parkingService.getParking(parkingId)))
}

@Operation(summary = "주차장 잔여 자리 조회 API", description = "주차장의 잔여 자리를 조회합니다.")
@ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공"))
@GetMapping("/{parkingId}/status")
fun getParkingStatus(
@PathVariable parkingId: Long
): ResponseEntity<ApiResponse<GetParkingStatus>> {
fun getParkingStatus(@PathVariable parkingId: Long): ResponseEntity<ApiResponse<GetParkingStatus>> {
return ResponseEntity.ok()
.body(ApiResponse.createSuccess(parkingService.getParkingStatus(parkingId)))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Member() : BaseTime() {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private var id: Long? = null
var id: Long? = null

@Column(name = "name")
var name: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import java.util.*

interface MemberRepository : JpaRepository<Member?, Long?> {
fun existsByEmail(email: String?): Boolean
fun findByEmail(email: String?): Optional<Member?>?
fun findByEmail(email: String?): Optional<Member>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.nbe2_3_3_team4.backend.domain.order.dto

import com.nbe2_3_3_team4.backend.domain.order.entity.enum.PaymentStatus

data class OrderRequest(
val createOrder: CreateOrder
) {
data class CreateOrder(
val paymentId: String,
val ticketId: Long,
val carNumber: String,
val paymentStatus: PaymentStatus
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.nbe2_3_3_team4.backend.domain.order.dto

import com.nbe2_3_3_team4.backend.domain.order.entity.Order
import com.nbe2_3_3_team4.backend.domain.order.entity.OrderDetail
import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking
import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket
import com.nbe2_3_3_team4.backend.domain.order.entity.enum.OrderStatus.*
import java.time.format.DateTimeFormatter

data class OrderResponse(
val parking: String?,
val addr: String?,
val carNum: String,
val startTime: String?,
val endTime: String,
val pkDuration: Int?,
val price: Int?,
val addPkDuration: Int,
val addPrice: Int,
val totalPrice: Int
) {
companion object {
fun from(parking: Parking, orderDetail: OrderDetail, ticket: Ticket, addPkDuration: Int, addPrice: Int): OrderResponse {
val formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 a h시 mm분")
val start = orderDetail.startParkingTime?.format(formatter)
val end = orderDetail.endParkingTime?.format(formatter) ?: "주차중"

return OrderResponse(
parking.name,
parking.address,
orderDetail.carNumber,
start,
end,
ticket.parkingDuration,
ticket.price,
addPkDuration,
addPrice,
ticket.price!! + addPrice
)
}
}



data class CreateOrder(
val orderId: String,
val ticketId: Long,
val memberId: Long,
val carNum: String
) {
companion object {
fun from(orderId: String, ticketId: Long, memberId: Long, carNum: String): CreateOrder {
return CreateOrder(orderId, ticketId, memberId, carNum)
}
}
}

data class GetOrderHistory(
val orderId: String,
val parkingId: Long,
val carNum: String,
val time: String,
val status: String,
val duration: Int,
val price: Int
) {
companion object {
fun from(order: Order, parking: Parking, ticket: Ticket): GetOrderHistory {
val start = order.createdAt!!
val formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 a h시 mm분")
val time = start.format(formatter)
val status = when (order.orderStatus) {
WAITING -> "주차 대기"
PARKING -> "주차중"
CANCELED -> "환불"
else -> "주차 완료"
}

return GetOrderHistory(
order.id,
parking.parkingId!!,
order.orderDetail.carNumber,
time,
status,
ticket.parkingDuration!!,
ticket.price!!
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.nbe2_3_3_team4.backend.domain.order.entity

import com.nbe2_3_3_team4.backend.domain.member.entity.Member

import com.nbe2_3_3_team4.backend.domain.order.entity.enums.OrderStatus
import com.nbe2_3_3_team4.backend.domain.order.entity.enums.PaymentStatus
import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket
Expand Down Expand Up @@ -58,4 +59,21 @@ open class Order(
this.paymentKey = paymentKey
this.paymentDate = paymentDate
}

companion object {
@JvmStatic
fun createOrder(
id: String,
ticket: Ticket,
member: Member,
orderDetail: OrderDetail
): Order {
return Order(
id = id,
ticket = ticket,
member = member,
orderDetail = orderDetail
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.nbe2_3_3_team4.backend.global.BaseTime
import jakarta.persistence.*
import java.time.LocalDateTime


@Entity
@Table(name = "order_details")
class OrderDetail : BaseTime() {
Expand All @@ -17,4 +16,10 @@ class OrderDetail : BaseTime() {
private val cancelPrice = 0
private val addPrice = 0
private val totalPrice = 0

companion object {
fun createOrderDetail(totalPrice: Int, carNumber: String): OrderDetail {
return OrderDetail(totalPrice = totalPrice, carNumber = carNumber)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.nbe2_3_3_team4.backend.domain.order.entity.enum

enum class OrderStatus(val message: String) {
WAITING("주차 대기"),
PARKING("주차 중"),
FINISHED("주차 종료"),
CANCELED("취소");

override fun toString(): String = message
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.nbe2_3_3_team4.backend.domain.order.entity.enum

enum class PaymentStatus(val message : String) {
WAITING("결제 대기"),
COMPLETE("결제 완료");

override fun toString(): String = message
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.nbe2_3_3_team4.backend.domain.order.repository

import com.nbe2_3_3_team4.backend.domain.order.entity.OrderDetail
import org.springframework.data.jpa.repository.JpaRepository

interface OrderDetailRepository : JpaRepository<OrderDetail, Long> {

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.nbe2_3_3_team4.backend.domain.order.entity.Order
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface OrderRepository : JpaRepository<Order, String> {
fun findByPaymentKey(paymentKey: String): Order?
fun findAllByMember(member: Member): Optional<List<Order>>
}
Loading

0 comments on commit 316805b

Please sign in to comment.