diff --git a/BE/.gitignore b/BE/.gitignore new file mode 100644 index 000000000..dfcf34da1 --- /dev/null +++ b/BE/.gitignore @@ -0,0 +1,184 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/windows,java,intellij,gradle +# Edit at https://www.toptal.com/developers/gitignore?templates=windows,java,intellij,gradle + +### 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 + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# 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* + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Gradle ### +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### Gradle Patch ### +**/build/ + +# End of https://www.toptal.com/developers/gitignore/api/windows,java,intellij,gradle +/.idea/modules/BE.iml +/.idea/.name +/.idea/compiler.xml +/.idea/jarRepositories.xml +/.idea/misc.xml +/.idea/vcs.xml diff --git a/BE/.idea/.gitignore b/BE/.idea/.gitignore new file mode 100644 index 000000000..f326f97d9 --- /dev/null +++ b/BE/.idea/.gitignore @@ -0,0 +1,8 @@ +# 디폴트 무시된 파일 +/shelf/ +/workspace.xml +# 데이터 소스의 로컬 스토리지가 파일을 무시했습니다 +/../../../../../../:\Users\rnala\sidedish\BE\.idea/dataSources/ +/dataSources.local.xml +# 에디터 기반 HTTP 클라이언트 요청 +/httpRequests/ diff --git a/BE/HELP.md b/BE/HELP.md new file mode 100644 index 000000000..ffaa610ea --- /dev/null +++ b/BE/HELP.md @@ -0,0 +1,25 @@ +# 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 Web](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#boot-features-developing-web-applications) +* [Spring Data JDBC](https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/) + +### Guides +The following guides illustrate how to use some features concretely: + +* [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/) +* [Using Spring Data JDBC](https://github.com/spring-projects/spring-data-examples/tree/master/jdbc/basics) + +### 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/build.gradle b/BE/build.gradle new file mode 100644 index 000000000..6e2fe07ac --- /dev/null +++ b/BE/build.gradle @@ -0,0 +1,24 @@ +plugins { + id 'org.springframework.boot' version '2.4.5' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'com.codesquad' +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' + runtimeOnly 'mysql:mysql-connector-java' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +test { + useJUnitPlatform() +} diff --git a/BE/gradle/wrapper/gradle-wrapper.jar b/BE/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e708b1c02 Binary files /dev/null and b/BE/gradle/wrapper/gradle-wrapper.jar differ diff --git a/BE/gradle/wrapper/gradle-wrapper.properties b/BE/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..442d9132e --- /dev/null +++ b/BE/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/gradlew b/BE/gradlew new file mode 100644 index 000000000..4f906e0c8 --- /dev/null +++ b/BE/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/gradlew.bat b/BE/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/BE/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/settings.gradle b/BE/settings.gradle new file mode 100644 index 000000000..faefa2281 --- /dev/null +++ b/BE/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'sidedish' diff --git a/BE/src/main/java/com/codesquad/sidedish/SidedishApplication.java b/BE/src/main/java/com/codesquad/sidedish/SidedishApplication.java new file mode 100644 index 000000000..a654380a9 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/SidedishApplication.java @@ -0,0 +1,12 @@ +package com.codesquad.sidedish; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SidedishApplication { + + public static void main(String[] args) { + SpringApplication.run(SidedishApplication.class, args); + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/controller/CategoryController.java b/BE/src/main/java/com/codesquad/sidedish/controller/CategoryController.java new file mode 100644 index 000000000..c3340d47e --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/controller/CategoryController.java @@ -0,0 +1,36 @@ +package com.codesquad.sidedish.controller; + +import com.codesquad.sidedish.domain.Category; +import com.codesquad.sidedish.domain.Dish; +import com.codesquad.sidedish.dto.CategoryResponseDto; +import com.codesquad.sidedish.dto.ResponseDto; +import com.codesquad.sidedish.service.CategoryService; +import com.codesquad.sidedish.util.Status; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +@RestController +@RequestMapping("/categories/{type}") +public class CategoryController { + + private CategoryService categoryService; + + public CategoryController(CategoryService categoryService) { + this.categoryService = categoryService; + } + + @PostMapping + public ResponseEntity addDish(@PathVariable String type, @RequestBody Dish dish) { + categoryService.addDishToCategory(type, dish); + return ResponseEntity.ok().body(ResponseDto.of(Status.OK)); + } + + @GetMapping + public ResponseEntity readDishes(@PathVariable String type) { + Category category = categoryService.findCategoryByType(type); + return ResponseEntity.ok().body(CategoryResponseDto.of(category)); + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/controller/DishController.java b/BE/src/main/java/com/codesquad/sidedish/controller/DishController.java new file mode 100644 index 000000000..5df214bd0 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/controller/DishController.java @@ -0,0 +1,34 @@ +package com.codesquad.sidedish.controller; + +import com.codesquad.sidedish.domain.Dish; +import com.codesquad.sidedish.dto.DishDetailResponseDto; +import com.codesquad.sidedish.dto.ResponseDto; +import com.codesquad.sidedish.service.DishService; +import com.codesquad.sidedish.util.Status; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/dishes") +public class DishController { + + private DishService dishService; + + public DishController(DishService dishService) { + this.dishService = dishService; + } + + @GetMapping("/{dishId}") + public ResponseEntity readDish(@PathVariable String dishId) { + Dish dish = dishService.findDishByDishId(dishId); + return ResponseEntity.ok().body(DishDetailResponseDto.of(dish)); + } + + @PutMapping("/{dishId}") + public ResponseEntity orderDish(@PathVariable String dishId, @RequestParam("count") int orderSize) { + if (dishService.orderDish(dishId, orderSize)) { + return ResponseEntity.ok().body(ResponseDto.of(Status.OK)); + } + return ResponseEntity.badRequest().body(ResponseDto.of(Status.OUT_OF_STOCK)); + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/domain/Category.java b/BE/src/main/java/com/codesquad/sidedish/domain/Category.java new file mode 100644 index 000000000..eaff4ac7c --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/domain/Category.java @@ -0,0 +1,60 @@ +package com.codesquad.sidedish.domain; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.MappedCollection; + +import java.util.HashMap; +import java.util.Map; + +public class Category { + + @Id + private Long id; + private String name; + private String type; + + @MappedCollection(idColumn = "category_id", keyColumn = "id") + private Map dishes = new HashMap<>(); + + private Category() { + } + + public Category(String name, String type) { + this.name = name; + this.type = type; + } + + public void addDish(Dish dish) { + dishes.put(dish.getId(), dish); + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public Map getDishes() { + return dishes; + } + + public Dish getDishByDishId(String dishId) { + return dishes.get(dishId); + } + + @Override + public String toString() { + return "Category{" + + "id=" + id + + ", name='" + name + '\'' + + ", type='" + type + '\'' + + ", dishes=" + dishes + + '}'; + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/domain/Dish.java b/BE/src/main/java/com/codesquad/sidedish/domain/Dish.java new file mode 100644 index 000000000..5649d16f2 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/domain/Dish.java @@ -0,0 +1,131 @@ +package com.codesquad.sidedish.domain; + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Embedded; + +public class Dish { + + @Id + private String id; + + private String alt; + private String deliveryType; + private String title; + private String description; + private String normalPrice; + private String sellingPrice; + private String badge; + private Long categoryId; + private String deliveryInfo; + private String deliveryFee; + private int stock; + private String point; + + @Embedded.Nullable + private Image image; + + private Dish() { + } + + public Dish(String id, String alt, String deliveryType, String title, String description, String normalPrice, + String sellingPrice, String badge, Long categoryId, String deliveryInfo, String deliveryFee, int stock, + String point, Image image) { + this.id = id; + this.alt = alt; + this.deliveryType = deliveryType; + this.title = title; + this.description = description; + this.normalPrice = normalPrice; + this.sellingPrice = sellingPrice; + this.badge = badge; + this.categoryId = categoryId; + this.deliveryInfo = deliveryInfo; + this.deliveryFee = deliveryFee; + this.stock = stock; + this.point = point; + this.image = image; + } + + public String getId() { + return id; + } + + public String getAlt() { + return alt; + } + + public String getDeliveryType() { + return deliveryType; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public String getNormalPrice() { + return normalPrice; + } + + public String getSellingPrice() { + return sellingPrice; + } + + public String getBadge() { + return badge; + } + + public Long getCategoryId() { + return categoryId; + } + + public String getDeliveryInfo() { + return deliveryInfo; + } + + public String getDeliveryFee() { + return deliveryFee; + } + + public int getStock() { + return stock; + } + + public String getPoint() { + return point; + } + + public Image getImage() { + return image; + } + + public boolean checkStock(int orderSize) { + return stock >= orderSize; + } + public void updateStock(int orderSize){ + stock -= orderSize; + } + + @Override + public String toString() { + return "Dish{" + + "id='" + id + '\'' + + ", alt='" + alt + '\'' + + ", deliveryType='" + deliveryType + '\'' + + ", title='" + title + '\'' + + ", description='" + description + '\'' + + ", normalPrice='" + normalPrice + '\'' + + ", sellingPrice='" + sellingPrice + '\'' + + ", badge='" + badge + '\'' + + ", categoryId=" + categoryId + + ", deliveryInfo='" + deliveryInfo + '\'' + + ", deliveryFee='" + deliveryFee + '\'' + + ", stock=" + stock + + ", point='" + point + '\'' + + ", image=" + image + + '}'; + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/domain/Image.java b/BE/src/main/java/com/codesquad/sidedish/domain/Image.java new file mode 100644 index 000000000..e77a13762 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/domain/Image.java @@ -0,0 +1,25 @@ +package com.codesquad.sidedish.domain; + +public class Image { + + private String mainImage; + private String topImage; + private String thumbImages; + private String detailSection; + + public String getMainImage() { + return mainImage; + } + + public String getTopImage() { + return topImage; + } + + public String getThumbImages() { + return thumbImages; + } + + public String getDetailSection() { + return detailSection; + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/dto/CategoryResponseDto.java b/BE/src/main/java/com/codesquad/sidedish/dto/CategoryResponseDto.java new file mode 100644 index 000000000..fa2b8a032 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/dto/CategoryResponseDto.java @@ -0,0 +1,59 @@ +package com.codesquad.sidedish.dto; + +import com.codesquad.sidedish.domain.Category; +import com.codesquad.sidedish.domain.Dish; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@JsonPropertyOrder({"type", "name", "dishes"}) +public class CategoryResponseDto { + + @JsonProperty("category") + private String type; + private String name; + private List dishes; + + private CategoryResponseDto(String name, String type, List dishes) { + this.name = name; + this.type = type; + this.dishes = dishes; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public List getDishes() { + return dishes; + } + + public static CategoryResponseDto of(Category category) { + return new CategoryResponseDto(category.getName(), category.getType(), dishesMapToDishResponseDtoList(category.getDishes())); + } + + private static List dishesMapToDishResponseDtoList(Map dishes) { + List dishResponseDto = new ArrayList<>(); + + for (String key : dishes.keySet()) { + dishResponseDto.add(DishResponseDto.of(dishes.get(key))); + } + return dishResponseDto; + } + + @Override + public String toString() { + return "CategoryResponseDto{" + + ", type='" + type + '\'' + + ", name='" + name + '\'' + + ", dishes=" + dishes + + '}'; + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/dto/DishDetailResponseDto.java b/BE/src/main/java/com/codesquad/sidedish/dto/DishDetailResponseDto.java new file mode 100644 index 000000000..7cd5ff740 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/dto/DishDetailResponseDto.java @@ -0,0 +1,97 @@ +package com.codesquad.sidedish.dto; + +import com.codesquad.sidedish.domain.Dish; +import com.codesquad.sidedish.domain.Image; + +public class DishDetailResponseDto { + + private String dishId; + private String topImage; + private String thumbImages; + private String productDescription; + private String point; + private String deliveryInfo; + private String deliveryFee; + private String normalPrice; + private String sellingPrice; + private String detailSection; + + private DishDetailResponseDto(String dishId, String topImage, String thumbImages, String productDescription, + String point, String deliveryInfo, String deliveryFee, String normalPrice, + String sellingPrice, String detailSection) { + this.dishId = dishId; + this.topImage = topImage; + this.thumbImages = thumbImages; + this.productDescription = productDescription; + this.point = point; + this.deliveryInfo = deliveryInfo; + this.deliveryFee = deliveryFee; + this.normalPrice = normalPrice; + this.sellingPrice = sellingPrice; + this.detailSection = detailSection; + } + + public String getDishId() { + return dishId; + } + + public String getTopImage() { + return topImage; + } + + public String getThumbImages() { + return thumbImages; + } + + public String getProductDescription() { + return productDescription; + } + + public String getPoint() { + return point; + } + + public String getDeliveryInfo() { + return deliveryInfo; + } + + public String getDeliveryFee() { + return deliveryFee; + } + + public String getNormalPrice() { + return normalPrice; + } + + public String getSellingPrice() { + return sellingPrice; + } + + public String getDetailSection() { + return detailSection; + } + + public static DishDetailResponseDto of(Dish dish) { + Image image = dish.getImage(); + return new DishDetailResponseDto(dish.getId(), image.getTopImage(), image.getThumbImages(), + dish.getDescription(), dish.getPoint(), dish.getDeliveryInfo(), dish.getDeliveryFee(), + dish.getNormalPrice(), dish.getSellingPrice(), image.getDetailSection()); + } + + @Override + public String toString() { + return "DishDetailResponseDto{" + + "dishId='" + dishId + '\'' + + ", topImage='" + topImage + '\'' + + ", thumbImages='" + thumbImages + '\'' + + ", productDescription='" + productDescription + '\'' + + ", point='" + point + '\'' + + ", deliveryInfo='" + deliveryInfo + '\'' + + ", deliveryFee='" + deliveryFee + '\'' + + ", normalPrice='" + normalPrice + '\'' + + ", sellingPrice='" + sellingPrice + '\'' + + ", detailSection='" + detailSection + '\'' + + '}'; + } +} + diff --git a/BE/src/main/java/com/codesquad/sidedish/dto/DishResponseDto.java b/BE/src/main/java/com/codesquad/sidedish/dto/DishResponseDto.java new file mode 100644 index 000000000..52ec0427e --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/dto/DishResponseDto.java @@ -0,0 +1,95 @@ +package com.codesquad.sidedish.dto; + +import com.codesquad.sidedish.domain.Dish; +import com.codesquad.sidedish.domain.Image; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DishResponseDto { + + @JsonProperty("dishId") + private String id; + + @JsonProperty("image") + private String mainImage; + private String alt; + private String deliveryType; + private String title; + private String description; + private String normalPrice; + private String sellingPrice; + private String badge; + + + private DishResponseDto(String id, String mainImage, String alt, String deliveryType, + String title, String description, String normalPrice, String sellingPrice, + String badge) { + this.id = id; + this.mainImage = mainImage; + this.alt = alt; + this.deliveryType = deliveryType; + this.title = title; + this.description = description; + this.normalPrice = normalPrice; + this.sellingPrice = sellingPrice; + this.badge = badge; + } + + public String getId() { + return id; + } + + public String getMainImage() { + return mainImage; + } + + public String getAlt() { + return alt; + } + + public String getDeliveryType() { + return deliveryType; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public String getNormalPrice() { + return normalPrice; + } + + public String getSellingPrice() { + return sellingPrice; + } + + public String getBadge() { + return badge; + } + + + public static DishResponseDto of(Dish dish) { + Image image = dish.getImage(); + return new DishResponseDto(dish.getId(), image.getMainImage(), dish.getAlt(), + dish.getDeliveryType(), dish.getTitle(), dish.getDescription(), + dish.getNormalPrice(), dish.getSellingPrice(), dish.getBadge()); + } + + @Override + public String toString() { + return "DishResponseDto{" + + "id='" + id + '\'' + + ", mainImage='" + mainImage + '\'' + + ", alt='" + alt + '\'' + + ", deliveryType='" + deliveryType + '\'' + + ", title='" + title + '\'' + + ", description='" + description + '\'' + + ", normalPrice='" + normalPrice + '\'' + + ", sellingPrice='" + sellingPrice + '\'' + + ", badge='" + badge + '\'' + + '}'; + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/dto/ResponseDto.java b/BE/src/main/java/com/codesquad/sidedish/dto/ResponseDto.java new file mode 100644 index 000000000..2663da424 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/dto/ResponseDto.java @@ -0,0 +1,28 @@ +package com.codesquad.sidedish.dto; + +import com.codesquad.sidedish.util.Status; +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class ResponseDto { + + @JsonIgnore + private Status status; + private String message; + + private ResponseDto(Status status) { + this.status = status; + this.message = status.getMessage(); + } + + public Status getStatus() { + return status; + } + + public String getMessage() { + return message; + } + + public static ResponseDto of (Status status){ + return new ResponseDto(status); + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/exception/NotFoundException.java b/BE/src/main/java/com/codesquad/sidedish/exception/NotFoundException.java new file mode 100644 index 000000000..9a0a0076c --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/exception/NotFoundException.java @@ -0,0 +1,19 @@ +package com.codesquad.sidedish.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.NOT_FOUND) +public class NotFoundException extends RuntimeException { + + private String message; + + public NotFoundException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return message; + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/repository/CategoryRepository.java b/BE/src/main/java/com/codesquad/sidedish/repository/CategoryRepository.java new file mode 100644 index 000000000..5ee0f66d6 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/repository/CategoryRepository.java @@ -0,0 +1,17 @@ +package com.codesquad.sidedish.repository; + +import com.codesquad.sidedish.domain.Category; +import org.springframework.data.jdbc.repository.query.Query; +import org.springframework.data.repository.CrudRepository; + +import java.util.Optional; + +public interface CategoryRepository extends CrudRepository { + + Optional findByType(String categoryType); + + @Query("SELECT category.id, category.type, category.name FROM category " + + "INNER JOIN dish ON dish.category_id = category.id " + + "WHERE dish.id = :dishId") + Optional findByDishId(String dishId); +} diff --git a/BE/src/main/java/com/codesquad/sidedish/service/CategoryService.java b/BE/src/main/java/com/codesquad/sidedish/service/CategoryService.java new file mode 100644 index 000000000..b7be2edb2 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/service/CategoryService.java @@ -0,0 +1,28 @@ +package com.codesquad.sidedish.service; + +import com.codesquad.sidedish.exception.NotFoundException; +import com.codesquad.sidedish.domain.Category; +import com.codesquad.sidedish.domain.Dish; +import com.codesquad.sidedish.repository.CategoryRepository; +import com.codesquad.sidedish.util.Status; +import org.springframework.stereotype.Service; + +@Service +public class CategoryService { + + private CategoryRepository categoryRepository; + + public CategoryService(CategoryRepository categoryRepository) { + this.categoryRepository = categoryRepository; + } + + public Category findCategoryByType(String type) { + return categoryRepository.findByType(type).orElseThrow(() -> new NotFoundException(Status.NOTFOUND_CATEGORY.getMessage())); + } + + public void addDishToCategory(String type, Dish dish) { + Category category = findCategoryByType(type); + category.addDish(dish); + categoryRepository.save(category); + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/service/DishService.java b/BE/src/main/java/com/codesquad/sidedish/service/DishService.java new file mode 100644 index 000000000..368127ae8 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/service/DishService.java @@ -0,0 +1,41 @@ +package com.codesquad.sidedish.service; + +import com.codesquad.sidedish.domain.Category; +import com.codesquad.sidedish.domain.Dish; +import com.codesquad.sidedish.exception.NotFoundException; +import com.codesquad.sidedish.repository.CategoryRepository; +import com.codesquad.sidedish.util.Status; +import org.springframework.stereotype.Service; + +@Service +public class DishService { + + private CategoryRepository categoryRepository; + + public DishService(CategoryRepository categoryRepository) { + this.categoryRepository = categoryRepository; + } + + public Category findByDishId(String dishId){ + return categoryRepository.findByDishId(dishId).orElseThrow(() -> + new NotFoundException(Status.NOTFOUND_DISH.getMessage())); + } + + public Dish findDishByDishId(String dishId) { + Category category = findByDishId(dishId); + return category.getDishByDishId(dishId); + } + + public boolean orderDish(String dishId, int orderSize) { + Category category = findByDishId(dishId); + Dish dish = findDishByDishId(dishId); + + if (dish.checkStock(orderSize)) { + dish.updateStock(orderSize); + category.addDish(dish); + categoryRepository.save(category); + return true; + } + return false; + } +} diff --git a/BE/src/main/java/com/codesquad/sidedish/util/Status.java b/BE/src/main/java/com/codesquad/sidedish/util/Status.java new file mode 100644 index 000000000..18b32d0e3 --- /dev/null +++ b/BE/src/main/java/com/codesquad/sidedish/util/Status.java @@ -0,0 +1,18 @@ +package com.codesquad.sidedish.util; + +public enum Status { + OK("Success"), + NOTFOUND_CATEGORY("존재하지 않는 카테고리입니다."), + NOTFOUND_DISH("존재하지 않는 반찬입니다."), + OUT_OF_STOCK("반찬 재고 부족"); + + private String message; + + Status(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/BE/src/main/resources/application.properties b/BE/src/main/resources/application.properties new file mode 100644 index 000000000..a981be3e4 --- /dev/null +++ b/BE/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.datasource.url=jdbc:mysql://3.35.220.240:3306/sidedish?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC&allowPublicKeyRetrieval=true&validationQuery="SELECT 1" +spring.datasource.username=team11 +spring.datasource.password=0011 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +server.error.include-message=always diff --git a/BE/src/main/resources/schema.sql b/BE/src/main/resources/schema.sql new file mode 100644 index 000000000..6b8329e1c --- /dev/null +++ b/BE/src/main/resources/schema.sql @@ -0,0 +1,28 @@ +create table category ( + id int not null auto_increment, + name varchar(45) not null, + type varchar(10) not null, + primary key (id) +); + +create table dish ( + id varchar(5) not null, + main_image varchar(100) not null, + alt varchar(45) not null, + delivery_type varchar(45) not null, + title varchar(45) not null, + description varchar(45) not null, + normal_price varchar(45) not null, + selling_price varchar(45), + badge varchar(45), + category_id int not null, + top_image varchar(200) not null, + thumb_images varchar(1000) not null, + delivery_info varchar(1000) not null, + delivery_fee varchar(45) not null, + detail_section varchar(1000) not null, + stock int not null, + point varchar(5) not null, + primary key (id), + foreign key (category_id) references category (id) +); diff --git a/BE/src/test/java/com/codesquad/sidedish/SidedishApplicationTests.java b/BE/src/test/java/com/codesquad/sidedish/SidedishApplicationTests.java new file mode 100644 index 000000000..a22958a8a --- /dev/null +++ b/BE/src/test/java/com/codesquad/sidedish/SidedishApplicationTests.java @@ -0,0 +1,9 @@ +package com.codesquad.sidedish; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SidedishApplicationTests { + +} diff --git a/README.md b/README.md index c04306379..a05e4e73d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,38 @@ -# sidedish -그룹프로젝트 #2 +# 팀원 구성 +|팀원|소속|자기소개| +|------|---|---| +|마르코🦝|BE|지브리 신작에 실망한 🥶| +|Bibi🤑|BE|현질에 맛을 느낀 😫| +|Hong🐶|iOS|현업 강아지 똥치우기💩| +|Downey🤖|iOS|모코코 캐는중🌱| + +# 팀 규칙 +## 스크럼 방식 +10:00 ~ 10:30 Zoom 그룹 내에서 근황 공유 간단 스크럼😁 +10:30 ~ 11:00 팀 내에서 자신의 진행 상황, 어려운 점 공유 및 오늘의 진행 할 내용 공유! 🤗 + +## 회의 시간 +필요할 때 gather에서 회의 소집☠️ + +## 참여 시간 +11:00 ~ 18:00 까지 팀 단위 모각코😇😈 + +## 코딩 스타일 + +### iOS +TDD 지향 : 각 함수의 Unit Test가 가능하도록 개발.😎 +iOS UI 개발 방식 : Storyboard 위주 개발.😵 +재사용 성을 최대한 고려한 개발.🤪 + +### BackEnd + +## 할일 정리 +1. 기획서 내용 분석 +2. Epic - Story - Task 만들기 +3. Task에 따른 Issue 발행 +4. Issue에 따른 Branch 생성 +5. 작업 완료 시 개발 브랜치에 PR +6. 리뷰어 : 같은 팀원, Label, Proj, MileStone 지정. +7. Issue에 PR Link +8. PR Merge +9. Issue Close 💩