From bc4eb7cb272f733b7b760069966f24ba46f4d383 Mon Sep 17 00:00:00 2001 From: Dianuma <dltmdgus1208@gmail.com> Date: Fri, 24 Jan 2025 06:53:32 +0900 Subject: [PATCH 1/7] =?UTF-8?q?.gitignore=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 197 ++++++++++++++++++++++++++++++++++++++++++++ backend/.gitignore | 199 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 396 insertions(+) create mode 100644 .gitignore create mode 100644 backend/.gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e4955f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,197 @@ +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### NetBeans template +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +### Intellij+all template +HELP.md +.gradle +.gradle/** +.gradle/buildOutputCleanup/ +.gradle/8.11.1/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iml +*.ipr +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +# IntelliJ project files +out +gen + +### Gradle template +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + + +### Windows template +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp +# Windows shortcuts + +*.lnk diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..ec2bec7 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,199 @@ +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### NetBeans template +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +### Intellij+all template +HELP.md +.gradle +.gradle/** +.gradle/buildOutputCleanup/ +.gradle/8.11.1/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iml +*.ipr +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +# IntelliJ project files +out +gen + +### Gradle template +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +### Windows template +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp +# Windows shortcuts + +*.lnk +!/.gitignore +!/.gitignore From 700121920ca372f782a320a5d3fafe24abaf1273 Mon Sep 17 00:00:00 2001 From: Dianuma <dltmdgus1208@gmail.com> Date: Fri, 24 Jan 2025 06:58:37 +0900 Subject: [PATCH 2/7] =?UTF-8?q?.java=EC=9D=84(=EB=A5=BC)=20.kt(=EC=9C=BC)?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/{ParkingController.java => ParkingController.kt} | 0 .../parking/dto/{ParkingResponse.java => ParkingResponse.kt} | 0 .../backend/domain/parking/entity/{Parking.java => Parking.kt} | 0 .../parking/entity/{ParkingStatus.java => ParkingStatus.kt} | 0 .../repository/{ParkingRepository.java => ParkingRepository.kt} | 0 .../parking/service/{ParkingService.java => ParkingService.kt} | 0 .../exception/{NotFoundException.java => NotFoundException.kt} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename backend/src/main/java/com/nbe2_3_3_team4/backend/controller/{ParkingController.java => ParkingController.kt} (100%) rename backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/{ParkingResponse.java => ParkingResponse.kt} (100%) rename backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/{Parking.java => Parking.kt} (100%) rename backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/{ParkingStatus.java => ParkingStatus.kt} (100%) rename backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/{ParkingRepository.java => ParkingRepository.kt} (100%) rename backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/{ParkingService.java => ParkingService.kt} (100%) rename backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/{NotFoundException.java => NotFoundException.kt} (100%) diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.java b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt similarity index 100% rename from backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.java rename to backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.java b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.kt similarity index 100% rename from backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.java rename to backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.java b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt similarity index 100% rename from backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.java rename to backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.java b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt similarity index 100% rename from backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.java rename to backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.java b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.kt similarity index 100% rename from backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.java rename to backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.java b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt similarity index 100% rename from backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.java rename to backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.java b/backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.kt similarity index 100% rename from backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.java rename to backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.kt From bcad85ba4698ffb1e9669038345a2147bc8e29c9 Mon Sep 17 00:00:00 2001 From: Dianuma <dltmdgus1208@gmail.com> Date: Fri, 24 Jan 2025 07:10:07 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/.env | 9 + backend/build.gradle | 7 +- backend/settings.gradle | 7 +- .../backend/controller/ParkingController.kt | 103 ++++---- .../domain/parking/dto/ParkingResponse.kt | 46 ++-- .../backend/domain/parking/entity/Parking.kt | 142 +++++------ .../domain/parking/entity/ParkingStatus.kt | 52 ++-- .../parking/repository/ParkingRepository.kt | 14 +- .../domain/parking/service/ParkingService.kt | 227 +++++++----------- .../global/exception/NotFoundException.kt | 9 +- backend/src/main/resources/application.yml | 2 +- 11 files changed, 276 insertions(+), 342 deletions(-) create mode 100644 backend/.env diff --git a/backend/.env b/backend/.env new file mode 100644 index 0000000..f8b0208 --- /dev/null +++ b/backend/.env @@ -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 \ No newline at end of file diff --git a/backend/build.gradle b/backend/build.gradle index 96b9228..ec7b5d9 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.3.6' id 'io.spring.dependency-management' version '1.1.6' + id 'org.jetbrains.kotlin.jvm' } group = 'com.team4' @@ -53,9 +54,13 @@ dependencies { runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' // json - implementation "org.json:json:20210307" + implementation 'org.json:json:20231013' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.3.6' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + + // Kotlin reflection features + implementation "org.jetbrains.kotlin:kotlin-reflect:1.9.10" } tasks.named('test') { diff --git a/backend/settings.gradle b/backend/settings.gradle index 2f5a9c4..7409ba5 100644 --- a/backend/settings.gradle +++ b/backend/settings.gradle @@ -1 +1,6 @@ -rootProject.name = 'ttukttak_parking' +pluginManagement { + plugins { + id 'org.jetbrains.kotlin.jvm' version '1.9.24' + } +} +rootProject.name = 'ttukttak_parking' \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt index 7ae7c77..6f9a065 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt @@ -1,60 +1,53 @@ -package com.nbe2_3_3_team4.backend.controller; - -import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse; -import com.nbe2_3_3_team4.backend.domain.parking.service.ParkingService; -import com.nbe2_3_3_team4.backend.global.response.ApiResponse; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; +package com.nbe2_3_3_team4.backend.controller + +import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.* +import com.nbe2_3_3_team4.backend.domain.parking.service.ParkingService +import com.nbe2_3_3_team4.backend.global.response.ApiResponse +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter +import io.swagger.v3.oas.annotations.responses.ApiResponses +import io.swagger.v3.oas.annotations.tags.Tag +import lombok.extern.slf4j.Slf4j +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* @RestController -@RequiredArgsConstructor @RequestMapping("/api/parking") -@Slf4j @Tag(name = "🚗 Parking", description = "주차장 관련 API") -public class ParkingController { - - private final ParkingService parkingService; - - @Operation(summary = "좌표 근처 주차장 정보 조회 API", description = "좌표 근처 주차장 정보를 조회합니다.") - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공")}) - @GetMapping("/search") - public ResponseEntity<ApiResponse<List<ParkingResponse.GetNearbyParking>>> getNearbyParking( - @Parameter(description = "위도") @RequestParam(value = "lat") Double lat, - @Parameter(description = "경도") @RequestParam(value = "lng") Double lng) { - return ResponseEntity.ok() - .body(ApiResponse.createSuccess(parkingService.getNearbyParking(lat, lng))); - } - - @Operation(summary = "주차장 조회 API", description = "주차장을 조회합니다.") - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공")}) - @GetMapping("/{parkingId}") - public ResponseEntity<ApiResponse<ParkingResponse.GetParking>> getNearbyParking( - @PathVariable Long parkingId - ) { - 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") - public ResponseEntity<ApiResponse<ParkingResponse.GetParkingStatus>> getParkingStatus( - @PathVariable Long parkingId - ) { - return ResponseEntity.ok() - .body(ApiResponse.createSuccess(parkingService.getParkingStatus(parkingId))); - } - - +class ParkingController { + + @Autowired + private val parkingService: ParkingService? = null + + @Operation(summary = "좌표 근처 주차장 정보 조회 API", description = "좌표 근처 주차장 정보를 조회합니다.") + @ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공")) + @GetMapping("/search") + fun getNearbyParking( + @Parameter(description = "위도") @RequestParam(value = "lat") lat: Double, + @Parameter(description = "경도") @RequestParam(value = "lng") lng: Double + ): ResponseEntity<ApiResponse<List<GetNearbyParking>>> { + return ResponseEntity.ok() + .body(ApiResponse.createSuccess(parkingService!!.getNearbyParking(lat, lng))) + } + + @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>> { + 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>> { + return ResponseEntity.ok() + .body(ApiResponse.createSuccess(parkingService!!.getParkingStatus(parkingId))) + } } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.kt index 06517a0..a82c84a 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/dto/ParkingResponse.kt @@ -1,31 +1,35 @@ -package com.nbe2_3_3_team4.backend.domain.parking.dto; +package com.nbe2_3_3_team4.backend.domain.parking.dto -import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking; -import com.nbe2_3_3_team4.backend.domain.parking.entity.ParkingStatus; +import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking +import com.nbe2_3_3_team4.backend.domain.parking.entity.ParkingStatus -public record ParkingResponse() { - - public record GetNearbyParking(Long id, String name, Double latitude, Double longitude, String status) { - public static GetNearbyParking from(Parking parking, String status) { - return new GetNearbyParking(parking.getParkingId(), parking.getName(), parking.getLatitude(), parking.getLongitude(), status); +class ParkingResponse { + data class GetNearbyParking(val id: Long?, val name: String?, val latitude: Double?, val longitude: Double?, val status: String? + ) { + companion object { + fun from(parking: Parking, status: String) = with(parking) { + GetNearbyParking(parkingId, name, latitude, longitude, status) + } } } - public record GetParking(String name, String address, String weOpenTime, String weEndTime, - String wdOpenTime, String wdEndTime, int basicCharge, int addCharge, int addChargeTime) { - public static GetParking from(Parking parking) { - return new GetParking(parking.getName(), parking.getAddress(), - parking.getWeOpenTime(), parking.getWeEndTime(), parking.getWdOpenTime(), parking.getWdEndTime(), - parking.getBasicCharge(), parking.getAddCharge(), parking.getAddChargeTime()); + data class GetParking( + val name: String?, val address: String?, val weOpenTime: String?, val weEndTime: String?, + val wdOpenTime: String?, val wdEndTime: String?, val basicCharge: Int, val addCharge: Int, val addChargeTime: Int + ) { + companion object { + fun from(parking: Parking) = with(parking) { + GetParking( name, address, weOpenTime, weEndTime, wdOpenTime, wdEndTime, basicCharge, addCharge, addChargeTime ) + } } } - public record GetParkingStatus(int availableSpace, - int usedSpace, - int totalSpace) { - public static GetParkingStatus from(ParkingStatus status) { - return new GetParkingStatus( - status.getTotalParkingSpace() - status.getUsedParkingSpace(), status.getUsedParkingSpace(), status.getTotalParkingSpace()); + data class GetParkingStatus(val availableSpace: Int, val usedSpace: Int, val totalSpace: Int + ) { + companion object { + fun from(status: ParkingStatus) = with(status) { + GetParkingStatus( totalParkingSpace - usedParkingSpace, usedParkingSpace, totalParkingSpace ) + } } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt index 98aa56b..73fcf34 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt @@ -1,87 +1,71 @@ -package com.nbe2_3_3_team4.backend.domain.parking.entity; +package com.nbe2_3_3_team4.backend.domain.parking.entity -import com.fasterxml.jackson.databind.JsonNode; -import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket; -import com.nbe2_3_3_team4.backend.global.BaseTime; -import jakarta.persistence.*; -import lombok.*; +import com.fasterxml.jackson.databind.JsonNode +import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket +import jakarta.persistence.* -import java.util.ArrayList; -import java.util.List; - -@Getter -@Builder @Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "parking") -public class Parking extends BaseTime { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "parking_id") - private Long parkingId; - - @Column(name = "name") - private String name; - @Column(name = "address") - private String address; - @Column(name = "latitude") - private Double latitude; - @Column(name = "longitude") - private Double longitude; - @Column(name = "we_open_time", length = 4) - private String weOpenTime; - @Column(name = "we_end_time", length = 4) - private String weEndTime; - @Column(name = "wd_open_time", length = 4) - private String wdOpenTime; - @Column(name = "wd_end_time", length = 4) - private String wdEndTime; - @Column(name = "basic_charge") - private int basicCharge; - @Column(name = "basic_charge_time") - private int basicChargeTime; - @Column(name = "add_charge") - private int addCharge; - @Column(name = "add_charge_time") - private int addChargeTime; - - @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @JoinColumn(name = "pklt_status_id") - private ParkingStatus parkingStatus; - - @OneToMany(mappedBy = "parking", cascade = CascadeType.ALL, orphanRemoval = true) - private List<Ticket> tickets = new ArrayList<>(); - - public static Parking to(JsonNode data, ParkingStatus status) { - int addCharge = data.get("add_prk_crg").asInt(); - int addChargeTime = data.get("add_prk_hr").asInt(); +data class Parking( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "parking_id") + val parkingId: Long? = null, + @Column(name = "name") + var name: String? = null, + @Column(name = "address") + var address: String? = null, + @Column(name = "latitude") + var latitude: Double? = null, + @Column(name = "longitude") + var longitude: Double? = null, + @Column(name = "we_open_time", length = 4) + var weOpenTime: String? = null, + @Column(name = "we_end_time", length = 4) + var weEndTime: String? = null, + @Column(name = "wd_open_time", length = 4) + var wdOpenTime: String? = null, + @Column(name = "wd_end_time", length = 4) + var wdEndTime: String? = null, + @Column(name = "basic_charge") + var basicCharge: Int = 0, + @Column(name = "basic_charge_time") + var basicChargeTime: Int = 0, + @Column(name = "add_charge") + var addCharge: Int = 0, + @Column(name = "add_charge_time") + var addChargeTime: Int = 0, - if (data.get("add_prk_crg").asInt() == 0) { - addCharge = 220; - addChargeTime = 5; - } + @OneToOne(cascade = [CascadeType.ALL], fetch = FetchType.LAZY) + @JoinColumn(name = "pklt_status_id") + var parkingStatus: ParkingStatus? = null, - return Parking.builder() - .name(data.get("pklt_nm").asText()) - .address(data.get("addr").asText()) - .latitude(data.get("lat").asDouble()) - .longitude(data.get("lot").asDouble()) - .weOpenTime(data.get("we_oper_bgng_tm").asText()) - .weEndTime(data.get("we_oper_end_tm").asText()) - .wdOpenTime(data.get("wd_oper_bgng_tm").asText()) - .wdEndTime(data.get("wd_oper_end_tm").asText()) - .basicCharge(data.get("bsc_prk_crg").asInt()) - .basicChargeTime(data.get("bsc_prk_hr").asInt()) - .addCharge(addCharge) - .addChargeTime(addChargeTime) - .parkingStatus(status) - .build(); - } + @OneToMany(mappedBy = "parking", cascade = [CascadeType.ALL], orphanRemoval = true) + var tickets: MutableList<Ticket> = mutableListOf() +) { + fun regTicket(ticket: Ticket) { tickets.add(ticket) } - public void regTicket(Ticket ticket) { - this.tickets.add(ticket); - } + companion object { + @JvmStatic + fun to(data: JsonNode, status: ParkingStatus?): Parking { + val addCharge = if (data["add_prk_crg"].asInt() == 0) 220 else data["add_prk_crg"].asInt() + val addChargeTime = if (data["add_prk_crg"].asInt() == 0) 5 else data["add_prk_hr"].asInt() -} + return Parking( + name = data["pklt_nm"].asText(), + address = data["addr"].asText(), + latitude = data["lat"].asDouble(), + longitude = data["lot"].asDouble(), + weOpenTime = data["we_oper_bgng_tm"].asText(), + weEndTime = data["we_oper_end_tm"].asText(), + wdOpenTime = data["wd_oper_bgng_tm"].asText(), + wdEndTime = data["wd_oper_end_tm"].asText(), + basicCharge = data["bsc_prk_crg"].asInt(), + basicChargeTime = data["bsc_prk_hr"].asInt(), + addCharge = addCharge, + addChargeTime = addChargeTime, + parkingStatus = status, + ) + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt index f8d838f..635585f 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt @@ -1,38 +1,24 @@ -package com.nbe2_3_3_team4.backend.domain.parking.entity; +package com.nbe2_3_3_team4.backend.domain.parking.entity - -import com.fasterxml.jackson.databind.JsonNode; -import jakarta.persistence.*; -import lombok.*; - -import java.time.LocalDateTime; +import com.fasterxml.jackson.databind.JsonNode +import jakarta.persistence.* +import java.time.LocalDateTime @Entity -@Getter -@AllArgsConstructor(access = AccessLevel.PROTECTED) -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Builder @Table(name = "parking_status") -public class ParkingStatus { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long parkingStatusId; - - private int totalParkingSpace; // 총 주차 면 - private int usedParkingSpace; // 사용중인 주차 면 - - private LocalDateTime space_updated_at; // 사용 주차면 업데이트 시간 - - public static ParkingStatus to(JsonNode data) { - return ParkingStatus.builder() - .totalParkingSpace(data.get("tpkct").asInt()) - .usedParkingSpace(data.get("now_prk_vhcl_cnt").asInt()) - .space_updated_at(LocalDateTime.now()) - .build(); - } - - public void ModifyTotalParkingSpaceOfJson() { - this.totalParkingSpace += 1; - } +data class ParkingStatus ( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + var parkingStatusId: Long? = null, + var totalParkingSpace: Int = 0, // 총 주차 면 + var usedParkingSpace: Int = 0, // 사용중인 주차 면 + var space_updated_at: LocalDateTime? = null // 사용 주차면 업데이트 시간 +) { + fun ModifyTotalParkingSpaceOfJson() { this.totalParkingSpace += 1 } + + companion object { + fun to(data: JsonNode): ParkingStatus { + return ParkingStatus ( null, data["tpkct"].asInt(), data["now_prk_vhcl_cnt"].asInt(), LocalDateTime.now() ) + } + } } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.kt index c871a2c..ed8bf50 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/repository/ParkingRepository.kt @@ -1,10 +1,10 @@ -package com.nbe2_3_3_team4.backend.domain.parking.repository; +package com.nbe2_3_3_team4.backend.domain.parking.repository -import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ParkingRepository extends JpaRepository<Parking, Long> { - - Parking findByName(String parkingName); +import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +@Repository +interface ParkingRepository : JpaRepository<Parking?, Long?> { + fun findByName(parkingName: String?): Parking? } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt index 1469780..c5704a2 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt @@ -1,141 +1,92 @@ -package com.nbe2_3_3_team4.backend.domain.parking.service; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse; -import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking; -import com.nbe2_3_3_team4.backend.domain.parking.entity.ParkingStatus; -import com.nbe2_3_3_team4.backend.domain.parking.repository.ParkingRepository; -import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket; -import com.nbe2_3_3_team4.backend.global.exception.ErrorCode; -import com.nbe2_3_3_team4.backend.global.exception.NotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.io.IOException; -import java.util.Comparator; -import java.util.List; -import java.util.function.Predicate; +package com.nbe2_3_3_team4.backend.domain.parking.service + +import com.fasterxml.jackson.databind.ObjectMapper +import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.GetParking +import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.GetParkingStatus +import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.GetNearbyParking +import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.GetNearbyParking.Companion.from +import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.GetParking.Companion.from +import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.GetParkingStatus.Companion.from +import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking +import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking.Companion.to +import com.nbe2_3_3_team4.backend.domain.parking.entity.ParkingStatus +import com.nbe2_3_3_team4.backend.domain.parking.repository.ParkingRepository +import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket +import com.nbe2_3_3_team4.backend.global.exception.ErrorCode +import com.nbe2_3_3_team4.backend.global.exception.NotFoundException +import lombok.RequiredArgsConstructor +import org.springframework.core.io.ClassPathResource +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import kotlin.math.cos + +const val KM = 0.5 +const val latKm = KM / 111 +val lowCongestion = 0.0..30.0 // 혼잡도 범위 여유 +val mediumCongestion = 30.0..70.0 // 혼잡도 범위 보통 @Service @RequiredArgsConstructor -public class ParkingService { - - private final ParkingRepository parkingRepository; - - @Transactional(readOnly = true) - public ParkingResponse.GetParking getParking(Long parkingId) { - Parking parking = parkingRepository.findById(parkingId) - .orElseThrow(() -> new NotFoundException(ErrorCode.PKLT_NOT_FOUND)); - - return ParkingResponse.GetParking.from(parking); - } - - @Transactional(readOnly = true) - public ParkingResponse.GetParkingStatus getParkingStatus(Long parkingId) { - Parking parking = parkingRepository.findById(parkingId) - .orElseThrow(() -> new NotFoundException(ErrorCode.PKLT_NOT_FOUND)); - - return ParkingResponse.GetParkingStatus.from(parking.getParkingStatus()); - } - - public List<ParkingResponse.GetNearbyParking> getNearbyParking(Double lat, Double lng) { - List<Parking> parkingList = getParkingList(); - List<Parking> nearbyParkingList = filterNearbyParking(parkingList, lat, lng); - return calculateCongestionAndSort(nearbyParkingList); - } - - public List<Parking> getParkingList() { - return parkingRepository.findAll(); - } - - public List<Parking> filterNearbyParking(List<Parking> parkingList, Double latitude, Double longitude) { - double KM = 0.5; - double lngDifference = KM / 111 / (Math.cos(latitude)); - - Predicate<Parking> latFilter = parking -> - parking.getLatitude() > latitude - (KM / 111) - && latitude + (KM / 111) > parking.getLatitude(); - Predicate<Parking> lngFilter = parking -> - parking.getLongitude() > longitude - lngDifference - && parking.getLongitude() < longitude + lngDifference; - - return parkingList.stream() - .filter(latFilter.and(lngFilter)) - .toList(); - } - - private List<ParkingResponse.GetNearbyParking> calculateCongestionAndSort(List<Parking> parkingList) { - return parkingList.stream().sorted( - Comparator.comparingDouble( - pklt -> { - ParkingStatus status = pklt.getParkingStatus(); - return (double) status.getUsedParkingSpace() / status.getTotalParkingSpace() * 100; - })) - .map(pklt -> { - ParkingStatus status = pklt.getParkingStatus(); - double percentage = (double) status.getUsedParkingSpace() / status.getTotalParkingSpace() * 100; - String congestionStatus; - if (percentage <= 30) { - congestionStatus = "여유"; - } else if (percentage <= 70) { - congestionStatus = "보통"; - } else { - congestionStatus = "혼잡"; - } - return ParkingResponse.GetNearbyParking.from(pklt, congestionStatus); - }).toList(); - } - - @Transactional - public Void loadDefaultDataByJson() throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - - JsonNode root = objectMapper.readTree(new ClassPathResource("static/data.json").getFile()); - JsonNode dataArray = root.get("DATA"); - - for (JsonNode data : dataArray) { - String parkingName = data.get("pklt_nm").asText(); - - Parking parking = parkingRepository.findByName(parkingName); - - if (parking == null) { - parkingRepository.save(Parking.to(data, ParkingStatus.to(data))); - } else { - parking.getParkingStatus().ModifyTotalParkingSpaceOfJson(); - } - } - - return null; - } - - @Transactional - public Void loadDefaultTickets() { - List<Parking> parkingList = parkingRepository.findAll(); - int[] nums = {1, 2, 4, 6, 12}; - - for (Parking parking : parkingList) { - - // 1시간 2시간 4시간 6시간 12시간 - // bsc_prk_crg => 기본 요금 - // bsc_prk_hr => 분단위 - for (int num : nums) { - int basicCharge = parking.getBasicCharge(); - int basicChargeTime = parking.getBasicChargeTime(); - - if (basicCharge == 0) { - basicCharge = 220; - basicChargeTime = 5; - } - - int result = (basicCharge / basicChargeTime) * 60 * num; - - parking.regTicket(Ticket.to(parking, result, num)); - } - } - - return null; - } -} +open class ParkingService( private val parkingRepository: ParkingRepository ) { + + @get:Transactional(readOnly = true) + open val parkingList: List<Parking?> get() = parkingRepository.findAll().filterNotNull() // 주차장 목록 조회 + + @Transactional(readOnly = true) + open fun getParking(parkingId: Long): GetParking = from( parkingRepository.findById(parkingId) // 주차장 조회 + .orElseThrow { NotFoundException(ErrorCode.PKLT_NOT_FOUND) }!! ) // 예외 처리 + + @Transactional(readOnly = true) + open fun getParkingStatus(parkingId: Long): GetParkingStatus = from( parkingRepository.findById(parkingId) // 주차장 상태 조회 + .orElseThrow { NotFoundException(ErrorCode.PKLT_NOT_FOUND) }!!.parkingStatus!! ) // 예외 처리 + + @Transactional(readOnly = true) + open fun getNearbyParking(lat: Double, lng: Double): List<GetNearbyParking> = calculateCongestionAndSort(filterNearbyParking(parkingList, lat, lng)) // 주변 주차장 조회 + + private fun filterNearbyParking(parkingList: List<Parking?>, latitude: Double, longitude: Double): List<Parking?> { + val lngDifference = latKm / (cos(latitude)) // 경도 차이 계산 + + return parkingList.filterNotNull().filter { + it.latitude != null && it.longitude != null && + it.latitude!! in (latitude - latKm)..(latitude + latKm) && + it.longitude!! in (longitude - lngDifference)..(longitude + lngDifference) } // 주변 주차장 필터링 + } + + private fun calculateCongestionAndSort(parkingList: List<Parking?>): List<GetNearbyParking> { + return parkingList.filterNotNull() + .sortedBy { it.parkingStatus?.getCongestionRate() ?: 0.0 } // 주차장 혼잡도에 따라 정렬 + .map { from(it, it.parkingStatus?.let { status -> + when (status.getCongestionRate()) { + in lowCongestion -> "여유" + in mediumCongestion -> "보통" + else -> "혼잡" + } } ?: "정보 없음") } // 주차장 혼잡도를 3단계로 나누어 반환 + } + + private fun ParkingStatus.getCongestionRate(): Double = usedParkingSpace.toDouble() / totalParkingSpace * 100 + + @Transactional + open fun loadDefaultDataByJson(): Void? { + val objectMapper = ObjectMapper() + val dataArray = objectMapper.readTree(ClassPathResource("static/data.json").file)["DATA"] + + dataArray.forEach { data -> + parkingRepository.findByName(data["pklt_nm"].asText())?.let { // 이미 존재하는 주차장인 경우 + it.parkingStatus?.ModifyTotalParkingSpaceOfJson() // 주차장의 총 주차면수 증가 + } ?: run { parkingRepository.save(to(data, ParkingStatus.to(data))) } } // 새로운 주차장인 경우 저장 + return null + } + + @Transactional + open fun loadDefaultTickets(): Void? { + parkingList.forEach { parking -> + val basicCharge = parking?.basicCharge?.takeIf { it != 0 } ?: 200 // 기본 요금 200원 + val basicChargeTime = parking?.basicChargeTime?.takeIf { it != 0 } ?: 5 // 기본 요금 시간 5분 + + intArrayOf(1, 2, 4, 6, 12).forEach { num -> // 1, 2, 4, 6, 12시간 주차권 생성 + val result = (basicCharge / basicChargeTime) * 60 * num + parking?.regTicket(Ticket.to(parking, result, num)) + } } + return null + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.kt index 01d631e..d6e6cd8 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/global/exception/NotFoundException.kt @@ -1,10 +1,7 @@ -package com.nbe2_3_3_team4.backend.global.exception; +package com.nbe2_3_3_team4.backend.global.exception -import lombok.Getter; -import lombok.RequiredArgsConstructor; +import lombok.Getter -@RequiredArgsConstructor @Getter -public class NotFoundException extends RuntimeException { - private final ErrorCode errorCode; +class NotFoundException(val errorCode: ErrorCode) : RuntimeException() { } diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index fa2a5b4..7f6a440 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -10,7 +10,7 @@ spring: jpa: hibernate: - ddl-auto: create + ddl-auto: update naming: physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy # 자바에서 카멜로 필드 작성하면 DB에 스네이크로 기록 From b23bd40bf5716e44a8b154359da189f33e90b8cd Mon Sep 17 00:00:00 2001 From: Dianuma <dltmdgus1208@gmail.com> Date: Fri, 24 Jan 2025 14:35:36 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat=20-=20=EC=A3=BC=EC=B0=A8=EC=9E=A5?= =?UTF-8?q?=EB=B3=84=20=EC=A3=BC=EC=B0=A8=EA=B6=8C=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/controller/ParkingController.kt | 17 +++++++++++------ .../domain/parking/service/ParkingService.kt | 19 ++++++++++++------- .../backend/domain/ticket/entity/Ticket.kt | 8 ++++---- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt index a4f8aff..3ef9579 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt @@ -2,6 +2,7 @@ package com.nbe2_3_3_team4.backend.controller import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.* import com.nbe2_3_3_team4.backend.domain.parking.service.ParkingService +import com.nbe2_3_3_team4.backend.domain.ticket.dto.TicketResponse.GetTicket import com.nbe2_3_3_team4.backend.global.response.ApiResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.Parameter @@ -28,9 +29,7 @@ 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))) } @@ -38,10 +37,16 @@ class ParkingController(val parkingService: ParkingService) { @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))) } + + @Operation(summary = "주차장 주차권 리스트 조회 API", description = "해당 주차장 주차권 정보를 수정합니다.") + @ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공")) + @GetMapping("/{parkingId}/tickets") + fun getTicketList(@PathVariable parkingId: Long): ResponseEntity<ApiResponse<List<GetTicket>>> { + return ResponseEntity.ok() + .body(ApiResponse.createSuccess(parkingService.getTicketList(parkingId))) + } } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt index 17dacc1..b568750 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt @@ -11,6 +11,7 @@ import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking.Companion.to import com.nbe2_3_3_team4.backend.domain.parking.entity.ParkingStatus import com.nbe2_3_3_team4.backend.domain.parking.repository.ParkingRepository +import com.nbe2_3_3_team4.backend.domain.ticket.dto.TicketResponse.GetTicket import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket import com.nbe2_3_3_team4.backend.global.exception.ErrorCode import com.nbe2_3_3_team4.backend.global.exception.NotFoundException @@ -27,21 +28,21 @@ val lowCongestion = 0.0..30.0 // 혼잡도 범위 여유 val mediumCongestion = 30.0..70.0 // 혼잡도 범위 보통 @Service -open class ParkingService( private val parkingRepository: ParkingRepository ) { +class ParkingService( private val parkingRepository: ParkingRepository ) { @get:Transactional(readOnly = true) - open val parkingList: List<Parking?> get() = parkingRepository.findAll().filterNotNull() // 주차장 목록 조회 + val parkingList: List<Parking?> get() = parkingRepository.findAll().filterNotNull() // 주차장 목록 조회 @Transactional(readOnly = true) - open fun getParking(parkingId: Long): GetParking = from( parkingRepository.findById(parkingId) // 주차장 조회 + fun getParking(parkingId: Long): GetParking = from( parkingRepository.findById(parkingId) // 주차장 조회 .orElseThrow { NotFoundException(ErrorCode.PKLT_NOT_FOUND) }!! ) // 예외 처리 @Transactional(readOnly = true) - open fun getParkingStatus(parkingId: Long): GetParkingStatus = from( parkingRepository.findById(parkingId) // 주차장 상태 조회 + fun getParkingStatus(parkingId: Long): GetParkingStatus = from( parkingRepository.findById(parkingId) // 주차장 상태 조회 .orElseThrow { NotFoundException(ErrorCode.PKLT_NOT_FOUND) }!!.parkingStatus!! ) // 예외 처리 @Transactional(readOnly = true) - open fun getNearbyParking(lat: Double, lng: Double): List<GetNearbyParking> = calculateCongestionAndSort(filterNearbyParking(parkingList, lat, lng)) // 주변 주차장 조회 + fun getNearbyParking(lat: Double, lng: Double): List<GetNearbyParking> = calculateCongestionAndSort(filterNearbyParking(parkingList, lat, lng)) // 주변 주차장 조회 private fun filterNearbyParking(parkingList: List<Parking?>, latitude: Double, longitude: Double): List<Parking?> { val lngDifference = latKm / (cos(latitude)) // 경도 차이 계산 @@ -66,7 +67,7 @@ open class ParkingService( private val parkingRepository: ParkingRepository ) { private fun ParkingStatus.getCongestionRate(): Double = usedParkingSpace.toDouble() / totalParkingSpace * 100 @Transactional - open fun loadDefaultDataByJson() { + fun loadDefaultDataByJson() { val objectMapper = ObjectMapper() val dataArray = objectMapper.readTree(ClassPathResource("static/data.json").file)["DATA"] @@ -77,7 +78,7 @@ open class ParkingService( private val parkingRepository: ParkingRepository ) { } @Transactional - open fun loadDefaultTickets() { + fun loadDefaultTickets() { parkingList.forEach { parking -> val basicCharge = parking?.basicCharge?.takeIf { it != 0 } ?: defaultCharge // 기본 요금 200원 val basicChargeTime = parking?.basicChargeTime?.takeIf { it != 0 } ?: defaultChargeTime // 기본 요금 시간 5분 @@ -87,4 +88,8 @@ open class ParkingService( private val parkingRepository: ParkingRepository ) { parking?.regTicket(Ticket.to(parking, result, num)) } } } + + @Transactional(readOnly = true) + fun getTicketList(parkingId: Long): List<GetTicket> = parkingRepository.findById(parkingId) + .orElseThrow { NotFoundException(ErrorCode.PKLT_NOT_FOUND) }!!.tickets.map { GetTicket.from(it) } // 주차장 주차권 목록 조회 } \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt index 93aa9b9..e3ee0f2 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt @@ -9,17 +9,17 @@ import jakarta.persistence.* class Ticket(parking: Parking?, price: Int?, parkingDuration: Int?) : BaseTime() { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private val id: Long? = null + val id: Long? = null @Column(name = "price") - private val price : Int? =null + val price : Int? =null @Column(name = "parking_duration") - private val parkingDuration : Int? =null + val parkingDuration : Int? =null @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parking_id") - private val parking: Parking? = null + val parking: Parking? = null companion object { fun to(parking: Parking?, price: Int, parkingDuration: Int): Ticket { From 51e83bd7653d067d49ff4c659397c7efe5623512 Mon Sep 17 00:00:00 2001 From: devPixel <oasis23ckr@gmail.com> Date: Fri, 24 Jan 2025 18:00:50 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat=20:=20Order/OrderDetail=20Entity,=20Or?= =?UTF-8?q?derService=20OrderRepository,=20OrderDetail=20,=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20DTO/Enum=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/member/entity/Member.kt | 2 +- .../member/repository/MemberRepository.kt | 2 +- .../backend/domain/order/dto/OrderRequest.kt | 14 ++ .../backend/domain/order/dto/OrderResponse.kt | 90 ++++++++++ .../backend/domain/order/entity/Order.kt | 63 +++++++ .../domain/order/entity/OrderDetail.kt | 29 +++ .../domain/order/entity/enum/OrderStatus.kt | 10 ++ .../domain/order/entity/enum/PaymentStatus.kt | 8 + .../order/repository/OrderDetailRepository.kt | 8 + .../order/repository/OrderRepository.kt | 11 ++ .../domain/order/service/OrderService.kt | 168 ++++++++++++++++++ .../backend/domain/parking/entity/Parking.kt | 2 +- .../domain/parking/entity/ParkingStatus.kt | 10 +- .../backend/domain/ticket/entity/Ticket.kt | 8 +- .../ticket/repository/TicketRepository.kt | 8 + 15 files changed, 425 insertions(+), 8 deletions(-) create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderRequest.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/OrderStatus.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/PaymentStatus.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderDetailRepository.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderRepository.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/repository/TicketRepository.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/entity/Member.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/entity/Member.kt index 4b1984a..3c6153c 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/entity/Member.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/entity/Member.kt @@ -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 diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/repository/MemberRepository.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/repository/MemberRepository.kt index d767e17..ce4ee3a 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/repository/MemberRepository.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/member/repository/MemberRepository.kt @@ -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> } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderRequest.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderRequest.kt new file mode 100644 index 0000000..c7c7fc0 --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderRequest.kt @@ -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 + ) +} diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt new file mode 100644 index 0000000..93e0eef --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt @@ -0,0 +1,90 @@ +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 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.toString()) { + "WAITING" -> "주차 대기" + "PARKING" -> "주차중" + "CANCELED" -> "환불" + else -> "주차 완료" + } + + return GetOrderHistory( + order.id, + parking.parkingId!!, + order.orderDetail.carNumber, + time, + status, + ticket.parkingDuration!!, + ticket.price!! + ) + } + } + } +} diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt new file mode 100644 index 0000000..b124a5d --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt @@ -0,0 +1,63 @@ +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.enum.OrderStatus +import com.nbe2_3_3_team4.backend.domain.order.entity.enum.PaymentStatus +import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket +import com.nbe2_3_3_team4.backend.global.BaseTime +import jakarta.persistence.* + +@Entity +@Table(name = "orders") +class Order( + @Id + @Column(name = "order_id") + val id: String, + + @Enumerated(EnumType.STRING) + var orderStatus: OrderStatus = OrderStatus.WAITING, + + @Enumerated(EnumType.STRING) + var paymentStatus: PaymentStatus = PaymentStatus.WAITING, + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "ticket_id") + val ticket: Ticket, + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + val member: Member, + + @OneToOne(fetch = FetchType.LAZY, cascade = [CascadeType.REMOVE], orphanRemoval = true) + @JoinColumn(name = "order_detail_id") + val orderDetail: OrderDetail, + + val paymentDate: String? = null, + val paymentKey: String? = null +) : BaseTime() { + + fun updatePaymentStatus(paymentStatus: PaymentStatus) { + this.paymentStatus = paymentStatus + } + + fun updateOrderStatus(orderStatus: OrderStatus) { + this.orderStatus = orderStatus + } + + companion object { + @JvmStatic + fun createOrder( + id: String, + ticket: Ticket, + member: Member, + orderDetail: OrderDetail + ): Order { + return Order( + id = id, + ticket = ticket, + member = member, + orderDetail = orderDetail + ) + } + } +} diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt new file mode 100644 index 0000000..6d4ad59 --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt @@ -0,0 +1,29 @@ +package com.nbe2_3_3_team4.backend.domain.order.entity + +import com.nbe2_3_3_team4.backend.global.BaseTime +import jakarta.persistence.* +import java.time.LocalDateTime + +@Entity +@Table(name = "order_details") +data class OrderDetail( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long? = null, // 기본값을 null로 설정하여 생성자를 통해 null을 받을 수 있게 함 + + val carNumber: String, + + val startParkingTime: LocalDateTime? = null, + val endParkingTime: LocalDateTime? = null, + val cancelPrice: Int? = null, + val addPrice: Int? = null, + + val totalPrice: Int +) : BaseTime() { + + companion object { + fun createOrderDetail(totalPrice: Int, carNumber: String): OrderDetail { + return OrderDetail(totalPrice = totalPrice, carNumber = carNumber) + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/OrderStatus.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/OrderStatus.kt new file mode 100644 index 0000000..885981e --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/OrderStatus.kt @@ -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 +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/PaymentStatus.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/PaymentStatus.kt new file mode 100644 index 0000000..747b577 --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/enum/PaymentStatus.kt @@ -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 +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderDetailRepository.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderDetailRepository.kt new file mode 100644 index 0000000..fc7a6ff --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderDetailRepository.kt @@ -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> { + +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderRepository.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderRepository.kt new file mode 100644 index 0000000..4fad5d6 --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/repository/OrderRepository.kt @@ -0,0 +1,11 @@ +package com.nbe2_3_3_team4.backend.domain.order.repository + +import com.nbe2_3_3_team4.backend.domain.member.entity.Member +import com.nbe2_3_3_team4.backend.domain.order.entity.Order +import org.springframework.data.jpa.repository.JpaRepository +import java.util.Optional + +interface OrderRepository : JpaRepository<Order, String> { + fun findByPaymentKey(paymentKey: String): Order? + fun findAllByMember(member: Member): Optional<List<Order>> +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt new file mode 100644 index 0000000..d26e968 --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt @@ -0,0 +1,168 @@ +package com.nbe2_3_3_team4.backend.domain.order.service + +import com.nbe2_3_3_team4.backend.domain.car.repository.CarRepository +import com.nbe2_3_3_team4.backend.domain.member.repository.MemberRepository +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.entity.Order +import com.nbe2_3_3_team4.backend.domain.order.entity.OrderDetail +import com.nbe2_3_3_team4.backend.domain.order.entity.enum.OrderStatus +import com.nbe2_3_3_team4.backend.domain.order.entity.enum.PaymentStatus +import com.nbe2_3_3_team4.backend.domain.order.repository.OrderDetailRepository +import com.nbe2_3_3_team4.backend.domain.order.repository.OrderRepository +import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking +import com.nbe2_3_3_team4.backend.domain.parking.entity.ParkingStatus +import com.nbe2_3_3_team4.backend.domain.ticket.repository.TicketRepository +import com.nbe2_3_3_team4.backend.global.exception.BadRequestException +import com.nbe2_3_3_team4.backend.global.exception.ErrorCode +import com.nbe2_3_3_team4.backend.global.exception.NotFoundException +import jakarta.transaction.Transactional +import org.springframework.stereotype.Service +import java.time.Duration +import java.time.LocalDateTime +import java.util.* + + +@Service +@Transactional +class OrderService( + private val orderRepository: OrderRepository, + private val orderDetailRepository: OrderDetailRepository, + private val memberRepository: MemberRepository, + private val ticketRepository: TicketRepository, + private val carRepository: CarRepository +) { + + private fun getRandomOrderId(): String = UUID.randomUUID().toString() + + fun createOrder(request: OrderRequest.CreateOrder, email: String): OrderResponse.CreateOrder { + // 회원 조회 + val member = memberRepository.findByEmail(email) + .orElseThrow { NotFoundException(ErrorCode.TICKET_NOT_FOUND) } + + // 해당 주차권 조회 + val ticket = ticketRepository.findById(request.ticketId) + .orElseThrow { NotFoundException(ErrorCode.TICKET_NOT_FOUND) } + + // 주차장 조회 + val parking = ticket!!.parking + val parkingStatus = parking?.parkingStatus + + // 새 주문에 부여할 새로운 UUID 생성 + val newOrderId = getRandomOrderId() + + val newOrder = if (isAvailable(parkingStatus!!)) { + val orderDetail = OrderDetail.createOrderDetail(ticket.price!!, request.carNumber) + orderDetailRepository.save(orderDetail) + + val order = Order.createOrder(newOrderId, ticket, member, orderDetail) + orderRepository.save(order) + order + } else { + throw BadRequestException(ErrorCode.PKLT_FULL) + } + + // 주차 현황 주차 차량수 추가 + parkingStatus.updateUsedParkingSpace() + + return OrderResponse.CreateOrder.from( + newOrder.id, ticket.id!!, member.id!!, request.carNumber + ) + } + + private fun isAvailable(parkingStatus: ParkingStatus): Boolean { + val totalParkingSpace = parkingStatus.totalParkingSpace + val usedParkingSpace = parkingStatus.usedParkingSpace + return (totalParkingSpace - usedParkingSpace) > 0 + } + + fun getOrder(orderId: String): OrderResponse { + val order = orderRepository.findById(orderId) + .orElseThrow { NotFoundException(ErrorCode.ORDER_NOT_FOUND) } + + val ticket = order!!.ticket + val parking = ticket!!.parking!! + val orderDetail = order.orderDetail + + // 입차 시간 조회 + val startParkingTime = orderDetail.startParkingTime + ?: throw BadRequestException(ErrorCode.NOT_PARKED) + + // 출차 시간 조회 + val endTime = orderDetail.endParkingTime ?: LocalDateTime.now() + val minutes = Duration.between(startParkingTime, endTime).toMinutes() + + val basePkDuration = ticket.parkingDuration!! * 60 + val addPkDuration = (minutes - basePkDuration).toInt() + + return if (addPkDuration <= 0) { + OrderResponse.from(parking, orderDetail, ticket, 0, 0) + } else { + val addPrice = calculateAdditionalPrice(parking, addPkDuration) + OrderResponse.from(parking, orderDetail, ticket, addPkDuration, addPrice) + } + } + + private fun calculateAdditionalPrice(parking: Parking, addPkDuration: Int): Int { + val price5Minute = (12.0 * parking.addCharge!! / 5) + return (addPkDuration / 5 * price5Minute).toInt() + } + + fun completePay(payId: String): String { + val order = orderRepository.findByPaymentKey(payId) + //.orElseThrow { NotFoundException(ErrorCode.ORDER_NOT_FOUND) } + ?: throw NotFoundException(ErrorCode.ORDER_NOT_FOUND) + + order.updatePaymentStatus(PaymentStatus.COMPLETE) + return order.id + } + + fun cancelTicket(email: String, orderId: String): String { + val order = orderRepository.findById(orderId) + .orElseThrow { NotFoundException(ErrorCode.ORDER_NOT_FOUND) } + + if (order.member.email != email) { + throw BadRequestException(ErrorCode.BAD_REQUEST) + } + + if (order.orderStatus == OrderStatus.WAITING) { + val refundMessage = if (order.createdAt!!.plusMinutes(10).isAfter(LocalDateTime.now())) { + order.updateOrderStatus(OrderStatus.CANCELED) + order.updatePaymentStatus(PaymentStatus.COMPLETE) + order.ticket.parking!!.parkingStatus!!.decreaseUsedParkingSpace() + "전액 환불되었습니다." + } else { + order.updateOrderStatus(OrderStatus.CANCELED) + order.updatePaymentStatus(PaymentStatus.COMPLETE) + order.ticket.parking!!.parkingStatus!!.decreaseUsedParkingSpace() + "구매 후 10분 이상이 경과되어 이용 금액의 50% 환불되었습니다." + } + return refundMessage + } + + throw BadRequestException(ErrorCode.ORDER_CANCEL_UNAVAILABLE) + } + + fun deleteOrder(id: String): Void? { + val order = orderRepository.findByPaymentKey(id) + ?: throw NotFoundException(ErrorCode.ORDER_NOT_FOUND) + + val parkingStatus = order.ticket.parking!!.parkingStatus + parkingStatus!!.decreaseUsedParkingSpace() + + orderRepository.delete(order) + return null + } + + fun getOrderHistory(email: String): List<OrderResponse.GetOrderHistory> { + val member = memberRepository.findByEmail(email) + .orElseThrow { NotFoundException(ErrorCode.USER_NOT_FOUND) } + + val orders = orderRepository.findAllByMember(member) + .orElseThrow { NotFoundException(ErrorCode.ORDER_NOT_FOUND) } + + return orders.map { order -> + OrderResponse.GetOrderHistory.from(order, order.ticket.parking!!, order.ticket) + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt index 25b2b31..a708e1d 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt @@ -11,7 +11,7 @@ class Parking() : BaseTime() { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "parking_id") - val parkingId: Long? = null + var parkingId: Long? = null @Column(name = "name") var name: String? = null diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt index 4945142..553285e 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/ParkingStatus.kt @@ -2,8 +2,8 @@ package com.nbe2_3_3_team4.backend.domain.parking.entity import com.fasterxml.jackson.databind.JsonNode -import java.time.LocalDateTime import jakarta.persistence.* +import java.time.LocalDateTime @Entity @Table(name = "parking_status") @@ -17,6 +17,14 @@ class ParkingStatus(var totalParkingSpace: Int, var usedParkingSpace: Int, priva this.totalParkingSpace += 1; } + fun updateUsedParkingSpace() { + this.usedParkingSpace +=1 + } + + fun decreaseUsedParkingSpace() { + this.usedParkingSpace -= 1 + } + companion object { @JvmStatic fun to(data: JsonNode): ParkingStatus { diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt index 93aa9b9..e3ee0f2 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/entity/Ticket.kt @@ -9,17 +9,17 @@ import jakarta.persistence.* class Ticket(parking: Parking?, price: Int?, parkingDuration: Int?) : BaseTime() { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private val id: Long? = null + val id: Long? = null @Column(name = "price") - private val price : Int? =null + val price : Int? =null @Column(name = "parking_duration") - private val parkingDuration : Int? =null + val parkingDuration : Int? =null @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parking_id") - private val parking: Parking? = null + val parking: Parking? = null companion object { fun to(parking: Parking?, price: Int, parkingDuration: Int): Ticket { diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/repository/TicketRepository.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/repository/TicketRepository.kt new file mode 100644 index 0000000..c173d21 --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/ticket/repository/TicketRepository.kt @@ -0,0 +1,8 @@ +package com.nbe2_3_3_team4.backend.domain.ticket.repository + +import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket +import org.springframework.data.jpa.repository.JpaRepository + +interface TicketRepository : JpaRepository< Ticket, Long >{ + +} \ No newline at end of file From 20c072d3e3c960ad62974d025348445f7ed0e64d Mon Sep 17 00:00:00 2001 From: devPixel <oasis23ckr@gmail.com> Date: Fri, 24 Jan 2025 19:21:38 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat=20:=20OrderController=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/controller/OrderController.kt | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt new file mode 100644 index 0000000..c5489f0 --- /dev/null +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt @@ -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.boot.autoconfigure.security.SecurityProperties +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +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: SecurityProperties.User + ): ResponseEntity<ApiResponse<OrderResponse.CreateOrder>> { + val response = orderService.createOrder(dto, user.name) + 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: SecurityProperties.User, + @PathVariable orderId: String + ): ResponseEntity<ApiResponse<String>> { + val response = orderService.cancelTicket(user.name, 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: SecurityProperties.User): ResponseEntity<ApiResponse<List<OrderResponse.GetOrderHistory>>> { + val response = orderService.getOrderHistory(user.name) + return ResponseEntity.ok(ApiResponse.createSuccess(response)) + } +} From b4dfef3db65f70e11902d20d461748ce7af83aad Mon Sep 17 00:00:00 2001 From: Dianuma <dltmdgus1208@gmail.com> Date: Mon, 27 Jan 2025 11:09:23 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[fix]=20=EA=B2=B0=EC=A0=9C=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A0=9C=EC=99=B8,=20=EC=9D=BC=EB=B6=80=20Error=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/controller/OrderController.kt | 14 +++++++------- .../backend/controller/ParkingController.kt | 9 --------- .../backend/domain/order/dto/OrderResponse.kt | 9 +++++---- .../backend/domain/order/entity/Order.kt | 2 ++ .../backend/domain/order/entity/OrderDetail.kt | 7 ++++--- .../backend/domain/order/service/OrderService.kt | 4 ++-- .../backend/domain/parking/entity/Parking.kt | 2 +- .../domain/parking/service/ParkingService.kt | 5 ----- 8 files changed, 21 insertions(+), 31 deletions(-) diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt index c5489f0..c7a951b 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/OrderController.kt @@ -7,9 +7,9 @@ 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.boot.autoconfigure.security.SecurityProperties 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.* @@ -26,9 +26,9 @@ class OrderController( @PostMapping("/tickets") fun createOrder( @RequestBody dto: OrderRequest.CreateOrder, - @AuthenticationPrincipal user: SecurityProperties.User + @AuthenticationPrincipal user: User ): ResponseEntity<ApiResponse<OrderResponse.CreateOrder>> { - val response = orderService.createOrder(dto, user.name) + val response = orderService.createOrder(dto, user.username) return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.createSuccess(response)) } @@ -52,10 +52,10 @@ class OrderController( @ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공")) @PutMapping("/{orderId}/cancel") fun cancelTicket( - @AuthenticationPrincipal user: SecurityProperties.User, + @AuthenticationPrincipal user: User, @PathVariable orderId: String ): ResponseEntity<ApiResponse<String>> { - val response = orderService.cancelTicket(user.name, orderId) + val response = orderService.cancelTicket(user.username, orderId) return ResponseEntity.ok(ApiResponse.createSuccess(response)) } @@ -67,8 +67,8 @@ class OrderController( @Operation(summary = "주차권 구매 기록 조회 API", description = "주차권 구매 기록을 조회합니다.") @ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공")) @GetMapping("/order-history") - fun getOrderHistory(@AuthenticationPrincipal user: SecurityProperties.User): ResponseEntity<ApiResponse<List<OrderResponse.GetOrderHistory>>> { - val response = orderService.getOrderHistory(user.name) + fun getOrderHistory(@AuthenticationPrincipal user: User): ResponseEntity<ApiResponse<List<OrderResponse.GetOrderHistory>>> { + val response = orderService.getOrderHistory(user.username) return ResponseEntity.ok(ApiResponse.createSuccess(response)) } } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt index 3ef9579..3cade25 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/controller/ParkingController.kt @@ -2,7 +2,6 @@ package com.nbe2_3_3_team4.backend.controller import com.nbe2_3_3_team4.backend.domain.parking.dto.ParkingResponse.* import com.nbe2_3_3_team4.backend.domain.parking.service.ParkingService -import com.nbe2_3_3_team4.backend.domain.ticket.dto.TicketResponse.GetTicket import com.nbe2_3_3_team4.backend.global.response.ApiResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.Parameter @@ -41,12 +40,4 @@ class ParkingController(val parkingService: ParkingService) { return ResponseEntity.ok() .body(ApiResponse.createSuccess(parkingService.getParkingStatus(parkingId))) } - - @Operation(summary = "주차장 주차권 리스트 조회 API", description = "해당 주차장 주차권 정보를 수정합니다.") - @ApiResponses(io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "성공")) - @GetMapping("/{parkingId}/tickets") - fun getTicketList(@PathVariable parkingId: Long): ResponseEntity<ApiResponse<List<GetTicket>>> { - return ResponseEntity.ok() - .body(ApiResponse.createSuccess(parkingService.getTicketList(parkingId))) - } } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt index 93e0eef..b57a9f1 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/dto/OrderResponse.kt @@ -4,6 +4,7 @@ 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( @@ -68,10 +69,10 @@ data class OrderResponse( val start = order.createdAt!! val formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 a h시 mm분") val time = start.format(formatter) - val status = when (order.orderStatus.toString()) { - "WAITING" -> "주차 대기" - "PARKING" -> "주차중" - "CANCELED" -> "환불" + val status = when (order.orderStatus) { + WAITING -> "주차 대기" + PARKING -> "주차중" + CANCELED -> "환불" else -> "주차 완료" } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt index b124a5d..c804f26 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/Order.kt @@ -32,7 +32,9 @@ class Order( @JoinColumn(name = "order_detail_id") val orderDetail: OrderDetail, + @Column(nullable = true) val paymentDate: String? = null, + @Column(nullable = true) val paymentKey: String? = null ) : BaseTime() { diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt index 6d4ad59..40acfc4 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/entity/OrderDetail.kt @@ -10,14 +10,15 @@ data class OrderDetail( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long? = null, // 기본값을 null로 설정하여 생성자를 통해 null을 받을 수 있게 함 - val carNumber: String, - + @Column(nullable = true) val startParkingTime: LocalDateTime? = null, + @Column(nullable = true) val endParkingTime: LocalDateTime? = null, + @Column(nullable = true) val cancelPrice: Int? = null, + @Column(nullable = true) val addPrice: Int? = null, - val totalPrice: Int ) : BaseTime() { diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt index d26e968..83ab03c 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/order/service/OrderService.kt @@ -81,7 +81,7 @@ class OrderService( .orElseThrow { NotFoundException(ErrorCode.ORDER_NOT_FOUND) } val ticket = order!!.ticket - val parking = ticket!!.parking!! + val parking = ticket.parking!! val orderDetail = order.orderDetail // 입차 시간 조회 @@ -104,7 +104,7 @@ class OrderService( } private fun calculateAdditionalPrice(parking: Parking, addPkDuration: Int): Int { - val price5Minute = (12.0 * parking.addCharge!! / 5) + val price5Minute = (12.0 * parking.addCharge / 5) return (addPkDuration / 5 * price5Minute).toInt() } diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt index 8dc5176..65b7cde 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/entity/Parking.kt @@ -10,7 +10,7 @@ data class Parking( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "parking_id") - var parkingId: Long? = null + var parkingId: Long? = null, @Column(name = "name") var name: String? = null, @Column(name = "address") diff --git a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt index b568750..1b0cefb 100644 --- a/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt +++ b/backend/src/main/java/com/nbe2_3_3_team4/backend/domain/parking/service/ParkingService.kt @@ -11,7 +11,6 @@ import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking import com.nbe2_3_3_team4.backend.domain.parking.entity.Parking.Companion.to import com.nbe2_3_3_team4.backend.domain.parking.entity.ParkingStatus import com.nbe2_3_3_team4.backend.domain.parking.repository.ParkingRepository -import com.nbe2_3_3_team4.backend.domain.ticket.dto.TicketResponse.GetTicket import com.nbe2_3_3_team4.backend.domain.ticket.entity.Ticket import com.nbe2_3_3_team4.backend.global.exception.ErrorCode import com.nbe2_3_3_team4.backend.global.exception.NotFoundException @@ -88,8 +87,4 @@ class ParkingService( private val parkingRepository: ParkingRepository ) { parking?.regTicket(Ticket.to(parking, result, num)) } } } - - @Transactional(readOnly = true) - fun getTicketList(parkingId: Long): List<GetTicket> = parkingRepository.findById(parkingId) - .orElseThrow { NotFoundException(ErrorCode.PKLT_NOT_FOUND) }!!.tickets.map { GetTicket.from(it) } // 주차장 주차권 목록 조회 } \ No newline at end of file