diff --git a/README.md b/README.md index 8ec09bd21..25148ae34 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,33 @@ -# airbnb -그룹 프로젝트 #4 +# airbnb ( 숙박업소 예약 어플리케이션 ) + +숙박 업소를 예약하는 앱 + +## [팀원소개, 팀자랑](https://github.com/dahun-lee-daji/airbnb/wiki/%ED%8C%80-%EC%86%8C%EA%B0%9C) + +## 기획 + +- [모바일 기획서](https://www.figma.com/proto/inTClwuq2Hr7E33JPIMKza/iOS_%EC%88%99%EC%86%8C%EC%98%88%EC%95%BD%EC%84%9C%EB%B9%84%EC%8A%A4?page-id=56%3A1424&node-id=56%3A1465&viewport=70%2C228%2C0.25&scaling=contain) +- [모바일 디자인](https://www.figma.com/file/inTClwuq2Hr7E33JPIMKza/iOS_%EC%88%99%EC%86%8C%EC%98%88%EC%95%BD%EC%84%9C%EB%B9%84%EC%8A%A4?node-id=1%3A133) + +## 커뮤니케이션 + +- 10시에 스크럼: 잡담 시간으로 잠깨우기 +- 유연하게 회의시간 가져가기! ( 보통 16시 )에 좀 서로 본격적인 이야기하기 + - 모바일 팀에서 추가된 API 요구사항 이야기해주기 + - 먼저 개발해 주었으면 좋겠는 API 우선순위도 이야기해주기 + +## [마일스톤 정책](https://github.com/dahun-lee-daji/airbnb/wiki/%EB%A7%88%EC%9D%BC%EC%8A%A4%ED%86%A4-%EC%A0%95%EC%B1%85) + +나누어진 Agile BackLog에 따라, Story의 하위 Task를 묶는 MileStone을 구성한다. + +## [이슈 정책](https://github.com/dahun-lee-daji/airbnb/wiki/%EB%A7%88%EC%9D%BC%EC%8A%A4%ED%86%A4-%EC%A0%95%EC%B1%85) + +`[BE|iOS] {요구사항 제목 or 구현할 기능의 제목}` + +## [브랜치 정책](https://github.com/dahun-lee-daji/airbnb/wiki/%EB%B8%8C%EB%9E%9C%EC%B9%98-%EC%A0%95%EC%B1%85) + +`{development part}/{branch header}/{issue number}/{short description}` + +## [커밋 메시지 정책](https://github.com/dahun-lee-daji/airbnb/wiki/%EC%BB%A4%EB%B0%8B-%EC%BB%A8%EB%B2%A4%EC%85%98) + +`{commit header}: {commit title} (#{issue number})` diff --git a/be/airbnb/.gitignore b/be/airbnb/.gitignore new file mode 100644 index 000000000..b098bb43d --- /dev/null +++ b/be/airbnb/.gitignore @@ -0,0 +1,142 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/java,intellij +# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# 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 +.idea/ + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries +build/ +.gradle/ + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. + .idea/artifacts + .idea/compiler.xml + .idea/jarRepositories.xml + .idea/modules.xml + .idea/*.iml + .idea/modules + *.iml + *.ipr + +# 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 + +# 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 + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +### Java ### +# 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* + +# End of https://www.toptal.com/developers/gitignore/api/java,intellij +/.idea/compiler.xml +/.idea/misc.xml +/.idea/vcs.xml +/.idea/libraries-with-intellij-classes.xml +/.idea/jarRepositories.xml +/.idea/.gitignore diff --git a/be/airbnb/HELP.md b/be/airbnb/HELP.md new file mode 100644 index 000000000..8acb11dda --- /dev/null +++ b/be/airbnb/HELP.md @@ -0,0 +1,26 @@ +# Getting Started + +### Reference Documentation +For further reference, please consider the following sections: + +* [Official Gradle documentation](https://docs.gradle.org) +* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.4.5/gradle-plugin/reference/html/) +* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.4.5/gradle-plugin/reference/html/#build-image) +* [Spring Data JDBC](https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/) +* [Spring Web](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#boot-features-developing-web-applications) +* [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#using-boot-devtools) + +### Guides +The following guides illustrate how to use some features concretely: + +* [Using Spring Data JDBC](https://github.com/spring-projects/spring-data-examples/tree/master/jdbc/basics) +* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) +* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) +* [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/) +* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/) + +### Additional Links +These additional references should also help you: + +* [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle) + diff --git a/be/airbnb/build.gradle b/be/airbnb/build.gradle new file mode 100644 index 000000000..66254be53 --- /dev/null +++ b/be/airbnb/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'org.springframework.boot' version '2.4.5' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'com.team19' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '1.8' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-web' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + runtimeOnly 'mysql:mysql-connector-java' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +test { + useJUnitPlatform() +} diff --git a/be/airbnb/gradle/wrapper/gradle-wrapper.jar b/be/airbnb/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e708b1c02 Binary files /dev/null and b/be/airbnb/gradle/wrapper/gradle-wrapper.jar differ diff --git a/be/airbnb/gradle/wrapper/gradle-wrapper.properties b/be/airbnb/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..442d9132e --- /dev/null +++ b/be/airbnb/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/be/airbnb/gradlew b/be/airbnb/gradlew new file mode 100644 index 000000000..4f906e0c8 --- /dev/null +++ b/be/airbnb/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/be/airbnb/gradlew.bat b/be/airbnb/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/be/airbnb/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/be/airbnb/settings.gradle b/be/airbnb/settings.gradle new file mode 100644 index 000000000..aab815121 --- /dev/null +++ b/be/airbnb/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'airbnb' diff --git a/be/airbnb/src/main/java/com/team19/airbnb/AirbnbApplication.java b/be/airbnb/src/main/java/com/team19/airbnb/AirbnbApplication.java new file mode 100644 index 000000000..2b1342eed --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/AirbnbApplication.java @@ -0,0 +1,12 @@ +package com.team19.airbnb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AirbnbApplication { + + public static void main(String[] args) { + SpringApplication.run(AirbnbApplication.class, args); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/ResponseBody.java b/be/airbnb/src/main/java/com/team19/airbnb/ResponseBody.java new file mode 100644 index 000000000..15e39f2cd --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/ResponseBody.java @@ -0,0 +1,22 @@ +package com.team19.airbnb; + +public class ResponseBody { + + private final T body; + + private ResponseBody(T body) { + this.body = body; + } + + public static ResponseBody ok(T body) { + return new ResponseBody<>(body); + } + + public static ResponseBody notFound(String message) { + return new ResponseBody<>(message); + } + + public T getBody() { + return body; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/controller/BookingController.java b/be/airbnb/src/main/java/com/team19/airbnb/controller/BookingController.java new file mode 100644 index 000000000..c5170d01c --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/controller/BookingController.java @@ -0,0 +1,40 @@ +package com.team19.airbnb.controller; + +import com.team19.airbnb.ResponseBody; +import com.team19.airbnb.dto.BookingRequestDTO; +import com.team19.airbnb.dto.BookingResponseDTO; +import com.team19.airbnb.service.BookingService; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RequestMapping("/bookings") +@RestController +public class BookingController { + + private final BookingService bookingService; + + public BookingController(BookingService bookingService) { + this.bookingService = bookingService; + } + + @GetMapping("/{bookingId}/{userId}") + public ResponseBody showBooking(@PathVariable Long bookingId, @PathVariable Long userId) { + return ResponseBody.ok(bookingService.showBooking(userId, bookingId)); + } + + @GetMapping("/{userId}") + public ResponseBody> showBookings(@PathVariable Long userId) { + return ResponseBody.ok(bookingService.showBookings(userId)); + } + + @PostMapping("/{userId}") + public void book(@RequestBody BookingRequestDTO bookingRequestDTO, @PathVariable Long userId) { + bookingService.book(bookingRequestDTO, userId); + } + + @DeleteMapping("/{bookingId}/{userId}") + public void deleteBooking(@PathVariable Long bookingId, @PathVariable Long userId) { + bookingService.cancelBooking(bookingId, userId); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/controller/MainController.java b/be/airbnb/src/main/java/com/team19/airbnb/controller/MainController.java new file mode 100644 index 000000000..17c7f876d --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/controller/MainController.java @@ -0,0 +1,22 @@ +package com.team19.airbnb.controller; + +import com.team19.airbnb.ResponseBody; +import com.team19.airbnb.dto.MainResponseDTO; +import com.team19.airbnb.service.MainService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class MainController { + + private final MainService mainService; + + public MainController(MainService mainService) { + this.mainService = mainService; + } + + @GetMapping("/main") + public ResponseBody main() { + return ResponseBody.ok(mainService.main()); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/controller/RoomController.java b/be/airbnb/src/main/java/com/team19/airbnb/controller/RoomController.java new file mode 100644 index 000000000..74dc8a768 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/controller/RoomController.java @@ -0,0 +1,45 @@ +package com.team19.airbnb.controller; + +import com.team19.airbnb.ResponseBody; +import com.team19.airbnb.dto.RoomDetailResponseDTO; +import com.team19.airbnb.dto.RoomPriceRequestDTO; +import com.team19.airbnb.dto.RoomPriceResponseDTO; +import com.team19.airbnb.domain.room.Host; +import com.team19.airbnb.dto.SearchRequestDTO; +import com.team19.airbnb.service.RoomService; +import org.springframework.web.bind.annotation.*; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RestController +public class RoomController { + + private final RoomService roomService; + + public RoomController(RoomService roomService) { + this.roomService = roomService; + } + + @GetMapping("/rooms/{roomId}") + public ResponseBody detailRoom(@PathVariable Long roomId) { + return ResponseBody.ok(roomService.showRoom(roomId)); + } + + @GetMapping("/rooms/{roomId}/price") + public RoomPriceResponseDTO detailRoomPopup(@ModelAttribute RoomPriceRequestDTO roomPriceRequestDTO, @PathVariable Long roomId) { + return roomService.showEstimate(roomPriceRequestDTO, roomId); + } + + @GetMapping("/rooms/price") + public List searchPriceRange(@RequestParam Double latitude, @RequestParam Double longitude ) { + return roomService.searchPriceRange(latitude, longitude); + } + + @GetMapping("/rooms") + public List searchRoomsByCondition(@ModelAttribute SearchRequestDTO searchRequestDTO) { + return roomService.searchRoomsByCondition(searchRequestDTO); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/controller/WishlistController.java b/be/airbnb/src/main/java/com/team19/airbnb/controller/WishlistController.java new file mode 100644 index 000000000..37e004772 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/controller/WishlistController.java @@ -0,0 +1,36 @@ +package com.team19.airbnb.controller; + +import com.team19.airbnb.ResponseBody; +import com.team19.airbnb.dto.RoomDetailResponseDTO; +import com.team19.airbnb.service.UserService; +import com.team19.airbnb.service.WishlistService; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +public class WishlistController { + + private final UserService userService; + private final WishlistService wishlistService; + + public WishlistController(UserService userService, WishlistService wishlistService) { + this.userService = userService; + this.wishlistService = wishlistService; + } + + @GetMapping("/wishlist/{userId}") + public ResponseBody> getWishList(@PathVariable Long userId) { + return ResponseBody.ok(userService.showWishLists(userId)); + } + + @PostMapping("/wishlist/{userId}") + public void postWishList(@RequestParam Long roomId, @PathVariable Long userId) { + wishlistService.addWishList(roomId, userId); + } + + @DeleteMapping("/wishlist/{userId}") + public void deleteWishList(@RequestParam Long roomId, @PathVariable Long userId) { + wishlistService.deleteWishlist(roomId, userId); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/Booking/Booking.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/Booking/Booking.java new file mode 100644 index 000000000..4d3cfe25d --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/Booking/Booking.java @@ -0,0 +1,150 @@ +package com.team19.airbnb.domain.Booking; + +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.PersistenceConstructor; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; + +public class Booking { + + @Id + private Long id; + + private LocalDate checkIn; + private LocalDate checkOut; + private Integer guest; + private BigDecimal totalPrice; + private Long user; + private Long room; + + @PersistenceConstructor + Booking(Long id, + LocalDate checkIn, LocalDate checkOut, + Integer guest, + BigDecimal totalPrice, + Long user, + Long room) { + this.id = id; + this.checkIn = checkIn; + this.checkOut = checkOut; + this.guest = guest; + this.totalPrice = totalPrice; + this.user = user; + this.room = room; + } + + Booking(Builder builder) { + this.id = builder.id; + this.checkIn = builder.checkIn; + this.checkOut = builder.checkOut; + this.guest = builder.guest; + this.totalPrice = builder.totalPrice; + this.user = builder.user; + this.room = builder.room; + } + + public static class Builder { + + private Long id; + + private LocalDate checkIn; + private LocalDate checkOut; + private Integer guest; + private BigDecimal totalPrice; + private Long user; + private Long room; + + public Builder() { + } + + public Builder id(Long id) { + this.id = id; + return this; + } + + public Builder checkIn(LocalDate checkIn) { + this.checkIn = checkIn; + return this; + } + + public Builder checkOut(LocalDate checkOut) { + this.checkOut = checkOut; + return this; + } + + public Builder guest(Integer guest) { + this.guest = guest; + return this; + } + + public Builder totalPrice(BigDecimal totalPrice) { + this.totalPrice = totalPrice; + return this; + } + + public Builder user(Long user) { + this.user = user; + return this; + } + + public Builder room(Long room) { + this.room = room; + return this; + } + + public Booking build() { + return new Booking(this); + } + } + + public Long getId() { + return id; + } + + public LocalDate getCheckIn() { + return checkIn; + } + + public LocalDate getCheckOut() { + return checkOut; + } + + public Integer getGuest() { + return guest; + } + + public BigDecimal getTotalPrice() { + return totalPrice; + } + + public Long getUser() { + return user; + } + + public Long getRoom() { + return room; + } + + public void setId(Long id) { + this.id = id; + } + + public void setUser(Long userId) { + this.user = userId; + } + + public boolean isUser(Long userId) { + return this.user.equals(userId); + } + + public BigDecimal calculateTotalPrice(BigDecimal roomPricePerDay) { + this.totalPrice = new Price.Builder(countDays(), roomPricePerDay).build().getTotalPrice(); + return totalPrice; + } + + public Long countDays() { + return ChronoUnit.DAYS.between(checkIn, checkOut); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/Booking/Price.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/Booking/Price.java new file mode 100644 index 000000000..128ae1864 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/Booking/Price.java @@ -0,0 +1,139 @@ +package com.team19.airbnb.domain.Booking; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class Price { + + private static final BigDecimal CLEANING_FEE_PERCENTAGE_FOR_ROOM = BigDecimal.valueOf(0.30); + private static final BigDecimal SERVICE_FEE_PERCENTAGE_FOR_ROOM = BigDecimal.valueOf(0.10); + private static final BigDecimal TAX_PERCENTAGE_FOR_TOTAL_PRICE = BigDecimal.valueOf(0.10); + private static final BigDecimal DISCOUNT_PERCENTAGE_FOR_WEEK = BigDecimal.valueOf(0.04); + private static final double DAYS_OF_A_WEEK = 0.7; + + private Long days; + private BigDecimal pricePerDay; + private BigDecimal basePrice; + + private BigDecimal discountPerWeek; + private BigDecimal cleaningFee; + private BigDecimal serviceFee; + private BigDecimal tax; + private BigDecimal totalPrice; + + public Price(Builder builder) { + this.days = builder.days; + this.pricePerDay = builder.pricePerDay; + this.basePrice = builder.basePrice; + this.discountPerWeek = builder.discountPerWeek; + this.cleaningFee = builder.cleaningFee; + this.serviceFee = builder.serviceFee; + this.tax = builder.tax; + this.totalPrice = builder.totalPrice; + } + + public static class Builder { + + private Long days; + private BigDecimal pricePerDay; + private BigDecimal basePrice; + + private BigDecimal discountPerWeek; + private BigDecimal cleaningFee; + private BigDecimal serviceFee; + private BigDecimal tax; + private BigDecimal totalPrice; + + public Builder(Long days, BigDecimal pricePerDay) { + this.days = days; + this.pricePerDay = pricePerDay; + this.basePrice = basePrice(); + + this.discountPerWeek = discountPerWeek(); + this.cleaningFee = cleaningFee(); + this.serviceFee = serviceFee(); + this.tax = calculateTax(); + this.totalPrice = totalPrice(); + } + + private BigDecimal basePrice() { + return pricePerDay.multiply(new BigDecimal(days)); + } + + private BigDecimal discountPerWeek() { + if (days < 7) { + return BigDecimal.ZERO; + } + + long discountDays = days - (days % 7); + return pricePerDay.multiply(new BigDecimal(discountDays)) + .multiply(DISCOUNT_PERCENTAGE_FOR_WEEK) + .setScale(0, RoundingMode.FLOOR); + } + + private BigDecimal cleaningFee() { + return pricePerDay.multiply(CLEANING_FEE_PERCENTAGE_FOR_ROOM) + .setScale(0, RoundingMode.FLOOR); + } + + private BigDecimal serviceFee() { + return pricePerDay.multiply(SERVICE_FEE_PERCENTAGE_FOR_ROOM) + .setScale(0, RoundingMode.FLOOR); + } + + private BigDecimal calculateTax() { + return basePrice.subtract(discountPerWeek) + .add(cleaningFee) + .add(serviceFee) + .multiply(TAX_PERCENTAGE_FOR_TOTAL_PRICE) + .setScale(0, RoundingMode.FLOOR); + } + + public BigDecimal totalPrice() { + return basePrice.subtract(discountPerWeek) + .add(cleaningFee) + .add(serviceFee) + .add(tax); + } + + public Price build() { + return new Price(this); + } + } + + public BigDecimal getPricePerDay() { + return pricePerDay; + } + + public BigDecimal getBasePrice() { + return basePrice; + } + + public BigDecimal getDiscountPerWeek() { + return discountPerWeek; + } + + public BigDecimal getCleaningFee() { + return cleaningFee; + } + + public BigDecimal getServiceFee() { + return serviceFee; + } + + public BigDecimal getTax() { + return tax; + } + + public BigDecimal getTotalPrice() { + return totalPrice; + } +} + + + + + + + + diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/User.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/User.java new file mode 100644 index 000000000..e358ff3f4 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/User.java @@ -0,0 +1,62 @@ +package com.team19.airbnb.domain; + +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.PersistenceConstructor; + +import java.util.ArrayList; +import java.util.List; + +public class User { + + @Id + private Long id; + + private String github; + private List wishlists; + + @PersistenceConstructor + User(Long id, String github, + List wishlists) { + this.id = id; + this.github = github; + this.wishlists = wishlists; + } + + User(String github) { + this.id = null; + this.github = github; + this.wishlists = new ArrayList<>(); + } + + public Long getId() { + return id; + } + + public String getGithub() { + return github; + } + + public List getWishlists() { + return wishlists; + } + + public void setId(Long id) { + this.id = id; + } + + public static User create(String github) { + return new User(github); + } + + public static User create(Long id, String github, List wishlists) { + return new User(id, github, wishlists); + } + + public void addWishlist(Wishlist wishlist) { + wishlists.add(wishlist); + } + + public void removeWishlist(Wishlist wishlist) { + wishlists.remove(wishlist); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/Wishlist.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/Wishlist.java new file mode 100644 index 000000000..127ee6745 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/Wishlist.java @@ -0,0 +1,35 @@ +package com.team19.airbnb.domain; + +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.PersistenceConstructor; + +public class Wishlist { + + @Id + private Long id; + + private Long room; + + @PersistenceConstructor + Wishlist(Long id, Long room) { + this.id = id; + this.room = room; + } + + Wishlist(Long room) { + this.id = null; + this.room = room; + } + + public static Wishlist create(Long id, Long room) { + return new Wishlist(id, room); + } + + public static Wishlist create(Long room) { + return new Wishlist(room); + } + + public Long getRoom() { + return room; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/main/HeroBanner.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/main/HeroBanner.java new file mode 100644 index 000000000..41f8048f6 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/main/HeroBanner.java @@ -0,0 +1,30 @@ +package com.team19.airbnb.domain.main; + +import org.springframework.data.annotation.Id; + +public class HeroBanner { + + @Id + private Long id; + + private String title; + private String image; + + HeroBanner(Long id, String title, String image) { + this.id = id; + this.title = title; + this.image = image; + } + + public static HeroBanner create(Long id, String title, String image) { + return new HeroBanner(id, title, image); + } + + public String getTitle() { + return title; + } + + public String getImage() { + return image; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/main/NearDestination.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/main/NearDestination.java new file mode 100644 index 000000000..bad54d6ea --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/main/NearDestination.java @@ -0,0 +1,42 @@ +package com.team19.airbnb.domain.main; + +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.data.annotation.Id; + +import java.sql.Time; +import java.time.LocalTime; + +public class NearDestination { + + @Id + private Long id; + + private String destination; + + @JsonFormat(pattern = "HH:mm") + private LocalTime timeDistance; + private String image; + + NearDestination(Long id, String destination, LocalTime timeDistance, String image) { + this.id = id; + this.destination = destination; + this.timeDistance = timeDistance; + this.image = image; + } + + public static NearDestination create(Long id, String destination, LocalTime timeDistance, String image) { + return new NearDestination(id, destination, timeDistance, image); + } + + public String getDestination() { + return destination; + } + + public LocalTime getTimeDistance() { + return timeDistance; + } + + public String getImage() { + return image; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Host.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Host.java new file mode 100644 index 000000000..a01ac3bde --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Host.java @@ -0,0 +1,24 @@ +package com.team19.airbnb.domain.room; + +public class Host { + + private String hostName; + private String hostImage; + + Host(String hostName, String hostImage) { + this.hostName = hostName; + this.hostImage = hostImage; + } + + public static Host create(String hostName, String hostImage) { + return new Host(hostName, hostImage); + } + + public String getHostName() { + return hostName; + } + + public String getHostImage() { + return hostImage; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Image.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Image.java new file mode 100644 index 000000000..6c33a8568 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Image.java @@ -0,0 +1,18 @@ +package com.team19.airbnb.domain.room; + +public class Image { + + private String url; + + Image(String url) { + this.url = url; + } + + public static Image create(String url) { + return new Image(url); + } + + public String getUrl() { + return url; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Location.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Location.java new file mode 100644 index 000000000..0ed8ee129 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Location.java @@ -0,0 +1,30 @@ +package com.team19.airbnb.domain.room; + +public class Location { + + private String address; + private Double latitude; + private Double longitude; + + Location(String address, Double latitude, Double longitude) { + this.address = address; + this.latitude = latitude; + this.longitude = longitude; + } + + public static Location create(String address, Double latitude, Double longitude) { + return new Location(address, latitude, longitude); + } + + public String getAddress() { + return address; + } + + public Double getLatitude() { + return latitude; + } + + public Double getLongitude() { + return longitude; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Review.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Review.java new file mode 100644 index 000000000..26756ff8e --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Review.java @@ -0,0 +1,24 @@ +package com.team19.airbnb.domain.room; + +public class Review { + + private Double grade; + private Integer reviewer; + + Review(Double grade, Integer reviewer) { + this.grade = grade; + this.reviewer = reviewer; + } + + public static Review create(Double grade, Integer reviewers) { + return new Review(grade, reviewers); + } + + public Double getGrade() { + return grade; + } + + public Integer getReviewer() { + return reviewer; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Room.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Room.java new file mode 100644 index 000000000..81f868e12 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/Room.java @@ -0,0 +1,124 @@ +package com.team19.airbnb.domain.room; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Embedded; + +import java.math.BigDecimal; +import java.util.List; + +public class Room { + + @Id + private Long id; + + private String name; + private List images; + + @Embedded.Empty + private Review review; + + @Embedded.Empty + private Location location; + + private String roomType; + + @Embedded.Empty + private RoomsAndBeds roomsAndBeds; + private String description; + + @Embedded.Empty + private Host host; + + private BigDecimal pricePerDay; + + private Integer capacity; + + public Room() { + } + + Room(Long id, + String name, List images, + Review review, + Location location, + String roomType, RoomsAndBeds roomsAndBeds, String description, + Host host, + BigDecimal pricePerDay, + Integer capacity) { + this.id = id; + this.name = name; + this.images = images; + this.review = review; + this.location = location; + this.roomType = roomType; + this.roomsAndBeds = roomsAndBeds; + this.description = description; + this.host = host; + this.pricePerDay = pricePerDay; + this.capacity = capacity; + } + + public static Room create(Long id, + String name, List images, + Review review, + Location location, + RoomType roomType, RoomsAndBeds roomsAndBeds, String description, + Host host, + BigDecimal pricePerDay, + Integer capacity) { + return new Room(id, + name, images, + review, location, + roomType.name(), roomsAndBeds, description, + host, + pricePerDay, + capacity); + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public List getImages() { + return images; + } + + public Review getReview() { + return review; + } + + public Location getLocation() { + return location; + } + + public String getRoomType() { + return roomType; + } + + public RoomsAndBeds getRoomsAndBeds() { + return roomsAndBeds; + } + + public String getDescription() { + return description; + } + + public Host getHost() { + return host; + } + + public BigDecimal getPricePerDay() { + return pricePerDay; + } + + public Integer getCapacity() { + return capacity; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/room/RoomType.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/RoomType.java new file mode 100644 index 000000000..159d0441b --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/RoomType.java @@ -0,0 +1,19 @@ +package com.team19.airbnb.domain.room; + +public enum RoomType { + + ENTIRE_PLACE("집전체"), + PRIVATE_ROOM("개인실"), + HOTEL_ROOM("호텔객실"), + SHARED_ROOM("다인실"); + + private final String korean; + + RoomType(String korean) { + this.korean = korean; + } + + public String getKorean() { + return korean; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/domain/room/RoomsAndBeds.java b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/RoomsAndBeds.java new file mode 100644 index 000000000..4eb54967d --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/domain/room/RoomsAndBeds.java @@ -0,0 +1,30 @@ +package com.team19.airbnb.domain.room; + +public class RoomsAndBeds { + + private int bed; + private int bedRoom; + private int bathRoom; + + RoomsAndBeds(int bed, int bedRoom, int bathRoom) { + this.bed = bed; + this.bedRoom = bedRoom; + this.bathRoom = bathRoom; + } + + public static RoomsAndBeds create(int bed, int bedRoom, int bathRoom) { + return new RoomsAndBeds(bed, bedRoom, bathRoom); + } + + public int getBed() { + return bed; + } + + public int getBedRoom() { + return bedRoom; + } + + public int getBathRoom() { + return bathRoom; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/dto/BookingRequestDTO.java b/be/airbnb/src/main/java/com/team19/airbnb/dto/BookingRequestDTO.java new file mode 100644 index 000000000..4a3cfce56 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/dto/BookingRequestDTO.java @@ -0,0 +1,39 @@ +package com.team19.airbnb.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.team19.airbnb.domain.Booking.Booking; + +import java.math.BigDecimal; +import java.time.LocalDate; + +public class BookingRequestDTO { + + @JsonProperty("roomId") + private Long roomId; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate checkIn; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate checkOut; + + @JsonProperty("personnel") + private Integer guest; + + @JsonProperty("totalPrice") + private BigDecimal totalPrice; + + public BookingRequestDTO() { + } + + public Booking toEntity() { + return new Booking.Builder() + .checkIn(checkIn) + .checkOut(checkOut) + .guest(guest) + .totalPrice(totalPrice) + .room(roomId) + .build(); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/dto/BookingResponseDTO.java b/be/airbnb/src/main/java/com/team19/airbnb/dto/BookingResponseDTO.java new file mode 100644 index 000000000..07a023f7f --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/dto/BookingResponseDTO.java @@ -0,0 +1,100 @@ +package com.team19.airbnb.dto; + +import com.team19.airbnb.domain.Booking.Booking; +import com.team19.airbnb.domain.room.Host; +import com.team19.airbnb.domain.room.Image; +import com.team19.airbnb.domain.room.Room; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + +public class BookingResponseDTO { + + private final Long bookingId; + private final LocalDate checkIn; + private final LocalDate checkOut; + private final Integer guest; + private final BigDecimal totalPrice; + + private final Long roomId; + private final String roomName; + private final List images; + private final String roomType; + private final Host host; + + private BookingResponseDTO(Long bookingId, + LocalDate checkIn, LocalDate checkOut, + Integer guest, + BigDecimal totalPrice, + Long roomId, + String roomName, List images, + String roomType, + Host host) { + this.bookingId = bookingId; + this.checkIn = checkIn; + this.checkOut = checkOut; + this.guest = guest; + this.totalPrice = totalPrice; + this.roomId = roomId; + this.roomName = roomName; + this.images = images; + this.roomType = roomType; + this.host = host; + } + + public static BookingResponseDTO create(Booking booking, Room room) { + return new BookingResponseDTO(booking.getId(), + booking.getCheckIn(), booking.getCheckOut(), + booking.getGuest(), + booking.getTotalPrice(), + room.getId(), + room.getName(), + room.getImages().stream() + .map(Image::getUrl) + .collect(Collectors.toList()), + room.getRoomType(), + room.getHost()); + } + + public Long getBookingId() { + return bookingId; + } + + public LocalDate getCheckIn() { + return checkIn; + } + + public LocalDate getCheckOut() { + return checkOut; + } + + public BigDecimal getTotalPrice() { + return totalPrice; + } + + public Long getRoomId() { + return roomId; + } + + public String getRoomName() { + return roomName; + } + + public String getRoomType() { + return roomType; + } + + public List getImages() { + return images; + } + + public Host getHost() { + return host; + } + + public Integer getGuest() { + return guest; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/dto/MainResponseDTO.java b/be/airbnb/src/main/java/com/team19/airbnb/dto/MainResponseDTO.java new file mode 100644 index 000000000..298fc924f --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/dto/MainResponseDTO.java @@ -0,0 +1,29 @@ +package com.team19.airbnb.dto; + +import com.team19.airbnb.domain.main.HeroBanner; +import com.team19.airbnb.domain.main.NearDestination; + +import java.util.List; + +public class MainResponseDTO { + + private List heroBanners; + private List nearDestinations; + + private MainResponseDTO(List heroBanners, List nearDestinations) { + this.heroBanners = heroBanners; + this.nearDestinations = nearDestinations; + } + + public static MainResponseDTO create(List heroBanners, List nearDestinations) { + return new MainResponseDTO(heroBanners, nearDestinations); + } + + public List getHeroBanners() { + return heroBanners; + } + + public List getNearDestinations() { + return nearDestinations; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomDetailResponseDTO.java b/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomDetailResponseDTO.java new file mode 100644 index 000000000..3a4e9669b --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomDetailResponseDTO.java @@ -0,0 +1,185 @@ +package com.team19.airbnb.dto; + +import com.team19.airbnb.domain.room.*; + +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; + +public class RoomDetailResponseDTO { + + private Long roomId; + + private String roomName; + + private List images; + + private Double grade; + private Integer reviewer; + + private String location; + private Double[] coordinate; + + private String roomType; + private String roomConfiguration; + private String description; + + private Host host; + + private BigDecimal pricePerDay; + + private BigDecimal totalPrice; + + public RoomDetailResponseDTO() { + } + + private RoomDetailResponseDTO(Builder builder) { + + this.roomId = builder.roomId; + + this.roomName = builder.roomName; + + this.images = builder.images; + + this.grade = builder.grade; + this.reviewer = builder.reviewer; + + this.location = builder.location; + this.coordinate = builder.coordinate; + + this.roomType = builder.roomType; + this.roomConfiguration = builder.roomConfiguration; + ; + this.description = builder.description; + + this.host = builder.host; + + this.pricePerDay = builder.pricePerDay; + this.totalPrice = builder.totalPrice; + } + + public static class Builder { + + private final Long roomId; + + private final String roomName; + private final List images; + + private final Double grade; + private final Integer reviewer; + + private final String location; + private final Double[] coordinate; + + private final String roomType; + private final String roomConfiguration; + private final String description; + + private final Host host; + + private final BigDecimal pricePerDay; + private BigDecimal totalPrice; + + public Builder(Room room) { + this.roomId = room.getId(); + + this.roomName = room.getName(); + this.images = room.getImages().stream() + .map(Image::getUrl) + .collect(Collectors.toList()); + + this.grade = room.getReview().getGrade(); + this.reviewer = room.getReview().getReviewer(); + + this.location = room.getLocation().getAddress(); + this.coordinate = coordinate(room.getLocation()); + + this.roomType = room.getRoomType(); + this.roomConfiguration = roomConfiguration(room.getRoomsAndBeds()); + this.description = room.getDescription(); + + this.host = room.getHost(); + + this.pricePerDay = room.getPricePerDay(); + this.totalPrice = BigDecimal.ZERO; + } + + private Double[] coordinate(Location location) { + Double[] coordinate = new Double[2]; + coordinate[0] = location.getLatitude(); + coordinate[1] = location.getLongitude(); + return coordinate; + } + + private String roomConfiguration(RoomsAndBeds roomsAndBeds) { + StringBuilder stringBuilder = new StringBuilder(); + return String.valueOf(stringBuilder.append("침구 : ") + .append(roomsAndBeds.getBed()) + .append(" 침실 : ") + .append(roomsAndBeds.getBedRoom()) + .append(" 욕실: ") + .append(roomsAndBeds.getBathRoom())); + } + + public Builder totalPrice(BigDecimal totalPrice) { + this.totalPrice = totalPrice; + return this; + } + + public RoomDetailResponseDTO build() { + return new RoomDetailResponseDTO(this); + } + } + + public Long getRoomId() { + return roomId; + } + + public String getRoomName() { + return roomName; + } + + public List getImages() { + return images; + } + + public Double getGrade() { + return grade; + } + + public Integer getReviewer() { + return reviewer; + } + + public String getLocation() { + return location; + } + + public Double[] getCoordinate() { + return coordinate; + } + + public String getRoomType() { + return roomType; + } + + public String getRoomConfiguration() { + return roomConfiguration; + } + + public String getDescription() { + return description; + } + + public Host getHost() { + return host; + } + + public BigDecimal getPricePerDay() { + return pricePerDay; + } + + public BigDecimal getTotalPrice() { + return totalPrice; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomPriceRequestDTO.java b/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomPriceRequestDTO.java new file mode 100644 index 000000000..5f0add438 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomPriceRequestDTO.java @@ -0,0 +1,52 @@ +package com.team19.airbnb.dto; + +import com.team19.airbnb.domain.Booking.Booking; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; + +public class RoomPriceRequestDTO { + + private Long roomId; + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate checkIn; + + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate checkOut; + + private Integer guest; + + public RoomPriceRequestDTO(Long roomId, + LocalDate checkIn, LocalDate checkOut, + int guest) { + this.roomId = roomId; + this.checkIn = checkIn; + this.checkOut = checkOut; + this.guest = guest; + } + + public void setRoomId(Long roomId) { + this.roomId = roomId; + } + + public void setCheckIn(LocalDate checkIn) { + this.checkIn = checkIn; + } + + public void setCheckOut(LocalDate checkOut) { + this.checkOut = checkOut; + } + + public void setGuest(Integer guest) { + this.guest = guest; + } + + public Booking toEntity(Long roomId) { + return new Booking.Builder() + .checkIn(checkIn) + .checkOut(checkOut) + .guest(guest) + .room(roomId) + .build(); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomPriceResponseDTO.java b/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomPriceResponseDTO.java new file mode 100644 index 000000000..713ef2aa2 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/dto/RoomPriceResponseDTO.java @@ -0,0 +1,54 @@ +package com.team19.airbnb.dto; + +import com.team19.airbnb.domain.Booking.Price; + +import java.math.BigDecimal; + +public class RoomPriceResponseDTO { + + private BigDecimal discountPerWeek; + private BigDecimal cleaningFee; + private BigDecimal serviceFee; + private BigDecimal tax; + private BigDecimal totalPrice; + + private RoomPriceResponseDTO(BigDecimal discountPerWeek, + BigDecimal cleaningFee, + BigDecimal serviceFee, + BigDecimal tax, + BigDecimal totalPrice) { + this.discountPerWeek = discountPerWeek; + this.cleaningFee = cleaningFee; + this.serviceFee = serviceFee; + this.tax = tax; + this.totalPrice = totalPrice; + } + + public static RoomPriceResponseDTO create(Price price) { + return new RoomPriceResponseDTO(price.getDiscountPerWeek(), + price.getCleaningFee(), + price.getServiceFee(), + price.getTax(), + price.getTotalPrice()); + } + + public BigDecimal getDiscountPerWeek() { + return discountPerWeek; + } + + public BigDecimal getCleaningFee() { + return cleaningFee; + } + + public BigDecimal getServiceFee() { + return serviceFee; + } + + public BigDecimal getTax() { + return tax; + } + + public BigDecimal getTotalPrice() { + return totalPrice; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/dto/SearchRequestDTO.java b/be/airbnb/src/main/java/com/team19/airbnb/dto/SearchRequestDTO.java new file mode 100644 index 000000000..cf8ec2363 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/dto/SearchRequestDTO.java @@ -0,0 +1,107 @@ +package com.team19.airbnb.dto; + +import com.team19.airbnb.domain.Booking.Booking; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.lang.Nullable; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Arrays; + +public class SearchRequestDTO { + + private Double[] coordinate; + + @Nullable + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate checkIn; + + @Nullable + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate checkOut; + + @Nullable + private BigDecimal minPrice; + + @Nullable + private BigDecimal maxPrice; + + @Nullable + private Integer guest; //adult + child , toddler x + + public SearchRequestDTO(Double[] coordinate, + LocalDate checkIn, LocalDate checkOut, + BigDecimal minPrice, BigDecimal maxPrice, + Integer guest) { + this.coordinate = coordinate; + this.checkIn = checkIn; + this.checkOut = checkOut; + this.minPrice = minPrice; + this.maxPrice = maxPrice; + this.guest = guest; + } + + public Double[] getCoordinate() { + return coordinate; + } + + public LocalDate getCheckIn() { + return checkIn; + } + + public LocalDate getCheckOut() { + return checkOut; + } + + public BigDecimal getMinPrice() { + return minPrice; + } + + public BigDecimal getMaxPrice() { + return maxPrice; + } + + public Integer getGuest() { + return guest; + } + + public void setCheckIn(LocalDate checkIn) { + this.checkIn = checkIn; + } + + public void setCheckOut(LocalDate checkOut) { + this.checkOut = checkOut; + } + + public void setMinPrice(BigDecimal minPrice) { + this.minPrice = minPrice; + } + + public void setMaxPrice(BigDecimal maxPrice) { + this.maxPrice = maxPrice; + } + + public void setGuest(Integer guest) { + this.guest = guest; + } + + public Booking toBooking() { + return new Booking.Builder() + .checkIn(checkIn) + .checkOut(checkOut) + .guest(guest) + .build(); + } + + @Override + public String toString() { + return "SearchRequestDTO{" + + "coordinate=" + Arrays.toString(coordinate) + + ", checkIn=" + checkIn + + ", checkOut=" + checkOut + + ", minPrice=" + minPrice + + ", maxPrice=" + maxPrice + + ", guest=" + guest + + '}'; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/exception/AirbnbExceptionHandler.java b/be/airbnb/src/main/java/com/team19/airbnb/exception/AirbnbExceptionHandler.java new file mode 100644 index 000000000..6eff3319b --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/exception/AirbnbExceptionHandler.java @@ -0,0 +1,31 @@ +package com.team19.airbnb.exception; + +import com.team19.airbnb.ResponseBody; +import com.team19.airbnb.exception.notauthorized.NotAuthorizedException; +import com.team19.airbnb.exception.notfound.NotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ControllerAdvice +public class AirbnbExceptionHandler { + + private static final Logger logger = LoggerFactory.getLogger(AirbnbExceptionHandler.class); + + @ExceptionHandler(NotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ResponseBody handleNotFoundException(NotFoundException e) { + logger.error(e.getMessage()); + return ResponseBody.notFound(e.getMessage()); + } + + @ExceptionHandler(NotAuthorizedException.class) + @ResponseStatus(HttpStatus.FORBIDDEN) + public ResponseBody handleNotAuthorizedException(NotAuthorizedException e) { + logger.error(e.getMessage()); + return ResponseBody.notFound(e.getMessage()); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/exception/notauthorized/NotAuthorizedException.java b/be/airbnb/src/main/java/com/team19/airbnb/exception/notauthorized/NotAuthorizedException.java new file mode 100644 index 000000000..cda7cf8be --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/exception/notauthorized/NotAuthorizedException.java @@ -0,0 +1,8 @@ +package com.team19.airbnb.exception.notauthorized; + +public class NotAuthorizedException extends RuntimeException { + + public NotAuthorizedException(String message) { + super(message); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/BookingNotFoundException.java b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/BookingNotFoundException.java new file mode 100644 index 000000000..3efc62bc3 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/BookingNotFoundException.java @@ -0,0 +1,8 @@ +package com.team19.airbnb.exception.notfound; + +public class BookingNotFoundException extends NotFoundException { + + public BookingNotFoundException() { + super("해당하는 예약을 찾을 수 없습니다."); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/ConditionNotFoundException.java b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/ConditionNotFoundException.java new file mode 100644 index 000000000..54d261732 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/ConditionNotFoundException.java @@ -0,0 +1,8 @@ +package com.team19.airbnb.exception.notfound; + +public class ConditionNotFoundException extends NotFoundException { + + public ConditionNotFoundException() { + super("조건이 없습니다. 조건은 최소한 1개 이상 입력해주세요."); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/NotFoundException.java b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/NotFoundException.java new file mode 100644 index 000000000..f34526756 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/NotFoundException.java @@ -0,0 +1,8 @@ +package com.team19.airbnb.exception.notfound; + +public class NotFoundException extends RuntimeException { + + public NotFoundException(String message) { + super(message); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/RoomNotFoundException.java b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/RoomNotFoundException.java new file mode 100644 index 000000000..f5b3c7cf1 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/RoomNotFoundException.java @@ -0,0 +1,8 @@ +package com.team19.airbnb.exception.notfound; + +public class RoomNotFoundException extends NotFoundException { + + public RoomNotFoundException() { + super("해당하는 room을 찾을 수 없습니다"); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/UserNotFoundException.java b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/UserNotFoundException.java new file mode 100644 index 000000000..6b794e5bc --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/exception/notfound/UserNotFoundException.java @@ -0,0 +1,8 @@ +package com.team19.airbnb.exception.notfound; + +public class UserNotFoundException extends NotFoundException { + + public UserNotFoundException() { + super("해당하는 user를 찾을 수 없습니다"); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/repository/BookingDAO.java b/be/airbnb/src/main/java/com/team19/airbnb/repository/BookingDAO.java new file mode 100644 index 000000000..20a21fc2b --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/repository/BookingDAO.java @@ -0,0 +1,64 @@ +package com.team19.airbnb.repository; + +import com.team19.airbnb.domain.Booking.Booking; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +@Repository +public class BookingDAO { + + private final JdbcTemplate jdbcTemplate; + + public BookingDAO(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + public Booking save(Booking booking) { + SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate); + jdbcInsert.withTableName("booking").usingGeneratedKeyColumns("id"); + + SqlParameterSource sqlParameterSource = new BeanPropertySqlParameterSource(booking); + Number key = jdbcInsert.executeAndReturnKey(sqlParameterSource); + booking.setId(key.longValue()); + return booking; + } + + public Optional findById(Long id) { + String selectById = "SELECT `id`, `check_in`, `check_out`, `guest`, `total_price`, `user`, `room` FROM `booking` WHERE `id` = ?"; + List result = jdbcTemplate.query(selectById, bookingRowMapper(), id); + return result.stream().findAny(); + } + + public List findAllByUser(Long user) { + String findAllByUser = "SELECT `id`, `check_in`, `check_out`, `guest`, `total_price`, `user`, `room` FROM `booking` WHERE `user` = ?"; + return jdbcTemplate.query(findAllByUser, bookingRowMapper(), user); + } + + public void delete(Long bookingId) { + String query = "DELETE FROM `booking` WHERE `id` = ? "; + jdbcTemplate.update(query, bookingId); + } + + private RowMapper bookingRowMapper() { + return (rs, rowNum) -> { + return new Booking.Builder() + .id(rs.getLong("id")) + .checkIn(rs.getObject("check_in", LocalDate.class)) + .checkOut(rs.getObject("check_out", LocalDate.class)) + .guest(rs.getInt("guest")) + .totalPrice(rs.getBigDecimal("total_price")) + .user(rs.getLong("user")) + .room(rs.getLong("room")) + .build(); + }; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/repository/HeroBannerDAO.java b/be/airbnb/src/main/java/com/team19/airbnb/repository/HeroBannerDAO.java new file mode 100644 index 000000000..96ee33c13 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/repository/HeroBannerDAO.java @@ -0,0 +1,32 @@ +package com.team19.airbnb.repository; + +import com.team19.airbnb.domain.main.HeroBanner; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.util.List; + +@Repository +public class HeroBannerDAO{ + + private final JdbcTemplate jdbcTemplate; + + public HeroBannerDAO(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public List findAll() { + String selectAll = "SELECT `id`, `title`, `image` FROM `hero_banner`"; + return jdbcTemplate.query(selectAll, heroBannerRowMapper()); + } + + private RowMapper heroBannerRowMapper() { + return (rs, rowNum) -> { + return HeroBanner.create(rs.getLong("id"), + rs.getString("title"), + rs.getString("image")); + }; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/repository/ImageDAO.java b/be/airbnb/src/main/java/com/team19/airbnb/repository/ImageDAO.java new file mode 100644 index 000000000..f87fe0aa9 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/repository/ImageDAO.java @@ -0,0 +1,30 @@ +package com.team19.airbnb.repository; + +import com.team19.airbnb.domain.room.Image; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.util.List; + +@Repository +public class ImageDAO { + + private final JdbcTemplate jdbcTemplate; + + public ImageDAO(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public List findAllByRoom(Long room) { + String selectByUser = "SELECT `url` FROM `image` WHERE `room` = ?"; + return jdbcTemplate.query(selectByUser, imageRowMapper(), room); + } + + private RowMapper imageRowMapper() { + return (rs, rowNum) -> { + return Image.create(rs.getString("url")); + }; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/repository/NearDestinationDAO.java b/be/airbnb/src/main/java/com/team19/airbnb/repository/NearDestinationDAO.java new file mode 100644 index 000000000..449a20e23 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/repository/NearDestinationDAO.java @@ -0,0 +1,35 @@ +package com.team19.airbnb.repository; + +import com.team19.airbnb.domain.main.NearDestination; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.List; + +@Repository +public class NearDestinationDAO { + + private final JdbcTemplate jdbcTemplate; + + public NearDestinationDAO(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public List findAll() { + String selectAll = "SELECT `id`, `destination`, `time_distance`, `image` FROM `near_destination`"; + return jdbcTemplate.query(selectAll, nearDestinationRowMapper()); + } + + private RowMapper nearDestinationRowMapper() { + return (rs, rowNum) -> { + return NearDestination.create(rs.getLong("id"), + rs.getString("destination"), + rs.getObject("time_distance", LocalTime.class), + rs.getString("image")); + }; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/repository/RoomDAO.java b/be/airbnb/src/main/java/com/team19/airbnb/repository/RoomDAO.java new file mode 100644 index 000000000..51f3d87d6 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/repository/RoomDAO.java @@ -0,0 +1,106 @@ +package com.team19.airbnb.repository; + +import com.team19.airbnb.domain.room.*; +import com.team19.airbnb.dto.SearchRequestDTO; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.util.*; + +@Repository +public class RoomDAO { + + private final JdbcTemplate jdbcTemplate; + private final ImageDAO imageDao; + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + public RoomDAO(JdbcTemplate jdbcTemplate, ImageDAO imageDao, DataSource dataSource) { + this.jdbcTemplate = jdbcTemplate; + this.imageDao = imageDao; + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + } + + public Optional findById(Long id) { + String selectById = "SELECT `id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity` FROM `room` WHERE `id` = ?"; + List result = jdbcTemplate.query(selectById, roomRowMapper(), id); + return result.stream().findAny(); + } + + public List findPriceByAddress(Double latitude, Double longitude) { + String sql = "SELECT `price_per_day`, (6371*acos(cos(radians(?))*cos(radians(latitude))*cos(radians(longitude) -radians(?))+sin(radians(?))*sin(radians(latitude)))) AS `distance` FROM `room` HAVING `distance` <= 0.5 ORDER BY `distance`"; + return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Room.class), latitude, longitude, latitude); + } + + public List findRoomsByCondition(SearchRequestDTO searchRequestDTO) { + String query = makeSqlSentence(searchRequestDTO); + SqlParameterSource namedParameter = setNamedParametersBySearchRequestDTO(searchRequestDTO); + return namedParameterJdbcTemplate.query(query, namedParameter, roomRowMapper()); + } + + private SqlParameterSource setNamedParametersBySearchRequestDTO(SearchRequestDTO searchRequestDTO) { + return new MapSqlParameterSource() + .addValue("minPrice", searchRequestDTO.getMinPrice()) + .addValue("maxPrice", searchRequestDTO.getMaxPrice()) + .addValue("guest", searchRequestDTO.getGuest()) + .addValue("checkIn", searchRequestDTO.getCheckIn()) + .addValue("checkOut", searchRequestDTO.getCheckOut()) + .addValue("latitude", searchRequestDTO.getCoordinate()[0]) + .addValue("longitude", searchRequestDTO.getCoordinate()[1]); + } + + private String makeSqlSentence(SearchRequestDTO searchRequestDTO) { + String sql = "SELECT *, (6371*acos(cos(radians(:latitude))*cos(radians(latitude))*cos(radians(longitude) -radians(:longitude))+sin(radians(:latitude))*sin(radians(latitude)))) AS distance FROM room WHERE 1=1 "; + if(searchRequestDTO.getMaxPrice() != null) { + sql += "AND price_per_day <= :maxPrice "; + } + if(searchRequestDTO.getMinPrice() != null) { + sql += "AND price_per_day >= :minPrice "; + } + if(searchRequestDTO.getGuest() != 0) { + sql += "AND capacity >= :guest "; + } + + if (searchRequestDTO.getCheckIn() != null || searchRequestDTO.getCheckOut() != null) { + sql += "AND id NOT IN ( SELECT room FROM booking WHERE 1=0 "; + if (searchRequestDTO.getCheckIn() != null) { + sql += "OR (check_in <= :checkIn AND check_out > :checkIn) "; + } + + if (searchRequestDTO.getCheckOut() != null) { + sql += "OR (check_in < :checkOut AND check_out >= :checkOut) "; + } + + if (searchRequestDTO.getCheckIn() != null && searchRequestDTO.getCheckOut() != null) { + sql += "OR (:checkIn <= check_in AND check_in < :checkOut) "; + } + + sql += ") "; + } + sql += "HAVING distance <= 0.5 ORDER BY distance"; + return sql; + } + + private RowMapper roomRowMapper() { + return (rs, rowNum) -> { + List images = imageDao.findAllByRoom(rs.getLong("id")); + return Room.create(rs.getLong("id"), + rs.getString("name"), + images, + Review.create(rs.getDouble("grade"), rs.getInt("reviewer")), + Location.create(rs.getString("address"), rs.getDouble("latitude"), rs.getDouble("longitude")), + RoomType.valueOf(rs.getString("room_type")), + RoomsAndBeds.create(rs.getInt("bed"), rs.getInt("bed_room"), rs.getInt("bath_room")), + rs.getString("description"), + Host.create(rs.getString("host_name"), rs.getString("host_image")), + rs.getObject("price_per_day", BigDecimal.class), + rs.getInt("capacity")); + }; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/repository/UserDAO.java b/be/airbnb/src/main/java/com/team19/airbnb/repository/UserDAO.java new file mode 100644 index 000000000..559e9c90a --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/repository/UserDAO.java @@ -0,0 +1,45 @@ +package com.team19.airbnb.repository; + +import com.team19.airbnb.domain.User; +import com.team19.airbnb.domain.Wishlist; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; + +import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; + +import java.util.List; +import java.util.Optional; + +@Repository +public class UserDAO { + + private final JdbcTemplate jdbcTemplate; + private final WishlistDAO wishlistDAO; + + public UserDAO(DataSource dataSource, WishlistDAO wishListDAO) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.wishlistDAO = wishListDAO; + } + + public Optional findById(Long id) { + String selectById = "SELECT `id`, `github` FROM `user` WHERE `id` = ?"; + List result = jdbcTemplate.query(selectById, userRowMapper(), id); + return result.stream().findAny(); + } + + private RowMapper userRowMapper() { + return (rs, rowNum) -> { + List wishlists = wishlistDAO.findAllByUser(rs.getLong("id")); + User user = User.create(rs.getLong("id"), + rs.getString("github"), + wishlists); + return user; + }; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/repository/WishlistDAO.java b/be/airbnb/src/main/java/com/team19/airbnb/repository/WishlistDAO.java new file mode 100644 index 000000000..186c3c4f3 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/repository/WishlistDAO.java @@ -0,0 +1,52 @@ +package com.team19.airbnb.repository; + +import com.team19.airbnb.domain.User; +import com.team19.airbnb.domain.Wishlist; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.util.List; +import java.util.Optional; + +@Repository +public class WishlistDAO { + + private final JdbcTemplate jdbcTemplate; + + public WishlistDAO(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public Optional findById(Long id) { + String selectById = "SELECT `id`, `room` FROM `wishlist` WHERE `id` = ?"; + List result = jdbcTemplate.query(selectById, wishlistRowMapper(), id); + return result.stream().findAny(); + } + + public List findAllByUser(Long user) { + String selectByUser = "SELECT `id`, `room` FROM `wishlist` WHERE `user` = ?"; + return jdbcTemplate.query(selectByUser, wishlistRowMapper(), user); + } + + public void updateWishlist(User user, Wishlist wishlist) { + String query = "insert into wishlist (user, user_key, room) values(?,?,?)"; + jdbcTemplate.update(query, user.getId(), user.getWishlists().size() - 1, wishlist.getRoom()); + } + + public void removeWishlist(User user, Wishlist wishlist) { + String query = "delete from wishlist where user = ? and room = ?"; + jdbcTemplate.update(query, user.getId(), wishlist.getRoom()); + } + + private RowMapper wishlistRowMapper() { + return (rs, rowNum) -> { + return Wishlist.create(rs.getLong("id"), + rs.getLong("room")); + }; + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/service/BookingService.java b/be/airbnb/src/main/java/com/team19/airbnb/service/BookingService.java new file mode 100644 index 000000000..5f292fe30 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/service/BookingService.java @@ -0,0 +1,64 @@ +package com.team19.airbnb.service; + +import com.team19.airbnb.domain.Booking.Booking; +import com.team19.airbnb.domain.User; +import com.team19.airbnb.domain.room.Room; +import com.team19.airbnb.dto.BookingRequestDTO; +import com.team19.airbnb.dto.BookingResponseDTO; +import com.team19.airbnb.exception.notauthorized.NotAuthorizedException; +import com.team19.airbnb.exception.notfound.BookingNotFoundException; +import com.team19.airbnb.repository.BookingDAO; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class BookingService { + + private final BookingDAO bookingDAO; + private final UserService userService; + private final RoomService roomService; + + public BookingService(BookingDAO bookingDAO, + UserService userService, + RoomService roomService) { + this.bookingDAO = bookingDAO; + this.userService = userService; + this.roomService = roomService; + } + + public BookingResponseDTO showBooking(Long userId, Long bookingId) { + User user = userService.findUserById(userId); + Booking booking = bookingDAO.findById(bookingId).orElseThrow(BookingNotFoundException::new); + return toResponseDTO(booking); + } + + public List showBookings(Long userId) { + User user = userService.findUserById(userId); + return bookingDAO.findAllByUser(userId).stream() + .map(this::toResponseDTO) + .collect(Collectors.toList()); + } + + public void book(BookingRequestDTO bookingRequestDTO, Long userId) { + User user = userService.findUserById(userId); + Booking booking = bookingRequestDTO.toEntity(); + booking.setUser(userId); + bookingDAO.save(booking); + } + + public void cancelBooking(Long bookingId, Long userId) { + User user = userService.findUserById(userId); + Booking booking = bookingDAO.findById(bookingId).orElseThrow(BookingNotFoundException::new); + if(!booking.isUser(userId)) { + throw new NotAuthorizedException("해당 예약을 삭제할 수 있는 권한이 없습니다"); + } + bookingDAO.delete(bookingId); + } + + private BookingResponseDTO toResponseDTO(Booking booking) { + Room room = roomService.findRoomById(booking.getRoom()); + return BookingResponseDTO.create(booking, room); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/service/MainService.java b/be/airbnb/src/main/java/com/team19/airbnb/service/MainService.java new file mode 100644 index 000000000..fa47d9fd1 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/service/MainService.java @@ -0,0 +1,22 @@ +package com.team19.airbnb.service; + +import com.team19.airbnb.dto.MainResponseDTO; +import com.team19.airbnb.repository.HeroBannerDAO; +import com.team19.airbnb.repository.NearDestinationDAO; +import org.springframework.stereotype.Service; + +@Service +public class MainService { + + private final HeroBannerDAO heroBannerDAO; + private final NearDestinationDAO nearDestinationDAO; + + public MainService(HeroBannerDAO heroBannerDAO, NearDestinationDAO nearDestinationDAO) { + this.heroBannerDAO = heroBannerDAO; + this.nearDestinationDAO = nearDestinationDAO; + } + + public MainResponseDTO main() { + return MainResponseDTO.create(heroBannerDAO.findAll(), nearDestinationDAO.findAll()); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/service/RoomService.java b/be/airbnb/src/main/java/com/team19/airbnb/service/RoomService.java new file mode 100644 index 000000000..f0474c8dc --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/service/RoomService.java @@ -0,0 +1,68 @@ +package com.team19.airbnb.service; + +import com.team19.airbnb.domain.Booking.Booking; +import com.team19.airbnb.domain.Booking.Price; +import com.team19.airbnb.domain.room.Room; +import com.team19.airbnb.dto.RoomDetailResponseDTO; +import com.team19.airbnb.dto.RoomPriceRequestDTO; +import com.team19.airbnb.dto.RoomPriceResponseDTO; +import com.team19.airbnb.dto.SearchRequestDTO; +import com.team19.airbnb.exception.notfound.ConditionNotFoundException; +import com.team19.airbnb.exception.notfound.NotFoundException; +import com.team19.airbnb.exception.notfound.RoomNotFoundException; +import com.team19.airbnb.exception.notfound.UserNotFoundException; +import com.team19.airbnb.repository.RoomDAO; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class RoomService { + + private final RoomDAO roomDAO; + + public RoomService(RoomDAO roomDAO) { + this.roomDAO = roomDAO; + } + + public RoomDetailResponseDTO showRoom(Long id) { + return new RoomDetailResponseDTO + .Builder(roomDAO.findById(id).orElseThrow(RoomNotFoundException::new)) + .build(); + } + + public RoomPriceResponseDTO showEstimate(RoomPriceRequestDTO roomPriceRequestDTO, Long roomId) { + Room room = roomDAO.findById(roomId).orElseThrow(RoomNotFoundException::new); + Booking booking = roomPriceRequestDTO.toEntity(roomId); + Price build = new Price.Builder(booking.countDays(), room.getPricePerDay()).build(); + return RoomPriceResponseDTO.create(new Price.Builder(booking.countDays(), room.getPricePerDay()).build()); + } + + public List searchPriceRange(Double latitude, Double longitude) { + return roomDAO.findPriceByAddress(latitude, longitude).stream() + .map(room -> room.getPricePerDay()) + .collect(Collectors.toList()); + } + + public List searchRoomsByCondition(SearchRequestDTO searchRequestDTO) { + if(searchRequestDTO.getCheckIn() == null && searchRequestDTO.getCheckOut() == null && searchRequestDTO.getCoordinate() == null + && searchRequestDTO.getGuest() == null && searchRequestDTO.getMinPrice() == null && searchRequestDTO.getMaxPrice() == null) { + throw new ConditionNotFoundException(); + } + if(searchRequestDTO.getCheckIn() != null && searchRequestDTO.getCheckOut() != null) { + Booking booking = searchRequestDTO.toBooking(); + return roomDAO.findRoomsByCondition(searchRequestDTO).stream() + .map((room) -> new RoomDetailResponseDTO.Builder(room).totalPrice(booking.calculateTotalPrice(room.getPricePerDay())).build()) + .collect(Collectors.toList()); + } + return roomDAO.findRoomsByCondition(searchRequestDTO).stream() + .map((room) -> new RoomDetailResponseDTO.Builder(room).build()) + .collect(Collectors.toList()); + } + + public Room findRoomById(Long id) { + return roomDAO.findById(id).orElseThrow(UserNotFoundException::new); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/service/UserService.java b/be/airbnb/src/main/java/com/team19/airbnb/service/UserService.java new file mode 100644 index 000000000..c3b7dc3f9 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/service/UserService.java @@ -0,0 +1,37 @@ +package com.team19.airbnb.service; + +import com.team19.airbnb.domain.User; +import com.team19.airbnb.domain.Wishlist; +import com.team19.airbnb.dto.RoomDetailResponseDTO; +import com.team19.airbnb.exception.notfound.RoomNotFoundException; +import com.team19.airbnb.exception.notfound.UserNotFoundException; +import com.team19.airbnb.repository.RoomDAO; +import com.team19.airbnb.repository.UserDAO; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class UserService { + + private final UserDAO userDAO; + private final RoomService roomService; + + public UserService(UserDAO userDAO, RoomService roomService) { + this.userDAO = userDAO; + this.roomService = roomService; + } + + public User findUserById(Long id) { + return userDAO.findById(id).orElseThrow(UserNotFoundException::new); + } + + public List showWishLists(Long userId) { + List wishlists = userDAO.findById(userId).orElseThrow(UserNotFoundException::new).getWishlists(); + return wishlists.stream().map(Wishlist::getRoom) + .map(roomId -> roomService.findRoomById(roomId)) + .map( room -> new RoomDetailResponseDTO.Builder(room).build()) + .collect(Collectors.toList()); + } +} diff --git a/be/airbnb/src/main/java/com/team19/airbnb/service/WishlistService.java b/be/airbnb/src/main/java/com/team19/airbnb/service/WishlistService.java new file mode 100644 index 000000000..1c41aa622 --- /dev/null +++ b/be/airbnb/src/main/java/com/team19/airbnb/service/WishlistService.java @@ -0,0 +1,33 @@ +package com.team19.airbnb.service; + +import com.team19.airbnb.domain.User; +import com.team19.airbnb.domain.Wishlist; +import com.team19.airbnb.repository.WishlistDAO; +import org.springframework.stereotype.Service; + +@Service +public class WishlistService { + + private final UserService userService; + private final WishlistDAO wishlistDAO; + + public WishlistService(UserService userService, WishlistDAO wishlistDAO) { + this.userService = userService; + this.wishlistDAO = wishlistDAO; + } + + public void addWishList(Long roomId, Long userId) { + User user = userService.findUserById(userId); + Wishlist wishlist = Wishlist.create(roomId); + user.addWishlist(wishlist); + wishlistDAO.updateWishlist(user, wishlist); + } + + public void deleteWishlist(Long roomId, Long userId) { + User user = userService.findUserById(userId); + Wishlist wishlist = Wishlist.create(roomId); + user.removeWishlist(wishlist); + wishlistDAO.removeWishlist(user, wishlist); + + } +} diff --git a/be/airbnb/src/main/resources/application.properties b/be/airbnb/src/main/resources/application.properties new file mode 100644 index 000000000..e0aa3ed8d --- /dev/null +++ b/be/airbnb/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://localhost:3306/airbnb?autoReconnection=true +spring.datasource.username=scott +spring.datasource.password=tiger +spring.datasource.initialization-mode=always +logging.level.sql=debug diff --git a/be/airbnb/src/main/resources/data.sql b/be/airbnb/src/main/resources/data.sql new file mode 100644 index 000000000..33421636e --- /dev/null +++ b/be/airbnb/src/main/resources/data.sql @@ -0,0 +1,213 @@ +INSERT INTO user(`id`, `github`) VALUES(1, 'tree'); +INSERT INTO user(`id`, `github`) VALUES(2, 'BONG-F'); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (1, 'the-k seoul', 4.5, 100, '서울특별시 서초구 양재2동 바우뫼로12길 70', 37.4661237, 127.0304784, 'ENTIRE_PLACE', 1, 1, 1, '양재역에 위치한 더케이서울입니다.', 'the-k', 'https://lh3.googleusercontent.com/p/AF1QipPFnRnv-rbPGS06Gyi4PQOm6be8vKawm7O4Oqzy=w296-h202-n-k-rw-no-v1', 60000, 10); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/c6d2dc5b-91f8-4070-adbd-e252759c24a7.jpg?im_w=1200', 1); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/b5b4f7ee-d104-4729-b9b9-64192dae4227.jpg?im_w=1200', 1); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/c9e17964-093b-47f4-b93e-c796e7359b39.jpg?im_w=720', 1); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (2, 'codesquad', 4.9, 13, '서울특별시 강남구 역삼동 836-24', 37.4908252, 127.0312283, 'ENTIRE_PLACE', 1, 2, 2, '코드스쿼드입니다.', 'HONUX', 'https://ca.slack-edge.com/T74H5245A-U74KKLB0D-4f2767985e3d-512', 60000, 5); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipNxntYBPh5s0xjPzvjnlhi4730KlGBiH4z7B0M2=w408-h306-k-no', 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipObkWYQyr6rOwJ1V6k9duVHA-gIEUQcJ4FPFFa7=w203-h135-k-no', 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipNfSllpnpl1R3zWI4lQsaqlDLrSaEOo3zjkHQKv=s718-k-no', 2); + +INSERT INTO `room`(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (3, 'YeoksamElementarySchool', 3.6, 12, '서울특별시 강남구 역삼1동 강남대로66길 21', 37.4927053, 127.0305617, 'HOTEL_ROOM', 10, 10, 10, '역삼초입니다.', 'YEON', 'https://ca.slack-edge.com/T74H5245A-U01J5LYPUKT-4f8bc7881fba-512', 100000, 100); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipO-75G4s9xmUVRUmoAgPTeUdrlcbxyV8gXqvmth=s670-k-no', 3); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipMS3vA2PMHOwVwKM2tOlvmmFwiF_7NsbgA-wvEE=w203-h270-k-no', 3); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipNyOrnxkCr3MrmxP-AUkUmpJ7cT7AN-MtljdbBG=w203-h270-k-no', 3); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (4, 'Dogok-APT', 4.7, 38, '서울특별시 강남구 도곡2동 선릉로 221', 37.4935719, 127.048583, 'SHARED_ROOM', 6, 7, 2, '도곡아파트입니다. 방이 넓어요', 'Dong', 'https://ca.slack-edge.com/T74H5245A-U01J1D774UC-4cb9989e1d29-512', 70000, 6); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipNtsg3PfMje-yGa6BC_2vRPZC7G4bnMx8cNk7vQ=w203-h152-k-no', 4); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipNtsg3PfMje-yGa6BC_2vRPZC7G4bnMx8cNk7vQ=s744-k-no', 4); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipOVj8iEgeUa0a1boqAoaUmukiO9Po8saf6d-KMQ=s1117-k-no', 4); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (5, 'DAMIAN-HOTEL', 3.8, 82, '서울특별시 강남구 도곡1동 도곡로 220', 37.4926686, 127.0255512, 'HOTEL_ROOM', 1, 1, 1, '호텔입니다. 방이 넓어요', 'Dumba', 'https://ca.slack-edge.com/T74H5245A-U01HBG75AG7-fedf3b75b5d4-512', 30000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/b1871fa0-7a16-45dd-ad6f-7c1a62af9888.jpg?im_w=1200', 5); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/58e79bf0-76d8-4455-8342-d79ff04bfa9c.jpg?im_w=1200', 5); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/962e576f-6178-4ace-98f2-1aee1bac5846.jpg?im_w=720', 5); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (6, 'ibis Styles Ambassador Seoul Gangnam', 4.0, 1664, '서울특별시 강남구 대치4동 삼성로 431', 37.4996378, 127.0379374, 'HOTEL_ROOM', 3, 3, 2, '호텔입니다. 방이 넓어요', 'NAS', 'https://ca.slack-edge.com/T74H5245A-U01HD2AF9B9-9f9b4014d997-512', 270000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh5.googleusercontent.com/p/AF1QipOEQs8J3Yiwq6WT3tb5fOcdHiJ9W0UKigOVkWQn=s836-k-no', 6); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://lh6.googleusercontent.com/proxy/KprAz3tvr7tFsxeirVXSLp5OrCmzcZZuX61Ej4dVr42I7k4Gqu7_W5tPAKzVEqwOoFwQqA7e2h6B9dAh9zn7OAlIDaWoJ1XhCQXn_LNEshiPoAvr2ReKrJ4kdQE7UXmsnbTO6ru7oHAVUERu-bfnxQ7yIh3hTCQ=w203-h135-k-no', 6); +INSERT INTO `image`(`url`, `room`) +VALUES ('https:////lh4.googleusercontent.com/proxy/cAvwgOJqSykJjiBpjEz6QLVrQuIBihUUziIcXDqIT_A3Soit5-oH1NrNbAfnxOJVKfM6gc1eWxdqjyyoDp0SSMx6YLGHXUJFtxrHbhF66sy_7zPG0K_m9nI26_hyc7VOCp5j1t6OuFZtgwBVJ2fFE6rjqblDFw=w203-h152-k-no', 5); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (7, '성산카리스다올림', 4.91, 11, '서울 마포구 성산동 591-6', 37.5652326, 126.9006676, 'PRIVATE_ROOM', 1, 1, 1, '방입니다. 방이 넓어요', 'marco', 'https://ca.slack-edge.com/T74H5245A-U01J4TYE589-ga928c512f7c-512', 85000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/26cff20a-c966-4621-a56f-d6b4530ec191.jpg?im_w=960', 7); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/00ced434-add9-44ce-81e1-a4738304cafd.jpg?im_w=1200', 7); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/0a1881d2-61f1-436f-be3e-60789e2ae44f.jpg?im_w=720', 7); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (8, 'Micasa@Seoul: Just opened for you~', 4.0, 1, '서울 마포구 성산동 591-6', 37.5506404, 126.9136096, 'PRIVATE_ROOM', 1, 1, 1, '방입니다. 방이 넓어요', 'noel', 'https://ca.slack-edge.com/T74H5245A-U01HM6VJMQW-1d088720709b-512', 65000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/595815bd-9083-4d3b-a78f-d42356080415.jpg?im_w=1200', 8); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/f9fb1d13-5ce1-4c7c-bc60-29964dd0c06c.jpg?im_w=720', 8); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/21bdb540-0256-4040-b71d-fd839075c64c.jpg?im_w=720', 8); + + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (9, '위크앤드 [ Week;and ] 감성충전! 디자이너집 살아보기', 4.88, 428, '서울특별시 용산구 이태원1동 이태원로23길 21', 37.5353311, 126.9918668, 'ENTIRE_PLACE', 1, 1, 1, '방입니다. 방이 넓어요', 'sally', 'https://ca.slack-edge.com/T74H5245A-U01HF8HEXRV-6cb18d7abf63-512', 130000, 5); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/3b72f326-5c82-44a5-9299-f3e1d0a547fe.jpg?im_w=1200', 9); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/91f5e64b-d0c7-4bf6-aae0-1c169bd24d77.jpg?im_w=1200', 9); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/miso/Hosting-18674278/original/e4a6c067-76b3-463e-9e29-46de29a39d62.jpeg?im_w=720', 9); + + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (10, '고즈넉한 한옥스테이 희담재', 4.96, 53, '서울특별시 한남동 소월로 322', 37.5393549, 126.9966033, 'ENTIRE_PLACE', 3, 2, 3, '돌담과 가림벽으로 주변 시선에 노출되지 않고 프라이빗하게 숙소에서 즐길 수 있습니다. 숙소와 카페를 동시 운영하고 있어 음료/커피/브런치 등 다양하게 이용하실 수 있는 장점이 있습니다. 3년동안 오프라인만 운영하였습니다. 운영 과정을 통해 정말 좋은 분들과의 만남도 가지고 아끼지 않는 칭찬도 많이 받았었지만 그 속에서도 부족한 부분을 점검하고 보완하여 이제는 더 많은 분들께 저희 희담재를 소개 시켜 드리고 싶은 주인장 마음에 이렇게 에어비앤비에 등록을 하게 되었습니다.', 'rano', 'https://ca.slack-edge.com/T74H5245A-U01JK703LC8-46a9f3da2ad1-512', 160000, 8); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/4faf53de-3b74-443c-8f50-30da1b4cc8ba.jpg?im_w=1200', 10); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/14fdc8f1-ad90-4faa-b714-e6e1ea664381.jpg?im_w=1200', 10); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/7c53dfd7-2825-4976-9e81-ef850913fa77.jpg?im_w=1200', 10); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (11, '유유자적 삼동', 4.94, 16, '서울특별시 용산구 한남동 621-1 2층', 37.5335673, 126.9990757, 'PRIVATE_ROOM', 1, 1, 1, '적정한 온도의 미온수에서 수영을 즐겨요 북한강이 보이는 욕조에 몸을 담가 그동안 쌓였던 피로를 풀어보세요 폭신한 침대에 누워 사각거리는 이불을 덮고 그동안 바빠서 놓쳤던 영화도 보고 그러다 어느새 단잠에 빠질 거예요 아침엔 나란히 앉아 강물을 바라보며 준비된 가벼운 식사로 하루를 시작해요 그렇게 유유자적 하루를 지내보면 지쳤던 몸과 마음에 위로가 될 거예요 이곳에서 쉬어가는 동안 여유롭고 편안하시길 바라는 마음으로 정성을 다해 준비하였습니다 기본인원 2명 최대인원 2인이며, 예약 시 인원수에 맞게 침구와 어메니티 그리고 조식을 준비해 드립니다. 침구와 가운 은 항상 깨끗하게 유지하며, 사계절 온수 수영장은 매일 순환식으로 수질관리하고 있습니다. 깨끗한 청소와 피톤치드 연무 소독으로 청결한 숙소를 유지하고 있습니다. 다만 자연과 가까운 곳이어서 곤충들이 놀러 올 수 있습니다. 충에 예민 하신 분은 예약에 신중해 주세요', 'robin', 'https://ca.slack-edge.com/T74H5245A-U01HP9PKWUD-410ede43863b-512', 255000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/fbbab78f-d066-4f3e-bf74-3763ca09ba13.jpg?im_w=1200', 11); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/miso/Hosting-49336798/original/86bb9561-752a-456b-9c24-05462092f640.jpeg?im_w=1200', 11); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/9fdddcc3-acc4-445b-b736-6c003ce3623f.jpg?im_w=720', 11); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (12, 'yuyujajeok, 편히쉬어가는곳', 5.0, 12, '서울특별시 영등포구 여의도동 의사당대로 82', 37.5226344, 126.9213062, 'HOTEL_ROOM', 1, 1, 1, '계절마다 반짝이는 북한강을 바라보며 적정한 온도의 미온수에서 수영을 즐겨요 탁 트인 하늘을 보며 따끈한 노천탕에 몸을 담가 쌓였던 피로를 풀어보세요 폭신한 침대에 누워 사각거리는 이불을 덮고 그동안 바빠서 놓쳤던 영화도 보세요 그러다 어느새 단잠에 빠질 거예요 아침엔 강물 위를 노니는 귀여운 새들을 보며 준비된 가벼운 식사로 하루를 시작해요 그렇게 유유자적 하루를 지내보면 지쳤던 몸과 마음에 위로가 될 거예요', 'downy', 'https://ca.slack-edge.com/T74H5245A-U01HSCSFSSW-d04ad5c21501-512', 185000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/2840943e-c8bd-4a56-ab32-05ffd425fa6d.jpg?im_w=1200', 12); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/7ccc3ecc-4884-4911-8bf8-9193c403ee7f.jpg?im_w=720', 12); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/79ad82bf-e7d4-43e2-acbd-dfeccfca907e.jpg?im_w=720', 12); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (13, '구례옥잠 (GuryeOkjam)', 4.89, 55, '서울특별시 동작구 노량진동 294-456', 37.5007495, 126.9600952, 'HOTEL_ROOM', 2, 2, 3, '구례옥잠은 옛날 집을 개조한 작은 게스트하우스입니다. 오래된 건물이라 천장이 낮고 방음이 취약해 조금 불편할 수 있지만 옛날집의 아늑함을 느낄 수 있는 장점도 있답니다.', 'bmo', 'https://ca.slack-edge.com/T74H5245A-U01JG8T9KEC-0ef89874444c-512', 65000, 10); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/42c5d1a1-fce7-4b85-928c-80b151bb5446.jpg?im_w=1200', 13); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/11c5c65d-682e-4562-b200-72a5c32d7592.jpg?im_w=1200', 13); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/4a967e77-9bd7-4c9f-a929-5ced045223b2.jpg?im_w=720', 13); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (14, '고전적인 한옥의 감성과 현대적인 편리함을 공유', 4.99, 74, '서울특별시 관악구 남현동 1082-37', 37.4742981, 126.9749058, 'PRIVATE_ROOM', 1, 1, 1, '여유로운 라이프 스타일을 지향하는 곳입니다. 77년에 지어진 한옥을 현대식으로 리모델링하여 고전적인 한옥의 감성과 현대적인 편리함을 공유시킨 장소입니다. 황리단길의 메인도로에 위치해 있으며 인근 관광지 및 핫플레이스와 인접해 있어 도보로 여행이 가능합니다. 공용 다이닝 룸을 중심으로 3개의 방으로 나뉘어져 있습니다. 그 중 2번방은 2인을 위한 공간으로 게스트의 편안한 휴식을 위해 붙박이 침대, 붙박이 벤치, 개별 테라스로 이루어져 있으며 독립된 공간에서 아늑한 휴식을 취하실 수 있을 것입니다.', 'jenny', 'https://ca.slack-edge.com/T74H5245A-U01HU1MMT0A-e40ce30efd70-512', 65000, 20); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/d74b2be1-9218-4ec9-a5c9-2437203da6d4.jpg?im_w=720', 14); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/05193eb4-e410-4758-b7e6-a1cd6eea2208.jpg?im_w=720', 14); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/6e55a618-490e-48c1-adec-d7bcabea4bbf.jpg?im_w=1200', 14); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (15, '일영댁의 루프탑', 4.93, 68, '서울특별시 광진구 자양동 770-1', 37.5391522, 127.0806075, 'ENTIRE_PLACE', 1, 2, 1, '서울에서 가까운 공기좋고 조용한 작은마을안에 있는 루프탑을 즐겨보세요! 엘레베이터가 없는 4층의 옥상입니다. 조금은 힘들게 올라오셔야겠지만, 루프탑에 도착하시면 북한산 전망을 바라보시며 야외테라스에서 프라이빗한 시간을 만드실수 있는 장소이며, 테라스에서 야외 욕조도 이용하실 수 있습니다. (냉,온수)', 'jane', 'https://ca.slack-edge.com/T74H5245A-U01J52Z9HJM-bff56f282096-512', 233000, 6); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/a317fbfd-e121-4bcb-ac8b-f5720aaa016d.jpg?im_w=960', 15); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/f49f39cb-6316-46bb-a515-bee1d98117f0.jpg?im_w=720', 15); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/8c7bf879-7c10-4bae-8109-ff1a06b20e00.jpg?im_w=720', 15); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (16, '오션뷰 노천탕이 있는 프라이빗 렌트 하우스', 4.94, 121, '서울특별시 광진구 구의동 594-1', 37.5349632, 127.0908141, 'HOTEL_ROOM', 2, 2, 2, '여름,겨울에 대비하여 시스템에어컨과 내외 단열재 사용으로 사계절 내내 최상의 환경을 제공합니다. 또한 여러 사용자를 대비하여 두개 세면대를 설치하였고 화장실과 샤워실을 분리 하여 더욱 쾌적한 환경을 만들었습니다.', 'lin', 'https://ca.slack-edge.com/T74H5245A-URXB5F5E1-f16d2186493d-512', 135000, 6); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/b1005ef2-7df2-4f92-9516-f865005990d9.jpg?im_w=1200', 16); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/2efece2a-36c1-486b-b7b8-0fb10019be6b.jpg?im_w=720', 16); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/8bc0dfba-3d7e-49db-b78e-b6e1da8e27b8.jpg?im_w=1200', 16); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (17, '몽상가의 시골집', 4.76, 373, '서울특별시 강남구 삼성1동 봉은사로 524 코엑스 1층 인터컨티넨탈', 37.4966206, 127.0496687, 'HOTEL_ROOM', 2, 2, 1, '강원도 평창, 700미터 고도 위 쉼여행 최적지. 산과 구름, 몇 채의 민가와 고랭지 채소밭 말고는 아무것도 없는 진짜 시골 여행! 그러나 누군가에는 너무도 많은 것이 있는 곳!! 그림과 아날로그르 음악, 그리고 책이 있는 퀸사이즈룸 2개에 넓은 거실, 자연을 향해 열려 있는 넓은 테라스. 맑은 물과 공기, 밤하늘의 별과 고요가 있는 전원주택 독채! 동서울터미널에서 운교행 버스 타면 한시간반만에 도착! *WELLI HILLI SKI Resort is a 20 minute drive. *토요일과 공휴일, 휴가철 4인이상 우선예약! *기본 셀프 입실.', 'freddy', 'https://ca.slack-edge.com/T74H5245A-U01HBNWQVCP-35001a089583-512', 55000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/eb8028f9-0ddd-49f0-95a9-daad056c92b1.jpg?im_w=1200', 17); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/a9d4d521-39df-47dc-a54a-9650c45a5f7a.jpg?im_w=1200', 17); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/0779ad72-5967-4b63-84cf-3aeabe3b0575.jpg?im_w=720',17); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (18, ' 풀잎애', 4.87, 55, '서울특별시 동대문구 이문동 이문로 174-1', 37.6032226, 127.0614934, 'ENTIRE_PLACE', 1, 2, 1, '- 산 속에 위치하고 있어 추울 수 있으니 따뜻한 옷을 가져오시길 바랍니다. 주변에 편의점이나 마트가 없으니 오시기 전에 장을 봐오시길 추천드려요. 겨울철 산길을 올라오시는 길이 미끄럽습니다. 스노우타이어가 장착된 4륜구동차량이 아닌 경우 스노우체인(단순 부착X)이 꼭 필요합니다.혹 그게 어려우신 경우 콜밴 이용 추천드립니다. 날씨가 따뜻해지면서 곤충들의 출현이 있을 수 있습니다. 산에 둘러쌓인 자연공간인 만큼 당연한 부분이니 널리 양해와 이해부탁드립니다.', 'seong', 'https://ca.slack-edge.com/T74H5245A-U01HP9EUWUD-7eba0ed5db6a-512', 35000, 4); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/8f57cd58-a9ac-4933-a405-add11a93d4e2.jpg?im_w=960', 18); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/de170ec6-eddd-4060-b015-80effa5ffd40.jpg?im_w=1200', 18); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/0db96064-69a6-48c7-b156-4b04c7077763.jpg?im_w=720', 18); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (19, '청수리 오즈네 164', 4.98, 123, '서울특별시 중랑구 상봉동 128-40번지', 37.5942015, 127.0609456, 'HOTEL_ROOM', 1, 1, 1, '청수리 오즈네는 제주 서쪽 감귤 과수원과 반딧불이로 유명한 청수리에 위치한 조용한 시골 주택입니다. 19년 1월을 시작으로 2년이 흘렀고 많은 관심을 가져주신 덕분에 숙소 안팎으로 재정비하는 시간을 가질 수 있었습니다. 남편이 만든 가구로 객실을 채우고, 아내인 저는 패브릭으로 온기를 전할 수 있는 것들을 만들어 준비했습니다. 새로워진 모습으로 21년 3월, 다시 시작합니다.', 'issac', 'https://ca.slack-edge.com/T74H5245A-U01HKR2C1B8-6f9beb6aeed5-512', 155000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/miso/Hosting-30629416/original/ebba04af-3de6-41e0-a44a-638f436fff01.jpeg?im_w=1200', 19); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/miso/Hosting-30629416/original/13415180-25a0-4c90-bebf-257aeafbbf6e.jpeg?im_w=1200', 19); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/73d4b623-0630-46d7-bf08-95aaac0a4edf.jpg?im_w=1200', 19); + +INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +VALUES (20, '돌집스테이', 4.97, 73, '서울특별시 구로구 구로동 디지털로 300', 37.4695193,126.9027923, 'PRIVATE_ROOM', 1, 1, 1, '평대바다 바로 앞에 있는 모던한 스타일의 제주 돌집입니다. 방 하나에 퀸메트리스 2개가 놓여 있고 방문을 열면 탁트인 스튜디오 형식으로 변합니다. 거실이나 데크, 잔디마당에서 바다 풍경을 즐길 수 있고 아침에는 아름다운 일출을 볼 수 있습니다. 창문으로 보이는 바다뷰는 진정한 쉼과 힐링을 제공합니다. 조용하고 여유로운 여행을 원하시는 분들께 적합한 숙소입니다.', 'coco', 'https://ca.slack-edge.com/T74H5245A-U01HSH6U0EN-e2addb0b3062-512', 270000, 2); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/110669257/ef543798_original.jpg?im_w=1200', 20); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/2774d63e-90c1-464c-a186-020c4f13b50a.jpg?im_w=720', 20); +INSERT INTO `image`(`url`, `room`) +VALUES ('https://a0.muscache.com/im/pictures/6e462fb3-eb4d-4351-a182-3a3c5905259f.jpg?im_w=720', 20); + +-- INSERT INTO room(`id`, `name`, `grade`, `reviewer`, `address`, `latitude`, `longitude`, `room_type`, `bed`, `bed_room`, `bath_room`, `description`, `host_name`, `host_image`, `price_per_day`, `capacity`) +-- VALUES (7, '성산카리스다올림', 4.91, 11, '서울 마포구 성산동 591-6', 37.5652326, 126.9006676,17, 'PRIVATE_ROOM', 1, 1, 1, '방입니다. 방이 넓어요', 'marco', '', 85000, 2); +-- INSERT INTO `image`(`url`, `room`) +-- VALUES ('', 7); +-- INSERT INTO `image`(`url`, `room`) +-- VALUES ('', 7); +-- INSERT INTO `image`(`url`, `room`) +-- VALUES ('', 7); + + + + + +INSERT INTO `booking`(`check_in`, `check_out`, `guest`, `total_price`, `user`, `room`) +VALUES ('2021-05-20', '2021-05-25', 1, 15000, 1, 1); +INSERT INTO `wishlist`(`id`, `user`, `user_key`, `room`) +VALUES (1, 1, 0, 1); +INSERT INTO `wishlist`(`id`, `user`, `user_key`, `room`) +VALUES (2, 1, 1, 2); +INSERT INTO `hero_banner`(`id`, `title`, `image`) +VALUES (1, 'title1', 'image1'); +INSERT INTO `hero_banner`(`id`, `title`, `image`) +VALUES (2, 'title2', 'image2'); +INSERT INTO `near_destination`(`id`, `destination`, `time_distance`, `image`) +VALUES (1, '광주', '00:25:00', 'image1'); +INSERT INTO `near_destination`(`id`, `destination`, `time_distance`, `image`) +VALUES (2, '대전', '01:25:00', 'image2'); + diff --git a/be/airbnb/src/main/resources/schema.sql b/be/airbnb/src/main/resources/schema.sql new file mode 100644 index 000000000..39dfd1de6 --- /dev/null +++ b/be/airbnb/src/main/resources/schema.sql @@ -0,0 +1,156 @@ +-- MySQL Workbench Forward Engineering + +SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; +SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; +SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; + +-- ----------------------------------------------------- +-- Schema airbnb +-- ----------------------------------------------------- + +-- ----------------------------------------------------- +-- Schema airbnb +-- ----------------------------------------------------- +CREATE SCHEMA IF NOT EXISTS `airbnb` DEFAULT CHARACTER SET utf8 ; +USE `airbnb` ; + +-- ----------------------------------------------------- +-- Table `airbnb`.`room` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `airbnb`.`room` ; + +CREATE TABLE IF NOT EXISTS `airbnb`.`room` ( + `id` INT NOT NULL, + `name` VARCHAR(45) NOT NULL, + `grade` DOUBLE NOT NULL, + `reviewer` INT NOT NULL, + `address` VARCHAR(45) NOT NULL, + `latitude` DOUBLE NOT NULL, + `longitude` DOUBLE NOT NULL, + `room_type` VARCHAR(45) NOT NULL, + `bed` INT NOT NULL, + `bed_room` INT NOT NULL, + `bath_room` INT NOT NULL, + `description` TEXT NOT NULL, + `host_name` VARCHAR(45) NOT NULL, + `host_image` VARCHAR(255) NOT NULL, + `price_per_day` DECIMAL NOT NULL, + `capacity` INT NOT NULL, + PRIMARY KEY (`id`)) +ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `airbnb`.`user` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `airbnb`.`user` ; + +CREATE TABLE IF NOT EXISTS `airbnb`.`user` ( + `id` INT AUTO_INCREMENT, + `github` VARCHAR(255) NOT NULL, + PRIMARY KEY (`id`)) +ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `airbnb`.`booking` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `airbnb`.`booking` ; + +CREATE TABLE IF NOT EXISTS `airbnb`.`booking` ( + `id` INT AUTO_INCREMENT, + `check_in` DATE NOT NULL, + `check_out` DATE NOT NULL, + `guest` INT NOT NULL, + `total_price` DECIMAL NOT NULL, + `user` INT NOT NULL, + `room` INT NOT NULL, + PRIMARY KEY (`id`), + INDEX `fk_booking_user1_idx` (`user` ASC) , + INDEX `fk_booking_room1_idx` (`room` ASC), + CONSTRAINT `fk_booking_user1` + FOREIGN KEY (`user`) + REFERENCES `airbnb`.`user` (`id`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_booking_room1` + FOREIGN KEY (`room`) + REFERENCES `airbnb`.`room` (`id`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `airbnb`.`wishlist` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `airbnb`.`wishlist` ; + +CREATE TABLE IF NOT EXISTS `airbnb`.`wishlist` ( + `id` INT AUTO_INCREMENT, + `user` INT NOT NULL, + `user_key` INT, + `room` INT NOT NULL, + PRIMARY KEY (`id`), + INDEX `fk_wishlist_user1_idx` (`user` ASC), + INDEX `fk_wishlist_room1_idx` (`room` ASC), + CONSTRAINT `fk_wishlist_user1` + FOREIGN KEY (`user`) + REFERENCES `airbnb`.`user` (`id`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_wishlist_room1` + FOREIGN KEY (`room`) + REFERENCES `airbnb`.`room` (`id`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `airbnb`.`hero_banner` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `airbnb`.`hero_banner` ; + +CREATE TABLE IF NOT EXISTS `airbnb`.`hero_banner` ( + `id` INT AUTO_INCREMENT, + `title` VARCHAR(45) NOT NULL, + `image` VARCHAR(255) NOT NULL, + PRIMARY KEY (`id`)) +ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `airbnb`.`near_destination` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `airbnb`.`near_destination` ; + +CREATE TABLE IF NOT EXISTS `airbnb`.`near_destination` ( + `id` INT AUTO_INCREMENT, + `destination` VARCHAR(45) NOT NULL, + `time_distance` TIME NOT NULL, + `image` VARCHAR(255) NOT NULL, + PRIMARY KEY (`id`)) +ENGINE = InnoDB; + + +-- ----------------------------------------------------- +-- Table `airbnb`.`image` +-- ----------------------------------------------------- +DROP TABLE IF EXISTS `airbnb`.`image` ; + +CREATE TABLE IF NOT EXISTS `airbnb`.`image` ( +`url` VARCHAR(255) NOT NULL, +`room` INT NOT NULL, +`room_key` INT, +PRIMARY KEY (`url`), +CONSTRAINT `fk_image_room` +FOREIGN KEY (`room`) + REFERENCES `airbnb`.`room` (`id`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB; + +SET SQL_MODE=@OLD_SQL_MODE; +SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; +SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; diff --git a/be/airbnb/src/test/java/com/team19/airbnb/AirbnbApplicationTests.java b/be/airbnb/src/test/java/com/team19/airbnb/AirbnbApplicationTests.java new file mode 100644 index 000000000..df9612e38 --- /dev/null +++ b/be/airbnb/src/test/java/com/team19/airbnb/AirbnbApplicationTests.java @@ -0,0 +1,13 @@ +package com.team19.airbnb; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AirbnbApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/etc/erd.mwb b/etc/erd.mwb new file mode 100644 index 000000000..d782005dc Binary files /dev/null and b/etc/erd.mwb differ