From 6616581a0365776aa3e679eb1edb2b44c57fe897 Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 13 Oct 2023 15:00:47 +0900 Subject: [PATCH 001/383] init: initialize the project to clarify collaboration without .mvn --- .gitignore | 34 ++ mvnw | 308 ++++++++++++++++++ mvnw.cmd | 205 ++++++++++++ pom.xml | 41 +++ .../VoucherManangementApplication.java | 13 + src/main/resources/application.properties | 1 + .../VoucherManangementApplicationTests.java | 13 + 7 files changed, 615 insertions(+) create mode 100644 .gitignore create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 src/main/java/com/programmers/vouchermanangement/VoucherManangementApplication.java create mode 100644 src/main/resources/application.properties create mode 100644 src/test/java/com/programmers/vouchermanangement/VoucherManangementApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..fa0c4c52c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.mvn + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/mvnw b/mvnw new file mode 100644 index 0000000000..66df285428 --- /dev/null +++ b/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + 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 + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000000..95ba6f54ac --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. 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, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000..86d0b7f797 --- /dev/null +++ b/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.1.4 + + + com.programmers + voucherManangement + 0.0.1-SNAPSHOT + voucherManangement + voucherManangement + + 17 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/src/main/java/com/programmers/vouchermanangement/VoucherManangementApplication.java b/src/main/java/com/programmers/vouchermanangement/VoucherManangementApplication.java new file mode 100644 index 0000000000..47179fffc9 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanangement/VoucherManangementApplication.java @@ -0,0 +1,13 @@ +package com.programmers.vouchermanangement; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class VoucherManangementApplication { + + public static void main(String[] args) { + SpringApplication.run(VoucherManangementApplication.class, args); + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/src/test/java/com/programmers/vouchermanangement/VoucherManangementApplicationTests.java b/src/test/java/com/programmers/vouchermanangement/VoucherManangementApplicationTests.java new file mode 100644 index 0000000000..5207b74d16 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanangement/VoucherManangementApplicationTests.java @@ -0,0 +1,13 @@ +package com.programmers.vouchermanangement; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class VoucherManangementApplicationTests { + + @Test + void contextLoads() { + } + +} From fb92697d1fbfa5889299423d0e94e337c9500cd9 Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 13 Oct 2023 15:14:03 +0900 Subject: [PATCH 002/383] chore: exclude .mvn to .gitignore --- .gitignore | 1 - .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 62547 bytes .mvn/wrapper/maven-wrapper.properties | 2 ++ 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties diff --git a/.gitignore b/.gitignore index fa0c4c52c2..549e00a2a9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ target/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ -.mvn ### STS ### .apt_generated diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..cb28b0e37c7d206feb564310fdeec0927af4123a GIT binary patch literal 62547 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 A?*IS* literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..5f0536eb74 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar From 9a7739691dda4c62d2c6b1161d653fb5e81dc993 Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 13 Oct 2023 15:17:10 +0900 Subject: [PATCH 003/383] style: fix typo for management --- .../VoucherManagementApplication.java} | 6 +++--- .../VoucherManagementApplicationTests.java} | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/main/java/com/programmers/{vouchermanangement/VoucherManangementApplication.java => vouchermanagement/VoucherManagementApplication.java} (55%) rename src/test/java/com/programmers/{vouchermanangement/VoucherManangementApplicationTests.java => vouchermanagement/VoucherManagementApplicationTests.java} (63%) diff --git a/src/main/java/com/programmers/vouchermanangement/VoucherManangementApplication.java b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java similarity index 55% rename from src/main/java/com/programmers/vouchermanangement/VoucherManangementApplication.java rename to src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java index 47179fffc9..df8683ebea 100644 --- a/src/main/java/com/programmers/vouchermanangement/VoucherManangementApplication.java +++ b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java @@ -1,13 +1,13 @@ -package com.programmers.vouchermanangement; +package com.programmers.vouchermanagement; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class VoucherManangementApplication { +public class VoucherManagementApplication { public static void main(String[] args) { - SpringApplication.run(VoucherManangementApplication.class, args); + SpringApplication.run(VoucherManagementApplication.class, args); } } diff --git a/src/test/java/com/programmers/vouchermanangement/VoucherManangementApplicationTests.java b/src/test/java/com/programmers/vouchermanagement/VoucherManagementApplicationTests.java similarity index 63% rename from src/test/java/com/programmers/vouchermanangement/VoucherManangementApplicationTests.java rename to src/test/java/com/programmers/vouchermanagement/VoucherManagementApplicationTests.java index 5207b74d16..85414204ad 100644 --- a/src/test/java/com/programmers/vouchermanangement/VoucherManangementApplicationTests.java +++ b/src/test/java/com/programmers/vouchermanagement/VoucherManagementApplicationTests.java @@ -1,10 +1,10 @@ -package com.programmers.vouchermanangement; +package com.programmers.vouchermanagement; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest -class VoucherManangementApplicationTests { +class VoucherManagementApplicationTests { @Test void contextLoads() { From 45bc3ce1977eff4ef0d35405838a6cebea37394a Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 13 Oct 2023 15:25:04 +0900 Subject: [PATCH 004/383] chore: fix typo in pom --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 86d0b7f797..8b9fa86804 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,8 @@ com.programmers voucherManangement 0.0.1-SNAPSHOT - voucherManangement - voucherManangement + voucherManagement + voucherManagement 17 From 3917ebed9690446ef73bef568e741de0b73707b3 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 13:43:38 +0900 Subject: [PATCH 005/383] chore: add text-io dependency --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 8b9fa86804..e8eb588309 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,12 @@ spring-boot-starter-test test + + + org.beryx + text-io + 3.4.1 + From c7bcb695227dbdb9341e394ca2e6913c6cc6ddcb Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 14:00:42 +0900 Subject: [PATCH 006/383] feat: add exit feature --- .../vouchermanagement/AppConfig.java | 14 +++++++++ .../programmers/vouchermanagement/Client.java | 31 +++++++++++++++++++ .../vouchermanagement/ConsoleAppRunner.java | 22 +++++++++++++ .../vouchermanagement/ConsoleManager.java | 28 +++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/AppConfig.java create mode 100644 src/main/java/com/programmers/vouchermanagement/Client.java create mode 100644 src/main/java/com/programmers/vouchermanagement/ConsoleAppRunner.java create mode 100644 src/main/java/com/programmers/vouchermanagement/ConsoleManager.java diff --git a/src/main/java/com/programmers/vouchermanagement/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/AppConfig.java new file mode 100644 index 0000000000..f32c6e95d3 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/AppConfig.java @@ -0,0 +1,14 @@ +package com.programmers.vouchermanagement; + +import org.beryx.textio.TextIO; +import org.beryx.textio.TextIoFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfig { + @Bean + public TextIO textIO() { + return TextIoFactory.getTextIO(); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/Client.java b/src/main/java/com/programmers/vouchermanagement/Client.java new file mode 100644 index 0000000000..541759502a --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/Client.java @@ -0,0 +1,31 @@ +package com.programmers.vouchermanagement; + +import org.springframework.stereotype.Component; + +@Component +public class Client { + private final ConsoleManager consoleManager; + + public Client(ConsoleManager consoleManager) { + this.consoleManager = consoleManager; + } + + public boolean selectMenu() { + String menu = consoleManager.selectMenu(); + + if (!validateMenu(menu)) { + consoleManager.printExit(); + return false; + } + + return true; + } + + private boolean validateMenu(String menu) { + if (menu.equals("exit")) { + return false; + } + + return true; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/ConsoleAppRunner.java new file mode 100644 index 0000000000..888d6dbc37 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/ConsoleAppRunner.java @@ -0,0 +1,22 @@ +package com.programmers.vouchermanagement; + +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +@Component +public class ConsoleAppRunner implements ApplicationRunner { + private final Client client; + + public ConsoleAppRunner(Client client) { + this.client = client; + } + + @Override + public void run(ApplicationArguments args) { + boolean isRunning = true; + while (isRunning) { + isRunning = client.selectMenu(); + } + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java new file mode 100644 index 0000000000..7fd002ba52 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java @@ -0,0 +1,28 @@ +package com.programmers.vouchermanagement; + +import org.beryx.textio.TextIO; +import org.springframework.stereotype.Component; + +@Component +public class ConsoleManager { + private static final String menuSelectionInstruction = """ + ===Voucher Program === + Type **exit** to exit the program. + Type **create** to create a new voucher. + Type **list** to list all vouchers. + """; + private final TextIO textIO; + + public ConsoleManager(TextIO textIO) { + this.textIO = textIO; + } + + public String selectMenu() { + return textIO.newStringInputReader() + .read(menuSelectionInstruction); + } + + public void printExit() { + textIO.getTextTerminal().println("System exits."); + } +} From bc3e9fb0838200cc82258853d27b827af1c867cd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 16 Oct 2023 14:22:20 +0900 Subject: [PATCH 007/383] feat: implement FixedAmountVoucher and PercentVoucher --- .../vouchermanagement/FixedAmountVoucher.java | 23 +++++++++++++++++++ .../vouchermanagement/PercentVoucher.java | 23 +++++++++++++++++++ .../vouchermanagement/Voucher.java | 10 ++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java create mode 100644 src/main/java/com/programmers/vouchermanagement/PercentVoucher.java create mode 100644 src/main/java/com/programmers/vouchermanagement/Voucher.java diff --git a/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java new file mode 100644 index 0000000000..00b670c74e --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java @@ -0,0 +1,23 @@ +package com.programmers.vouchermanagement; + +import java.util.UUID; + +public class FixedAmountVoucher implements Voucher { + private final UUID voucherID; + private final long discountAmount; + + public FixedAmountVoucher(UUID voucherID, long discountAmount) { + this.voucherID = voucherID; + this.discountAmount = discountAmount; + } + + @Override + public UUID getVoucherId() { + return voucherID; + } + + @Override + public long discount(long priceBeforeDiscount) { + return priceBeforeDiscount - discountAmount; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java new file mode 100644 index 0000000000..66f6c9c360 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java @@ -0,0 +1,23 @@ +package com.programmers.vouchermanagement; + +import java.util.UUID; + +public class PercentVoucher implements Voucher { + private final UUID voucherID; + private final double discountPercent; + + public PercentVoucher(UUID voucherID, double discountPercent) { + this.voucherID = voucherID; + this.discountPercent = discountPercent; + } + + @Override + public UUID getVoucherId() { + return voucherID; + } + + @Override + public long discount(long priceBeforeDiscount) { + return (long) (priceBeforeDiscount * (1 - discountPercent / 100)); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/Voucher.java b/src/main/java/com/programmers/vouchermanagement/Voucher.java new file mode 100644 index 0000000000..bc9b5556aa --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/Voucher.java @@ -0,0 +1,10 @@ +package com.programmers.vouchermanagement; + +import java.util.UUID; + +public interface Voucher { + UUID getVoucherId(); + + long discount(long priceBeforeDiscount); + +} From 270b64ecd8b59a934fe189c1e7c92b26b007d642 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 14:37:53 +0900 Subject: [PATCH 008/383] feat: add save feature to voucher repository --- .../InMemoryVoucherRepository.java | 21 +++++++++++++++++++ .../vouchermanagement/VoucherRepository.java | 5 +++++ 2 files changed, 26 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/InMemoryVoucherRepository.java create mode 100644 src/main/java/com/programmers/vouchermanagement/VoucherRepository.java diff --git a/src/main/java/com/programmers/vouchermanagement/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/InMemoryVoucherRepository.java new file mode 100644 index 0000000000..ef7e5d4f3b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/InMemoryVoucherRepository.java @@ -0,0 +1,21 @@ +package com.programmers.vouchermanagement; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.springframework.stereotype.Repository; + +@Repository +public class InMemoryVoucherRepository implements VoucherRepository { + private final Map vouchers; + + public InMemoryVoucherRepository() { + vouchers = new HashMap<>(); + } + + @Override + public void save(Voucher voucher) { + vouchers.put(voucher.getVoucherId(), voucher); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/VoucherRepository.java new file mode 100644 index 0000000000..1fb3b41794 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/VoucherRepository.java @@ -0,0 +1,5 @@ +package com.programmers.vouchermanagement; + +public interface VoucherRepository { + void save(Voucher voucher); +} From 73339c08500899b4347c19a8d895bedf1cd18863 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 16 Oct 2023 14:56:27 +0900 Subject: [PATCH 009/383] feat: add create feature in VoucherService --- .../vouchermanagement/FixedAmountVoucher.java | 5 ++++ .../vouchermanagement/PercentVoucher.java | 5 ++++ .../vouchermanagement/Voucher.java | 2 ++ .../vouchermanagement/VoucherService.java | 24 +++++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/VoucherService.java diff --git a/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java index 00b670c74e..37d449d12d 100644 --- a/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java @@ -20,4 +20,9 @@ public UUID getVoucherId() { public long discount(long priceBeforeDiscount) { return priceBeforeDiscount - discountAmount; } + + @Override + public boolean validatePositiveDiscount() { + return discountAmount > 0; + } } diff --git a/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java index 66f6c9c360..e1cbeaf70c 100644 --- a/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java @@ -20,4 +20,9 @@ public UUID getVoucherId() { public long discount(long priceBeforeDiscount) { return (long) (priceBeforeDiscount * (1 - discountPercent / 100)); } + + @Override + public boolean validatePositiveDiscount() { + return discountPercent > 0; + } } diff --git a/src/main/java/com/programmers/vouchermanagement/Voucher.java b/src/main/java/com/programmers/vouchermanagement/Voucher.java index bc9b5556aa..473616756d 100644 --- a/src/main/java/com/programmers/vouchermanagement/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/Voucher.java @@ -7,4 +7,6 @@ public interface Voucher { long discount(long priceBeforeDiscount); + boolean validatePositiveDiscount(); + } diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/VoucherService.java new file mode 100644 index 0000000000..7784bc4a3e --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/VoucherService.java @@ -0,0 +1,24 @@ +package com.programmers.vouchermanagement; + +import org.springframework.stereotype.Service; + +@Service +public class VoucherService { + private final VoucherRepository voucherRepository; + + public VoucherService(VoucherRepository voucherRepository) { + this.voucherRepository = voucherRepository; + } + + public Voucher create(Voucher voucher) { + validateDiscount(voucher); + voucherRepository.save(voucher); + return voucher; + } + + public void validateDiscount(Voucher voucher) { + if (!voucher.validatePositiveDiscount()) { + throw new IllegalArgumentException("input should be a number greater than 0"); + } + } +} From 056fa629ec23a0baa79901bc28e7f4b398253c30 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 15:41:08 +0900 Subject: [PATCH 010/383] refactor: edit type of discountPercent from double to long --- .../com/programmers/vouchermanagement/PercentVoucher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java index e1cbeaf70c..4a3897ef40 100644 --- a/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java @@ -4,9 +4,9 @@ public class PercentVoucher implements Voucher { private final UUID voucherID; - private final double discountPercent; + private final long discountPercent; - public PercentVoucher(UUID voucherID, double discountPercent) { + public PercentVoucher(UUID voucherID, long discountPercent) { this.voucherID = voucherID; this.discountPercent = discountPercent; } @@ -18,7 +18,7 @@ public UUID getVoucherId() { @Override public long discount(long priceBeforeDiscount) { - return (long) (priceBeforeDiscount * (1 - discountPercent / 100)); + return (long) (priceBeforeDiscount * (1 - discountPercent / 100D)); } @Override From 6c7bdd3832245d4c19bb2be0b459cfe192057152 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 15:42:51 +0900 Subject: [PATCH 011/383] feat: add create feature to VoucherController --- .../vouchermanagement/VoucherController.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/VoucherController.java diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/VoucherController.java new file mode 100644 index 0000000000..b8042f596a --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/VoucherController.java @@ -0,0 +1,16 @@ +package com.programmers.vouchermanagement; + +import org.springframework.stereotype.Controller; + +@Controller +public class VoucherController { + private final VoucherService voucherService; + + public VoucherController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + public Voucher create(Voucher voucher) { + return voucherService.create(voucher); + } +} From 051379a4910017590a1cfad28edfb90308822730 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 15:44:04 +0900 Subject: [PATCH 012/383] feat: add execute menu with voucher creation to Client --- .../com/programmers/vouchermanagement/Client.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/Client.java b/src/main/java/com/programmers/vouchermanagement/Client.java index 541759502a..85d40183a4 100644 --- a/src/main/java/com/programmers/vouchermanagement/Client.java +++ b/src/main/java/com/programmers/vouchermanagement/Client.java @@ -5,9 +5,11 @@ @Component public class Client { private final ConsoleManager consoleManager; + private final VoucherController voucherController; - public Client(ConsoleManager consoleManager) { + public Client(ConsoleManager consoleManager, VoucherController voucherController) { this.consoleManager = consoleManager; + this.voucherController = voucherController; } public boolean selectMenu() { @@ -18,6 +20,7 @@ public boolean selectMenu() { return false; } + executeMenu(menu); return true; } @@ -28,4 +31,13 @@ private boolean validateMenu(String menu) { return true; } + + public void executeMenu(String menu) { + switch (menu) { + case "create" -> { + Voucher voucher = consoleManager.instructCreate(); + voucherController.create(voucher); + } + } + } } From 0302aa09ab3767b115e7751e037b97bd1046b45d Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 15:44:55 +0900 Subject: [PATCH 013/383] feat: add instruction for voucher creation to ConsoleManager --- .../vouchermanagement/ConsoleManager.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java index 7fd002ba52..615172bb56 100644 --- a/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java @@ -1,5 +1,7 @@ package com.programmers.vouchermanagement; +import java.util.UUID; + import org.beryx.textio.TextIO; import org.springframework.stereotype.Component; @@ -11,6 +13,14 @@ public class ConsoleManager { Type **create** to create a new voucher. Type **list** to list all vouchers. """; + private static final String createSelectionInstruction = """ + Please select the type of voucher to create. + Type **fixed** to create a fixed amount voucher. + Type **percent** to create a percent discount voucher. + """; + + private static final String voucherDiscountAmountDecision = "Please type the amount/percent of discount of the voucher."; + private final TextIO textIO; public ConsoleManager(TextIO textIO) { @@ -22,6 +32,27 @@ public String selectMenu() { .read(menuSelectionInstruction); } + public Voucher instructCreate() { + String createMenu = textIO.newStringInputReader() + .read(createSelectionInstruction); + + long discountAmount = textIO.newLongInputReader() + .read(voucherDiscountAmountDecision); + + switch (createMenu) { + case "fixed" -> { + return new FixedAmountVoucher(UUID.randomUUID(), discountAmount); + } + + case "percent" -> { + return new PercentVoucher(UUID.randomUUID(), discountAmount); + } + + default -> + throw new IllegalArgumentException("Voucher type should be either fixed amount or percent discount voucher"); + } + } + public void printExit() { textIO.getTextTerminal().println("System exits."); } From 36391cec30cffdad517b11259cc1f24c867748b5 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 15:51:16 +0900 Subject: [PATCH 014/383] refactor: rebuild the structure of overall packaging of the project --- .../programmers/vouchermanagement/VoucherRepository.java | 5 ----- .../vouchermanagement/{ => configuration}/AppConfig.java | 2 +- .../vouchermanagement/{ => console}/Client.java | 5 ++++- .../vouchermanagement/{ => console}/ConsoleManager.java | 6 +++++- .../vouchermanagement/{ => runner}/ConsoleAppRunner.java | 4 +++- .../{ => voucher}/FixedAmountVoucher.java | 4 +++- .../{ => voucher}/InMemoryVoucherRepository.java | 5 ++++- .../vouchermanagement/{ => voucher}/PercentVoucher.java | 4 +++- .../vouchermanagement/{ => voucher}/Voucher.java | 2 +- .../vouchermanagement/{ => voucher}/VoucherController.java | 2 +- .../vouchermanagement/voucher/VoucherRepository.java | 7 +++++++ .../vouchermanagement/{ => voucher}/VoucherService.java | 2 +- 12 files changed, 33 insertions(+), 15 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/VoucherRepository.java rename src/main/java/com/programmers/vouchermanagement/{ => configuration}/AppConfig.java (84%) rename src/main/java/com/programmers/vouchermanagement/{ => console}/Client.java (85%) rename src/main/java/com/programmers/vouchermanagement/{ => console}/ConsoleManager.java (88%) rename src/main/java/com/programmers/vouchermanagement/{ => runner}/ConsoleAppRunner.java (83%) rename src/main/java/com/programmers/vouchermanagement/{ => voucher}/FixedAmountVoucher.java (84%) rename src/main/java/com/programmers/vouchermanagement/{ => voucher}/InMemoryVoucherRepository.java (71%) rename src/main/java/com/programmers/vouchermanagement/{ => voucher}/PercentVoucher.java (85%) rename src/main/java/com/programmers/vouchermanagement/{ => voucher}/Voucher.java (76%) rename src/main/java/com/programmers/vouchermanagement/{ => voucher}/VoucherController.java (87%) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java rename src/main/java/com/programmers/vouchermanagement/{ => voucher}/VoucherService.java (92%) diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/VoucherRepository.java deleted file mode 100644 index 1fb3b41794..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/VoucherRepository.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.programmers.vouchermanagement; - -public interface VoucherRepository { - void save(Voucher voucher); -} diff --git a/src/main/java/com/programmers/vouchermanagement/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java similarity index 84% rename from src/main/java/com/programmers/vouchermanagement/AppConfig.java rename to src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java index f32c6e95d3..bbcea60f67 100644 --- a/src/main/java/com/programmers/vouchermanagement/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.configuration; import org.beryx.textio.TextIO; import org.beryx.textio.TextIoFactory; diff --git a/src/main/java/com/programmers/vouchermanagement/Client.java b/src/main/java/com/programmers/vouchermanagement/console/Client.java similarity index 85% rename from src/main/java/com/programmers/vouchermanagement/Client.java rename to src/main/java/com/programmers/vouchermanagement/console/Client.java index 85d40183a4..060b335522 100644 --- a/src/main/java/com/programmers/vouchermanagement/Client.java +++ b/src/main/java/com/programmers/vouchermanagement/console/Client.java @@ -1,7 +1,10 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.console; import org.springframework.stereotype.Component; +import com.programmers.vouchermanagement.voucher.Voucher; +import com.programmers.vouchermanagement.voucher.VoucherController; + @Component public class Client { private final ConsoleManager consoleManager; diff --git a/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java similarity index 88% rename from src/main/java/com/programmers/vouchermanagement/ConsoleManager.java rename to src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java index 615172bb56..eb5eaffb29 100644 --- a/src/main/java/com/programmers/vouchermanagement/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java @@ -1,10 +1,14 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.console; import java.util.UUID; import org.beryx.textio.TextIO; import org.springframework.stereotype.Component; +import com.programmers.vouchermanagement.voucher.FixedAmountVoucher; +import com.programmers.vouchermanagement.voucher.PercentVoucher; +import com.programmers.vouchermanagement.voucher.Voucher; + @Component public class ConsoleManager { private static final String menuSelectionInstruction = """ diff --git a/src/main/java/com/programmers/vouchermanagement/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java similarity index 83% rename from src/main/java/com/programmers/vouchermanagement/ConsoleAppRunner.java rename to src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java index 888d6dbc37..1e2e286297 100644 --- a/src/main/java/com/programmers/vouchermanagement/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java @@ -1,9 +1,11 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.runner; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; +import com.programmers.vouchermanagement.console.Client; + @Component public class ConsoleAppRunner implements ApplicationRunner { private final Client client; diff --git a/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java similarity index 84% rename from src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java rename to src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java index 37d449d12d..1c34ec2cc7 100644 --- a/src/main/java/com/programmers/vouchermanagement/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java @@ -1,7 +1,9 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.voucher; import java.util.UUID; +import com.programmers.vouchermanagement.voucher.Voucher; + public class FixedAmountVoucher implements Voucher { private final UUID voucherID; private final long discountAmount; diff --git a/src/main/java/com/programmers/vouchermanagement/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java similarity index 71% rename from src/main/java/com/programmers/vouchermanagement/InMemoryVoucherRepository.java rename to src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java index ef7e5d4f3b..ed40c80046 100644 --- a/src/main/java/com/programmers/vouchermanagement/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.voucher; import java.util.HashMap; import java.util.Map; @@ -6,6 +6,9 @@ import org.springframework.stereotype.Repository; +import com.programmers.vouchermanagement.voucher.Voucher; +import com.programmers.vouchermanagement.voucher.VoucherRepository; + @Repository public class InMemoryVoucherRepository implements VoucherRepository { private final Map vouchers; diff --git a/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java similarity index 85% rename from src/main/java/com/programmers/vouchermanagement/PercentVoucher.java rename to src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java index 4a3897ef40..4b2f4a708d 100644 --- a/src/main/java/com/programmers/vouchermanagement/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java @@ -1,7 +1,9 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.voucher; import java.util.UUID; +import com.programmers.vouchermanagement.voucher.Voucher; + public class PercentVoucher implements Voucher { private final UUID voucherID; private final long discountPercent; diff --git a/src/main/java/com/programmers/vouchermanagement/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java similarity index 76% rename from src/main/java/com/programmers/vouchermanagement/Voucher.java rename to src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java index 473616756d..bc076da31b 100644 --- a/src/main/java/com/programmers/vouchermanagement/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.voucher; import java.util.UUID; diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java similarity index 87% rename from src/main/java/com/programmers/vouchermanagement/VoucherController.java rename to src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index b8042f596a..4d2567676b 100644 --- a/src/main/java/com/programmers/vouchermanagement/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.voucher; import org.springframework.stereotype.Controller; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java new file mode 100644 index 0000000000..6522cffe37 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java @@ -0,0 +1,7 @@ +package com.programmers.vouchermanagement.voucher; + +import com.programmers.vouchermanagement.voucher.Voucher; + +public interface VoucherRepository { + void save(Voucher voucher); +} diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java similarity index 92% rename from src/main/java/com/programmers/vouchermanagement/VoucherService.java rename to src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java index 7784bc4a3e..10f478f3d7 100644 --- a/src/main/java/com/programmers/vouchermanagement/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement; +package com.programmers.vouchermanagement.voucher; import org.springframework.stereotype.Service; From d864e2c6005c61e6424af291707c160b33564b71 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 16 Oct 2023 15:58:02 +0900 Subject: [PATCH 015/383] comment: leave to-dos for consideration in the future --- .../java/com/programmers/vouchermanagement/console/Client.java | 1 + .../programmers/vouchermanagement/console/ConsoleManager.java | 2 ++ .../vouchermanagement/voucher/FixedAmountVoucher.java | 2 -- .../vouchermanagement/voucher/InMemoryVoucherRepository.java | 3 --- .../programmers/vouchermanagement/voucher/PercentVoucher.java | 2 -- .../vouchermanagement/voucher/VoucherController.java | 1 + 6 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/console/Client.java b/src/main/java/com/programmers/vouchermanagement/console/Client.java index 060b335522..26cc6c7e5b 100644 --- a/src/main/java/com/programmers/vouchermanagement/console/Client.java +++ b/src/main/java/com/programmers/vouchermanagement/console/Client.java @@ -16,6 +16,7 @@ public Client(ConsoleManager consoleManager, VoucherController voucherController } public boolean selectMenu() { + // TODO: menu enumeration + business conflict with ConsoleManager String menu = consoleManager.selectMenu(); if (!validateMenu(menu)) { diff --git a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java index eb5eaffb29..01a595ed38 100644 --- a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java @@ -11,6 +11,7 @@ @Component public class ConsoleManager { + //TODO: consider responsibility of console manager regarding to messages private static final String menuSelectionInstruction = """ ===Voucher Program === Type **exit** to exit the program. @@ -43,6 +44,7 @@ public Voucher instructCreate() { long discountAmount = textIO.newLongInputReader() .read(voucherDiscountAmountDecision); + // TODO: reconsider constructing models (Bean, factory method in DTO) switch (createMenu) { case "fixed" -> { return new FixedAmountVoucher(UUID.randomUUID(), discountAmount); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java index 1c34ec2cc7..904c137126 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java @@ -2,8 +2,6 @@ import java.util.UUID; -import com.programmers.vouchermanagement.voucher.Voucher; - public class FixedAmountVoucher implements Voucher { private final UUID voucherID; private final long discountAmount; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java index ed40c80046..d085e85322 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java @@ -6,9 +6,6 @@ import org.springframework.stereotype.Repository; -import com.programmers.vouchermanagement.voucher.Voucher; -import com.programmers.vouchermanagement.voucher.VoucherRepository; - @Repository public class InMemoryVoucherRepository implements VoucherRepository { private final Map vouchers; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java index 4b2f4a708d..652af2b960 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java @@ -2,8 +2,6 @@ import java.util.UUID; -import com.programmers.vouchermanagement.voucher.Voucher; - public class PercentVoucher implements Voucher { private final UUID voucherID; private final long discountPercent; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index 4d2567676b..b85395c104 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -10,6 +10,7 @@ public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } + //TODO: add DTO public Voucher create(Voucher voucher) { return voucherService.create(voucher); } From ebaec43d58a7286687ad9e153061451f60d03708 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 17 Oct 2023 22:17:07 +0900 Subject: [PATCH 016/383] feat: add findAll feature to VoucherRepository --- .../voucher/InMemoryVoucherRepository.java | 9 ++++++--- .../vouchermanagement/voucher/VoucherRepository.java | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java index d085e85322..88766047e0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java @@ -1,8 +1,6 @@ package com.programmers.vouchermanagement.voucher; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; import org.springframework.stereotype.Repository; @@ -18,4 +16,9 @@ public InMemoryVoucherRepository() { public void save(Voucher voucher) { vouchers.put(voucher.getVoucherId(), voucher); } + + @Override + public List findAll() { + return vouchers.values().stream().toList(); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java index 6522cffe37..be3e9cd00c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java @@ -2,6 +2,10 @@ import com.programmers.vouchermanagement.voucher.Voucher; +import java.util.List; +import java.util.Optional; + public interface VoucherRepository { void save(Voucher voucher); + List findAll(); } From 1b3522b99e13ee6d2c8ecaa42f4c7ffb48b0915f Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 17 Oct 2023 22:53:21 +0900 Subject: [PATCH 017/383] feat: add readAllVouchers to VoucherService --- .../vouchermanagement/voucher/VoucherService.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java index 10f478f3d7..306034852b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java @@ -1,5 +1,8 @@ package com.programmers.vouchermanagement.voucher; +import java.util.List; +import java.util.NoSuchElementException; + import org.springframework.stereotype.Service; @Service @@ -16,9 +19,19 @@ public Voucher create(Voucher voucher) { return voucher; } + public List readAllVouchers() { + List vouchers = voucherRepository.findAll(); + + if (vouchers.isEmpty()) { + throw new NoSuchElementException("There is no voucher registered."); + } + + return vouchers; + } + public void validateDiscount(Voucher voucher) { if (!voucher.validatePositiveDiscount()) { - throw new IllegalArgumentException("input should be a number greater than 0"); + throw new IllegalArgumentException("Input should be a number greater than 0"); } } } From 9124686f52ec69b9c353306df4832a27f34f1d4b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 17 Oct 2023 23:02:13 +0900 Subject: [PATCH 018/383] feat: control readAll request and verify error thrown --- .../programmers/vouchermanagement/console/Client.java | 3 +++ .../vouchermanagement/voucher/VoucherController.java | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/console/Client.java b/src/main/java/com/programmers/vouchermanagement/console/Client.java index 26cc6c7e5b..9c5d2728dc 100644 --- a/src/main/java/com/programmers/vouchermanagement/console/Client.java +++ b/src/main/java/com/programmers/vouchermanagement/console/Client.java @@ -42,6 +42,9 @@ public void executeMenu(String menu) { Voucher voucher = consoleManager.instructCreate(); voucherController.create(voucher); } + case "list" -> { + voucherController.readAllVouchers(); + } } } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index b85395c104..3f9f5ffa7c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -2,6 +2,8 @@ import org.springframework.stereotype.Controller; +import java.util.List; + @Controller public class VoucherController { private final VoucherService voucherService; @@ -14,4 +16,13 @@ public VoucherController(VoucherService voucherService) { public Voucher create(Voucher voucher) { return voucherService.create(voucher); } + + public List readAllVouchers() { + try { + return voucherService.readAllVouchers(); + } catch (RuntimeException e) { + System.out.println(e.getMessage()); + } + return null; + } } From ed409f322fb9a39470ea281642add444b4239255 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 00:45:08 +0900 Subject: [PATCH 019/383] enhance: implement printing the result of list command including a case of no content --- .../programmers/vouchermanagement/console/Client.java | 5 ++++- .../vouchermanagement/console/ConsoleManager.java | 8 +++++++- .../vouchermanagement/voucher/FixedAmountVoucher.java | 10 ++++++++++ .../vouchermanagement/voucher/PercentVoucher.java | 11 +++++++++++ .../vouchermanagement/voucher/Voucher.java | 1 + .../vouchermanagement/voucher/VoucherController.java | 6 +++++- 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/console/Client.java b/src/main/java/com/programmers/vouchermanagement/console/Client.java index 9c5d2728dc..84049314d7 100644 --- a/src/main/java/com/programmers/vouchermanagement/console/Client.java +++ b/src/main/java/com/programmers/vouchermanagement/console/Client.java @@ -1,5 +1,7 @@ package com.programmers.vouchermanagement.console; +import java.util.List; + import org.springframework.stereotype.Component; import com.programmers.vouchermanagement.voucher.Voucher; @@ -43,7 +45,8 @@ public void executeMenu(String menu) { voucherController.create(voucher); } case "list" -> { - voucherController.readAllVouchers(); + List vouchers = voucherController.readAllVouchers(); + consoleManager.printReadAll(vouchers); } } } diff --git a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java index 01a595ed38..4264bfaeba 100644 --- a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.console; +import java.util.List; import java.util.UUID; import org.beryx.textio.TextIO; @@ -13,7 +14,7 @@ public class ConsoleManager { //TODO: consider responsibility of console manager regarding to messages private static final String menuSelectionInstruction = """ - ===Voucher Program === + === Voucher Program === Type **exit** to exit the program. Type **create** to create a new voucher. Type **list** to list all vouchers. @@ -41,6 +42,7 @@ public Voucher instructCreate() { String createMenu = textIO.newStringInputReader() .read(createSelectionInstruction); + //TODO: refactor order of inputs obtaining long discountAmount = textIO.newLongInputReader() .read(voucherDiscountAmountDecision); @@ -59,6 +61,10 @@ public Voucher instructCreate() { } } + public void printReadAll(List vouchers) { + vouchers.forEach(voucher -> textIO.getTextTerminal().println(voucher.toConsoleFormat())); + } + public void printExit() { textIO.getTextTerminal().println("System exits."); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java index 904c137126..6ea6603e06 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java @@ -25,4 +25,14 @@ public long discount(long priceBeforeDiscount) { public boolean validatePositiveDiscount() { return discountAmount > 0; } + + @Override + public String toConsoleFormat() { + return """ + Voucher ID : %s + Voucher Type : Fixed Amount Voucher + Discount Amount : %s + -------------------------""" + .formatted(voucherID, discountAmount); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java index 652af2b960..e92f9bed60 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher; +import java.lang.System; import java.util.UUID; public class PercentVoucher implements Voucher { @@ -25,4 +26,14 @@ public long discount(long priceBeforeDiscount) { public boolean validatePositiveDiscount() { return discountPercent > 0; } + + @Override + public String toConsoleFormat() { + return """ + Voucher ID : %s + Voucher Type : Percent Discount Voucher + Discount Percentage : %s%% + -------------------------""" + .formatted(voucherID, discountPercent); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java index bc076da31b..01489f9374 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java @@ -9,4 +9,5 @@ public interface Voucher { boolean validatePositiveDiscount(); + String toConsoleFormat(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index 3f9f5ffa7c..f43e772b70 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -2,6 +2,7 @@ import org.springframework.stereotype.Controller; +import java.util.Collections; import java.util.List; @Controller @@ -21,8 +22,11 @@ public List readAllVouchers() { try { return voucherService.readAllVouchers(); } catch (RuntimeException e) { + //TODO: add exception handling method externally System.out.println(e.getMessage()); + + //TODO: reconsider return empty list from service + return Collections.emptyList(); } - return null; } } From 55cdc25df979beb2bd2fdf972d81c4c852db6142 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 00:51:19 +0900 Subject: [PATCH 020/383] style: remove unused import statement --- .../programmers/vouchermanagement/voucher/PercentVoucher.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java index e92f9bed60..6338cff7f9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java @@ -1,6 +1,5 @@ package com.programmers.vouchermanagement.voucher; -import java.lang.System; import java.util.UUID; public class PercentVoucher implements Voucher { From e8a6d85b9587f434954357746b2099e88a35deb4 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 18 Oct 2023 01:44:46 +0900 Subject: [PATCH 021/383] feat: add logger to log error level logs from necessary classes --- .../configuration/AppConfig.java | 8 +++++++ .../console/ConsoleManager.java | 22 +++++++++++++------ .../runner/ConsoleAppRunner.java | 2 ++ .../voucher/VoucherController.java | 7 ++++-- src/main/resources/logback.xml | 22 +++++++++++++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 src/main/resources/logback.xml diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java index bbcea60f67..884b051279 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java @@ -1,12 +1,20 @@ package com.programmers.vouchermanagement.configuration; +import com.programmers.vouchermanagement.VoucherManagementApplication; import org.beryx.textio.TextIO; import org.beryx.textio.TextIoFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { + @Bean + public Logger logger() { + return LoggerFactory.getLogger(VoucherManagementApplication.class); + } + @Bean public TextIO textIO() { return TextIoFactory.getTextIO(); diff --git a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java index 4264bfaeba..ed7735978a 100644 --- a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java @@ -1,14 +1,14 @@ package com.programmers.vouchermanagement.console; -import java.util.List; -import java.util.UUID; - -import org.beryx.textio.TextIO; -import org.springframework.stereotype.Component; - import com.programmers.vouchermanagement.voucher.FixedAmountVoucher; import com.programmers.vouchermanagement.voucher.PercentVoucher; import com.programmers.vouchermanagement.voucher.Voucher; +import org.beryx.textio.TextIO; +import org.slf4j.Logger; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.UUID; @Component public class ConsoleManager { @@ -28,11 +28,14 @@ public class ConsoleManager { private static final String voucherDiscountAmountDecision = "Please type the amount/percent of discount of the voucher."; private final TextIO textIO; + private final Logger logger; - public ConsoleManager(TextIO textIO) { + public ConsoleManager(TextIO textIO, Logger logger) { this.textIO = textIO; + this.logger = logger; } + //TODO: validate input type is correct public String selectMenu() { return textIO.newStringInputReader() .read(menuSelectionInstruction); @@ -68,4 +71,9 @@ public void printReadAll(List vouchers) { public void printExit() { textIO.getTextTerminal().println("System exits."); } + + public void printException(RuntimeException e) { + logger.error(e.getMessage()); + System.out.println(e.getMessage()); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java index 1e2e286297..4551610b24 100644 --- a/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java @@ -6,6 +6,8 @@ import com.programmers.vouchermanagement.console.Client; +import java.util.logging.Logger; + @Component public class ConsoleAppRunner implements ApplicationRunner { private final Client client; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index f43e772b70..935839bf62 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher; +import com.programmers.vouchermanagement.console.ConsoleManager; import org.springframework.stereotype.Controller; import java.util.Collections; @@ -7,9 +8,11 @@ @Controller public class VoucherController { + private final ConsoleManager consoleManager; private final VoucherService voucherService; - public VoucherController(VoucherService voucherService) { + public VoucherController(ConsoleManager consoleManager, VoucherService voucherService) { + this.consoleManager = consoleManager; this.voucherService = voucherService; } @@ -23,7 +26,7 @@ public List readAllVouchers() { return voucherService.readAllVouchers(); } catch (RuntimeException e) { //TODO: add exception handling method externally - System.out.println(e.getMessage()); + consoleManager.printException(e); //TODO: reconsider return empty list from service return Collections.emptyList(); diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000000..620ee4d77f --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,22 @@ + + + + + logs/access-%d{yyyy-MM-dd}.log + + + ${FILE_LOG_PATTERN} + + + + + ${FILE_LOG_PATTERN} + + + + + + + + + From 1f200543d87b88505f82d9c41516f07a37f88486 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 12:41:59 +0900 Subject: [PATCH 022/383] feat: implement menu enum class to the consolecomponent package --- .../consolecomponent/Menu.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java new file mode 100644 index 0000000000..95e917fb27 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java @@ -0,0 +1,36 @@ +package com.programmers.vouchermanagement.consolecomponent; + +import java.util.Arrays; +import java.util.Objects; + +public enum Menu { + EXIT("exit", false), + CREATE("create", true), + LIST("list", true), + INCORRECT_MENU("incorrect menu", false) + ; + + private final String menuName; + private final boolean executable; + + Menu(String menuName, boolean executable) { + this.menuName = menuName; + this.executable = executable; + } + + private boolean isMatching(String input) { + return Objects.equals(menuName, input); + } + + //set static to tell that this method does not depend on a particular Menu value + public static Menu findSelectedMenu(String input) { + return Arrays.stream(Menu.values()) + .filter(menu -> menu.isMatching(input)) + .findFirst() + .orElse(INCORRECT_MENU); + } + + public boolean isExecutable() { + return executable; + } +} From 2e8b06559af84d22ec15e41409a16edc308aa5a9 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 12:44:42 +0900 Subject: [PATCH 023/383] enhance: use Menu enum as return value of selectMenu method in ConsoleManager --- .../ConsoleManager.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) rename src/main/java/com/programmers/vouchermanagement/{console => consolecomponent}/ConsoleManager.java (86%) diff --git a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java similarity index 86% rename from src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java rename to src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index ed7735978a..84ab2ae053 100644 --- a/src/main/java/com/programmers/vouchermanagement/console/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -1,4 +1,6 @@ -package com.programmers.vouchermanagement.console; +package com.programmers.vouchermanagement.consolecomponent; + +import static com.programmers.vouchermanagement.consolecomponent.Menu.findSelectedMenu; import com.programmers.vouchermanagement.voucher.FixedAmountVoucher; import com.programmers.vouchermanagement.voucher.PercentVoucher; @@ -36,9 +38,11 @@ public ConsoleManager(TextIO textIO, Logger logger) { } //TODO: validate input type is correct - public String selectMenu() { - return textIO.newStringInputReader() + public Menu selectMenu() { + String input = textIO.newStringInputReader() .read(menuSelectionInstruction); + + return findSelectedMenu(input); } public Voucher instructCreate() { @@ -72,6 +76,11 @@ public void printExit() { textIO.getTextTerminal().println("System exits."); } + public void printIncorrectMenu() { + textIO.getTextTerminal().println("Such input is incorrect."); + printExit(); + } + public void printException(RuntimeException e) { logger.error(e.getMessage()); System.out.println(e.getMessage()); From 304ab23091c220063cc015546e8a07f8d9f6ecfc Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 12:48:23 +0900 Subject: [PATCH 024/383] refactor: resolve TODO, clarifying roles of classes in consolecomponent, and repackage --- .../vouchermanagement/console/Client.java | 53 ----------------- .../consolecomponent/ConsoleAppRunner.java | 26 +++++++++ .../consolecomponent/MenuHandler.java | 57 +++++++++++++++++++ .../runner/ConsoleAppRunner.java | 26 --------- .../voucher/VoucherController.java | 2 +- 5 files changed, 84 insertions(+), 80 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/console/Client.java create mode 100644 src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java create mode 100644 src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java diff --git a/src/main/java/com/programmers/vouchermanagement/console/Client.java b/src/main/java/com/programmers/vouchermanagement/console/Client.java deleted file mode 100644 index 84049314d7..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/console/Client.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.programmers.vouchermanagement.console; - -import java.util.List; - -import org.springframework.stereotype.Component; - -import com.programmers.vouchermanagement.voucher.Voucher; -import com.programmers.vouchermanagement.voucher.VoucherController; - -@Component -public class Client { - private final ConsoleManager consoleManager; - private final VoucherController voucherController; - - public Client(ConsoleManager consoleManager, VoucherController voucherController) { - this.consoleManager = consoleManager; - this.voucherController = voucherController; - } - - public boolean selectMenu() { - // TODO: menu enumeration + business conflict with ConsoleManager - String menu = consoleManager.selectMenu(); - - if (!validateMenu(menu)) { - consoleManager.printExit(); - return false; - } - - executeMenu(menu); - return true; - } - - private boolean validateMenu(String menu) { - if (menu.equals("exit")) { - return false; - } - - return true; - } - - public void executeMenu(String menu) { - switch (menu) { - case "create" -> { - Voucher voucher = consoleManager.instructCreate(); - voucherController.create(voucher); - } - case "list" -> { - List vouchers = voucherController.readAllVouchers(); - consoleManager.printReadAll(vouchers); - } - } - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java new file mode 100644 index 0000000000..f9671577b9 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java @@ -0,0 +1,26 @@ +package com.programmers.vouchermanagement.consolecomponent; + +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import com.programmers.vouchermanagement.consolecomponent.MenuHandler; + +@Component +public class ConsoleAppRunner implements ApplicationRunner { + private final MenuHandler menuHandler; + + public ConsoleAppRunner(MenuHandler menuHandler) { + this.menuHandler = menuHandler; + } + + @Override + public void run(ApplicationArguments args) { + try { + menuHandler.handleMenu(); + run(args); + } catch (RuntimeException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java new file mode 100644 index 0000000000..2458208728 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -0,0 +1,57 @@ +package com.programmers.vouchermanagement.consolecomponent; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.programmers.vouchermanagement.voucher.Voucher; +import com.programmers.vouchermanagement.voucher.VoucherController; + +@Component +public class MenuHandler { + private final ConsoleManager consoleManager; + private final VoucherController voucherController; + + public MenuHandler(ConsoleManager consoleManager, VoucherController voucherController) { + this.consoleManager = consoleManager; + this.voucherController = voucherController; + } + + // Options.. + // ConsoleAppRunner (recursive run) --> MenuHandler --> Menu + // ConsoleAppRunner --> Menu <-- MenuHandler + // ConsoleAppRunner --> Menu + + public void handleMenu() { + Menu menu = selectMenu(); + executeMenu(menu); + validateMenu(menu); + } + + private Menu selectMenu() { + return consoleManager.selectMenu(); + } + + private boolean validateMenu(Menu menu) { + if (!menu.isExecutable()) { + throw new RuntimeException("Recursive.."); + } + + return true; + } + + private void executeMenu(Menu menu) { + switch (menu) { + case EXIT -> consoleManager.printExit(); + case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); + case CREATE -> { + Voucher voucher = consoleManager.instructCreate(); + voucherController.create(voucher); + } + case LIST -> { + List vouchers = voucherController.readAllVouchers(); + consoleManager.printReadAll(vouchers); + } + } + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java deleted file mode 100644 index 4551610b24..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/runner/ConsoleAppRunner.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.programmers.vouchermanagement.runner; - -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.stereotype.Component; - -import com.programmers.vouchermanagement.console.Client; - -import java.util.logging.Logger; - -@Component -public class ConsoleAppRunner implements ApplicationRunner { - private final Client client; - - public ConsoleAppRunner(Client client) { - this.client = client; - } - - @Override - public void run(ApplicationArguments args) { - boolean isRunning = true; - while (isRunning) { - isRunning = client.selectMenu(); - } - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index 935839bf62..97e58d8a18 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -1,6 +1,6 @@ package com.programmers.vouchermanagement.voucher; -import com.programmers.vouchermanagement.console.ConsoleManager; +import com.programmers.vouchermanagement.consolecomponent.ConsoleManager; import org.springframework.stereotype.Controller; import java.util.Collections; From c5ade6b7c9d01c9b6207c0b9554e978b76c2214b Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 13:09:50 +0900 Subject: [PATCH 025/383] enhance: clarify inexecutable exception message and leave corresponding log --- .../consolecomponent/ConsoleAppRunner.java | 9 +++++---- .../vouchermanagement/consolecomponent/MenuHandler.java | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java index f9671577b9..66ba3acf7d 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java @@ -1,17 +1,18 @@ package com.programmers.vouchermanagement.consolecomponent; +import org.slf4j.Logger; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; -import com.programmers.vouchermanagement.consolecomponent.MenuHandler; - @Component public class ConsoleAppRunner implements ApplicationRunner { private final MenuHandler menuHandler; + private final Logger logger; - public ConsoleAppRunner(MenuHandler menuHandler) { + public ConsoleAppRunner(MenuHandler menuHandler, Logger logger) { this.menuHandler = menuHandler; + this.logger = logger; } @Override @@ -20,7 +21,7 @@ public void run(ApplicationArguments args) { menuHandler.handleMenu(); run(args); } catch (RuntimeException e) { - System.out.println(e.getMessage()); + logger.error(e.getMessage()); } } } diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index 2458208728..df84a8b1ad 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -34,7 +34,7 @@ private Menu selectMenu() { private boolean validateMenu(Menu menu) { if (!menu.isExecutable()) { - throw new RuntimeException("Recursive.."); + throw new RuntimeException("This menu is not executable."); } return true; From 89fa17284a5275ef24624d18efae97a3d3757350 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 13:10:26 +0900 Subject: [PATCH 026/383] comment: leave TODO --- .../vouchermanagement/consolecomponent/ConsoleManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index 84ab2ae053..c5bb07026e 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -81,8 +81,9 @@ public void printIncorrectMenu() { printExit(); } + //TODO: add exception handling method externally public void printException(RuntimeException e) { logger.error(e.getMessage()); - System.out.println(e.getMessage()); + textIO.getTextTerminal().println(e.getMessage()); } } From 4ccda5317e4ac14aae40380163b443b61c025c93 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 18 Oct 2023 13:38:20 +0900 Subject: [PATCH 027/383] refactor: store messages in constant.message --- .../consolecomponent/ConsoleManager.java | 35 ++++++------------- .../consolecomponent/MenuHandler.java | 11 +++--- .../constant/message/ExceptionMessage.java | 12 +++++++ .../constant/message/Instruction.java | 18 ++++++++++ .../constant/message/ResultMessage.java | 8 +++++ .../voucher/VoucherService.java | 9 +++-- 6 files changed, 61 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java create mode 100644 src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java create mode 100644 src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index c5bb07026e..7d06cbbb75 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -1,7 +1,5 @@ package com.programmers.vouchermanagement.consolecomponent; -import static com.programmers.vouchermanagement.consolecomponent.Menu.findSelectedMenu; - import com.programmers.vouchermanagement.voucher.FixedAmountVoucher; import com.programmers.vouchermanagement.voucher.PercentVoucher; import com.programmers.vouchermanagement.voucher.Voucher; @@ -12,23 +10,13 @@ import java.util.List; import java.util.UUID; +import static com.programmers.vouchermanagement.consolecomponent.Menu.findSelectedMenu; +import static com.programmers.vouchermanagement.constant.message.ResultMessage.*; +import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INVALID_VOUCHER_TYPE_MESSAGE; +import static com.programmers.vouchermanagement.constant.message.Instruction.*; + @Component public class ConsoleManager { - //TODO: consider responsibility of console manager regarding to messages - private static final String menuSelectionInstruction = """ - === Voucher Program === - Type **exit** to exit the program. - Type **create** to create a new voucher. - Type **list** to list all vouchers. - """; - private static final String createSelectionInstruction = """ - Please select the type of voucher to create. - Type **fixed** to create a fixed amount voucher. - Type **percent** to create a percent discount voucher. - """; - - private static final String voucherDiscountAmountDecision = "Please type the amount/percent of discount of the voucher."; - private final TextIO textIO; private final Logger logger; @@ -40,18 +28,18 @@ public ConsoleManager(TextIO textIO, Logger logger) { //TODO: validate input type is correct public Menu selectMenu() { String input = textIO.newStringInputReader() - .read(menuSelectionInstruction); + .read(MENU_SELECTION_INSTRUCTION); return findSelectedMenu(input); } public Voucher instructCreate() { String createMenu = textIO.newStringInputReader() - .read(createSelectionInstruction); + .read(CREATE_SELECTION_INSTRUCTION); //TODO: refactor order of inputs obtaining long discountAmount = textIO.newLongInputReader() - .read(voucherDiscountAmountDecision); + .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); // TODO: reconsider constructing models (Bean, factory method in DTO) switch (createMenu) { @@ -63,8 +51,7 @@ public Voucher instructCreate() { return new PercentVoucher(UUID.randomUUID(), discountAmount); } - default -> - throw new IllegalArgumentException("Voucher type should be either fixed amount or percent discount voucher"); + default -> throw new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE); } } @@ -73,11 +60,11 @@ public void printReadAll(List vouchers) { } public void printExit() { - textIO.getTextTerminal().println("System exits."); + textIO.getTextTerminal().println(EXIT_MESSAGE); } public void printIncorrectMenu() { - textIO.getTextTerminal().println("Such input is incorrect."); + textIO.getTextTerminal().println(INCORRECT_INPUT_MESSAGE); printExit(); } diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index df84a8b1ad..180464b911 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -1,11 +1,12 @@ package com.programmers.vouchermanagement.consolecomponent; -import java.util.List; - -import org.springframework.stereotype.Component; - import com.programmers.vouchermanagement.voucher.Voucher; import com.programmers.vouchermanagement.voucher.VoucherController; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INEXECUTABLE_MESSAGE; @Component public class MenuHandler { @@ -34,7 +35,7 @@ private Menu selectMenu() { private boolean validateMenu(Menu menu) { if (!menu.isExecutable()) { - throw new RuntimeException("This menu is not executable."); + throw new RuntimeException(INEXECUTABLE_MESSAGE); } return true; diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java b/src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java new file mode 100644 index 0000000000..7b34937083 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java @@ -0,0 +1,12 @@ +package com.programmers.vouchermanagement.constant.message; + +public class ExceptionMessage { + public static final String INVALID_VOUCHER_TYPE_MESSAGE = + "Voucher type should be either fixed amount or percent discount voucher"; + public static final String INEXECUTABLE_MESSAGE = + "This menu is not executable."; + public static final String VOUCHER_NOT_FOUND_MESSAGE = + "There is no voucher registered."; + public static final String INVALID_DISCOUNT_INPUT_MESSAGE = + "Input should be a number greater than 0"; +} diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java b/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java new file mode 100644 index 0000000000..46534fefb7 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java @@ -0,0 +1,18 @@ +package com.programmers.vouchermanagement.constant.message; + +public class Instruction { + public static final String MENU_SELECTION_INSTRUCTION = """ + === Voucher Program === + Type **exit** to exit the program. + Type **create** to create a new voucher. + Type **list** to list all vouchers. + """; + public static final String CREATE_SELECTION_INSTRUCTION = """ + Please select the type of voucher to create. + Type **fixed** to create a fixed amount voucher. + Type **percent** to create a percent discount voucher. + """; + public static final String VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION = + "Please type the amount/percent of discount of the voucher."; + +} diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java b/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java new file mode 100644 index 0000000000..27ca985631 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java @@ -0,0 +1,8 @@ +package com.programmers.vouchermanagement.constant.message; + +public class ResultMessage { + public static final String EXIT_MESSAGE = + "System exits."; + public static final String INCORRECT_INPUT_MESSAGE = + "Such input is incorrect."; +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java index 306034852b..42bee8bfa3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java @@ -1,9 +1,12 @@ package com.programmers.vouchermanagement.voucher; +import org.springframework.stereotype.Service; + import java.util.List; import java.util.NoSuchElementException; -import org.springframework.stereotype.Service; +import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INVALID_DISCOUNT_INPUT_MESSAGE; +import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.VOUCHER_NOT_FOUND_MESSAGE; @Service public class VoucherService { @@ -23,7 +26,7 @@ public List readAllVouchers() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { - throw new NoSuchElementException("There is no voucher registered."); + throw new NoSuchElementException(VOUCHER_NOT_FOUND_MESSAGE); } return vouchers; @@ -31,7 +34,7 @@ public List readAllVouchers() { public void validateDiscount(Voucher voucher) { if (!voucher.validatePositiveDiscount()) { - throw new IllegalArgumentException("Input should be a number greater than 0"); + throw new IllegalArgumentException(INVALID_DISCOUNT_INPUT_MESSAGE); } } } From 8f0f590c00c5df78150c100f3448d9225d434c5b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 18 Oct 2023 13:47:43 +0900 Subject: [PATCH 028/383] enhance: add voucher creation success message printing --- .../vouchermanagement/consolecomponent/ConsoleManager.java | 6 +++++- .../vouchermanagement/consolecomponent/MenuHandler.java | 3 ++- .../vouchermanagement/constant/message/ResultMessage.java | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index 7d06cbbb75..f2199526bc 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -11,9 +11,9 @@ import java.util.UUID; import static com.programmers.vouchermanagement.consolecomponent.Menu.findSelectedMenu; -import static com.programmers.vouchermanagement.constant.message.ResultMessage.*; import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INVALID_VOUCHER_TYPE_MESSAGE; import static com.programmers.vouchermanagement.constant.message.Instruction.*; +import static com.programmers.vouchermanagement.constant.message.ResultMessage.*; @Component public class ConsoleManager { @@ -55,6 +55,10 @@ public Voucher instructCreate() { } } + public void printCreateResult(Voucher voucher) { + textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucher.getVoucherId())); + } + public void printReadAll(List vouchers) { vouchers.forEach(voucher -> textIO.getTextTerminal().println(voucher.toConsoleFormat())); } diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index 180464b911..0d888e24d7 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -47,7 +47,8 @@ private void executeMenu(Menu menu) { case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { Voucher voucher = consoleManager.instructCreate(); - voucherController.create(voucher); + voucher = voucherController.create(voucher); + consoleManager.printCreateResult(voucher); } case LIST -> { List vouchers = voucherController.readAllVouchers(); diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java b/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java index 27ca985631..ca3153f3f8 100644 --- a/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java +++ b/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java @@ -5,4 +5,6 @@ public class ResultMessage { "System exits."; public static final String INCORRECT_INPUT_MESSAGE = "Such input is incorrect."; + public static final String CREATE_SUCCESS_MESSAGE = + "The voucher(ID: %s) is successfully created."; } From d9367826472d00e6200914287b47baec663d0595 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 14:18:34 +0900 Subject: [PATCH 029/383] refactor: continue running when incorrect menu is selected --- .../consolecomponent/ConsoleManager.java | 5 ++--- .../consolecomponent/Menu.java | 17 +++++++---------- .../consolecomponent/MenuHandler.java | 2 +- .../constant/message/ResultMessage.java | 6 ++++-- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index f2199526bc..ea193fe3bf 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -3,6 +3,7 @@ import com.programmers.vouchermanagement.voucher.FixedAmountVoucher; import com.programmers.vouchermanagement.voucher.PercentVoucher; import com.programmers.vouchermanagement.voucher.Voucher; + import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.springframework.stereotype.Component; @@ -25,7 +26,6 @@ public ConsoleManager(TextIO textIO, Logger logger) { this.logger = logger; } - //TODO: validate input type is correct public Menu selectMenu() { String input = textIO.newStringInputReader() .read(MENU_SELECTION_INSTRUCTION); @@ -37,7 +37,7 @@ public Voucher instructCreate() { String createMenu = textIO.newStringInputReader() .read(CREATE_SELECTION_INSTRUCTION); - //TODO: refactor order of inputs obtaining + //TODO: refactor order of inputs obtaining + error handling long discountAmount = textIO.newLongInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); @@ -69,7 +69,6 @@ public void printExit() { public void printIncorrectMenu() { textIO.getTextTerminal().println(INCORRECT_INPUT_MESSAGE); - printExit(); } //TODO: add exception handling method externally diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java index 95e917fb27..fd522430fe 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java @@ -4,18 +4,15 @@ import java.util.Objects; public enum Menu { - EXIT("exit", false), - CREATE("create", true), - LIST("list", true), - INCORRECT_MENU("incorrect menu", false) - ; + EXIT("exit"), + CREATE("create"), + LIST("list"), + INCORRECT_MENU("incorrect menu"); private final String menuName; - private final boolean executable; - Menu(String menuName, boolean executable) { + Menu(String menuName) { this.menuName = menuName; - this.executable = executable; } private boolean isMatching(String input) { @@ -30,7 +27,7 @@ public static Menu findSelectedMenu(String input) { .orElse(INCORRECT_MENU); } - public boolean isExecutable() { - return executable; + public boolean isExit() { + return this == Menu.EXIT; } } diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index 0d888e24d7..da372b893a 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -34,7 +34,7 @@ private Menu selectMenu() { } private boolean validateMenu(Menu menu) { - if (!menu.isExecutable()) { + if (menu.isExit()) { throw new RuntimeException(INEXECUTABLE_MESSAGE); } diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java b/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java index ca3153f3f8..98ae40bb58 100644 --- a/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java +++ b/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java @@ -3,8 +3,10 @@ public class ResultMessage { public static final String EXIT_MESSAGE = "System exits."; - public static final String INCORRECT_INPUT_MESSAGE = - "Such input is incorrect."; + public static final String INCORRECT_INPUT_MESSAGE = """ + Such input is incorrect. + Please input a correct menu carefully. + """; public static final String CREATE_SUCCESS_MESSAGE = "The voucher(ID: %s) is successfully created."; } From edc0e0b5b6ccf7f6a6c70a2086fef172d98ae913 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 18 Oct 2023 14:18:50 +0900 Subject: [PATCH 030/383] comment: add TODO --- .../vouchermanagement/constant/message/Instruction.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java b/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java index 46534fefb7..da16611dec 100644 --- a/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java +++ b/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java @@ -12,7 +12,9 @@ public class Instruction { Type **fixed** to create a fixed amount voucher. Type **percent** to create a percent discount voucher. """; + + //TODO: consider line separator as new line command may differ for every OS public static final String VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION = - "Please type the amount/percent of discount of the voucher."; + "Please type the amount/percent of discount of the voucher.\n"; } From c5bbedcba254d3718727be4623e266ca87bb81e3 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 10:10:41 +0900 Subject: [PATCH 031/383] chore: fix logback xml temporarily --- .../resources/{logback.xml => logback-spring.xml} | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) rename src/main/resources/{logback.xml => logback-spring.xml} (72%) diff --git a/src/main/resources/logback.xml b/src/main/resources/logback-spring.xml similarity index 72% rename from src/main/resources/logback.xml rename to src/main/resources/logback-spring.xml index 620ee4d77f..ff9931be2b 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback-spring.xml @@ -1,5 +1,9 @@ + + + + logs/access-%d{yyyy-MM-dd}.log @@ -8,15 +12,8 @@ ${FILE_LOG_PATTERN} - - - ${FILE_LOG_PATTERN} - - + - - - From 672067c4ccf2feb6d5ed122cc7f5c73c426c4e3a Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 11:08:40 +0900 Subject: [PATCH 032/383] fix: raise an exception only for incorrect menu selected --- .../consolecomponent/ConsoleAppRunner.java | 12 +++++++----- .../vouchermanagement/consolecomponent/Menu.java | 4 ++++ .../consolecomponent/MenuHandler.java | 16 ++++++++++------ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java index 66ba3acf7d..7fa81a15a7 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java @@ -17,11 +17,13 @@ public ConsoleAppRunner(MenuHandler menuHandler, Logger logger) { @Override public void run(ApplicationArguments args) { - try { - menuHandler.handleMenu(); - run(args); - } catch (RuntimeException e) { - logger.error(e.getMessage()); + boolean isRunning = true; + while (isRunning) { + try { + isRunning = menuHandler.handleMenu(); + } catch (RuntimeException e) { + logger.error(e.getMessage()); + } } } } diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java index fd522430fe..4e05716656 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java @@ -30,4 +30,8 @@ public static Menu findSelectedMenu(String input) { public boolean isExit() { return this == Menu.EXIT; } + + public boolean isIncorrect() { + return this == INCORRECT_MENU; + } } diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index da372b893a..2b017b55ee 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -1,13 +1,13 @@ package com.programmers.vouchermanagement.consolecomponent; +import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INEXECUTABLE_MESSAGE; + import com.programmers.vouchermanagement.voucher.Voucher; import com.programmers.vouchermanagement.voucher.VoucherController; import org.springframework.stereotype.Component; import java.util.List; -import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INEXECUTABLE_MESSAGE; - @Component public class MenuHandler { private final ConsoleManager consoleManager; @@ -23,19 +23,23 @@ public MenuHandler(ConsoleManager consoleManager, VoucherController voucherContr // ConsoleAppRunner --> Menu <-- MenuHandler // ConsoleAppRunner --> Menu - public void handleMenu() { + public boolean handleMenu() { Menu menu = selectMenu(); executeMenu(menu); - validateMenu(menu); + return isValidMenu(menu); } private Menu selectMenu() { return consoleManager.selectMenu(); } - private boolean validateMenu(Menu menu) { + private boolean isValidMenu(Menu menu) { if (menu.isExit()) { - throw new RuntimeException(INEXECUTABLE_MESSAGE); + return false; + } + + if (menu.isIncorrect()) { + throw new IllegalArgumentException(INEXECUTABLE_MESSAGE); } return true; From 835421ca35601a99ae96932baf0e9db0f368eb66 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 11:18:44 +0900 Subject: [PATCH 033/383] refactor: move messages to where they are used and set private --- .../consolecomponent/ConsoleManager.java | 33 +++++++++++++++++-- .../consolecomponent/MenuHandler.java | 9 +++-- .../constant/message/ExceptionMessage.java | 12 ------- .../constant/message/Instruction.java | 20 ----------- .../constant/message/ResultMessage.java | 12 ------- .../voucher/VoucherService.java | 10 ++++-- 6 files changed, 43 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index ea193fe3bf..5f17ab7b99 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -12,12 +12,39 @@ import java.util.UUID; import static com.programmers.vouchermanagement.consolecomponent.Menu.findSelectedMenu; -import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INVALID_VOUCHER_TYPE_MESSAGE; -import static com.programmers.vouchermanagement.constant.message.Instruction.*; -import static com.programmers.vouchermanagement.constant.message.ResultMessage.*; +import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; @Component public class ConsoleManager { + //messages + private static final String MENU_SELECTION_INSTRUCTION = """ + === Voucher Program === + Type **exit** to exit the program. + Type **create** to create a new voucher. + Type **list** to list all vouchers. + """; + private static final String CREATE_SELECTION_INSTRUCTION = """ + Please select the type of voucher to create. + Type **fixed** to create a fixed amount voucher. + Type **percent** to create a percent discount voucher. + """; + + //TODO: consider line separator as new line command may differ for every OS + private static final String VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION = + "Please type the amount/percent of discount of the voucher.%s".formatted(LINE_SEPARATOR); + private static final String INVALID_VOUCHER_TYPE_MESSAGE = + "Voucher type should be either fixed amount or percent discount voucher."; + private static final String EXIT_MESSAGE = + "System exits."; + private static final String CREATE_SUCCESS_MESSAGE = + "The voucher(ID: %s) is successfully created."; + private static final String INCORRECT_INPUT_MESSAGE = + """ + Such input is incorrect. + Please input a correct command carefully. + """; + //--- + private final TextIO textIO; private final Logger logger; diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index 2b017b55ee..7a4e44928f 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -1,7 +1,5 @@ package com.programmers.vouchermanagement.consolecomponent; -import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INEXECUTABLE_MESSAGE; - import com.programmers.vouchermanagement.voucher.Voucher; import com.programmers.vouchermanagement.voucher.VoucherController; import org.springframework.stereotype.Component; @@ -10,6 +8,11 @@ @Component public class MenuHandler { + //messages + private static final String INCORRECT_MESSAGE = + "This menu is not executable."; + //--- + private final ConsoleManager consoleManager; private final VoucherController voucherController; @@ -39,7 +42,7 @@ private boolean isValidMenu(Menu menu) { } if (menu.isIncorrect()) { - throw new IllegalArgumentException(INEXECUTABLE_MESSAGE); + throw new IllegalArgumentException(INCORRECT_MESSAGE); } return true; diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java b/src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java deleted file mode 100644 index 7b34937083..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/constant/message/ExceptionMessage.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.programmers.vouchermanagement.constant.message; - -public class ExceptionMessage { - public static final String INVALID_VOUCHER_TYPE_MESSAGE = - "Voucher type should be either fixed amount or percent discount voucher"; - public static final String INEXECUTABLE_MESSAGE = - "This menu is not executable."; - public static final String VOUCHER_NOT_FOUND_MESSAGE = - "There is no voucher registered."; - public static final String INVALID_DISCOUNT_INPUT_MESSAGE = - "Input should be a number greater than 0"; -} diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java b/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java deleted file mode 100644 index da16611dec..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/constant/message/Instruction.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.programmers.vouchermanagement.constant.message; - -public class Instruction { - public static final String MENU_SELECTION_INSTRUCTION = """ - === Voucher Program === - Type **exit** to exit the program. - Type **create** to create a new voucher. - Type **list** to list all vouchers. - """; - public static final String CREATE_SELECTION_INSTRUCTION = """ - Please select the type of voucher to create. - Type **fixed** to create a fixed amount voucher. - Type **percent** to create a percent discount voucher. - """; - - //TODO: consider line separator as new line command may differ for every OS - public static final String VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION = - "Please type the amount/percent of discount of the voucher.\n"; - -} diff --git a/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java b/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java deleted file mode 100644 index 98ae40bb58..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/constant/message/ResultMessage.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.programmers.vouchermanagement.constant.message; - -public class ResultMessage { - public static final String EXIT_MESSAGE = - "System exits."; - public static final String INCORRECT_INPUT_MESSAGE = """ - Such input is incorrect. - Please input a correct menu carefully. - """; - public static final String CREATE_SUCCESS_MESSAGE = - "The voucher(ID: %s) is successfully created."; -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java index 42bee8bfa3..a2396b0243 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java @@ -5,11 +5,15 @@ import java.util.List; import java.util.NoSuchElementException; -import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.INVALID_DISCOUNT_INPUT_MESSAGE; -import static com.programmers.vouchermanagement.constant.message.ExceptionMessage.VOUCHER_NOT_FOUND_MESSAGE; - @Service public class VoucherService { + //messages + private static final String VOUCHER_NOT_FOUND_MESSAGE = + "There is no voucher registered."; + private static final String INVALID_DISCOUNT_INPUT_MESSAGE = + "Input should be a number greater than 0"; + //--- + private final VoucherRepository voucherRepository; public VoucherService(VoucherRepository voucherRepository) { From 5cb5a3f78062614c5033442c5a31264ea9ee5f89 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 11:21:21 +0900 Subject: [PATCH 034/383] feat: add line separator as a constant --- .../com/programmers/vouchermanagement/constant/Constant.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/constant/Constant.java diff --git a/src/main/java/com/programmers/vouchermanagement/constant/Constant.java b/src/main/java/com/programmers/vouchermanagement/constant/Constant.java new file mode 100644 index 0000000000..2ffa5f8c04 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/constant/Constant.java @@ -0,0 +1,5 @@ +package com.programmers.vouchermanagement.constant; + +public class Constant { + public static final String LINE_SEPARATOR = System.lineSeparator(); +} From 61a0559ca6752ef04eca8e2571347aa6fbd5b3bd Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 12:15:49 +0900 Subject: [PATCH 035/383] feat: implement Customer domain class --- .../vouchermanagement/customer/Customer.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/Customer.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/Customer.java new file mode 100644 index 0000000000..c2f098c704 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/Customer.java @@ -0,0 +1,24 @@ +package com.programmers.vouchermanagement.customer; + +import java.util.UUID; + +public class Customer { + private final UUID customerId; + private final String name; + private final boolean isBlack; + + public Customer(UUID customerId, String name) { + this(customerId, name, false); + } + + public Customer(UUID customerId, String name, boolean isBlack) { + this.customerId = customerId; + this.name = name; + this.isBlack = isBlack; + } + + public UUID getCustomerId() { + return customerId; + } +} + From ba9fa32e8e2bab8418bd2513d6ebd3cb09bf0d8c Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 12:16:51 +0900 Subject: [PATCH 036/383] feat: implement load blacklist in FileCustomerRepository from blacklist.csv in resources --- .../customer/CustomerRepository.java | 7 +++ .../customer/FileCustomerRepository.java | 49 +++++++++++++++++++ src/main/resources/blacklist.csv | 3 ++ 3 files changed, 59 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java create mode 100644 src/main/resources/blacklist.csv diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java new file mode 100644 index 0000000000..3a65ff4cf7 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java @@ -0,0 +1,7 @@ +package com.programmers.vouchermanagement.customer; + +import java.util.List; + +public interface CustomerRepository { + List findAll(); +} diff --git a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java new file mode 100644 index 0000000000..4acb0479c5 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java @@ -0,0 +1,49 @@ +package com.programmers.vouchermanagement.customer; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class FileCustomerRepository implements CustomerRepository { + private static final String BLACKLIST_FILE_PATH = "src/main/resources/blacklist.csv"; + private final Map customers; + + public FileCustomerRepository() { + this.customers = new HashMap<>(); + loadBlacklist(); + } + + @Override + public List findAll() { + return null; + } + + private void loadBlacklist() { + List blacklist = new ArrayList<>(); + + try (BufferedReader br = new BufferedReader(new FileReader(BLACKLIST_FILE_PATH))) { + br.readLine(); // skip the first line + String str; + while ((str = br.readLine()) != null) { + String[] line = str.split(", "); + + UUID blackCustomerId = UUID.fromString(line[0]); + String name = line[1]; + + Customer blackCustomer = new Customer(blackCustomerId, name, true); + + blacklist.add(blackCustomer); + } + } catch (IOException e) { + e.printStackTrace(); + //TODO: add logger + } + + blacklist.forEach(blackCustomer -> customers.put(blackCustomer.getCustomerId(), blackCustomer)); + } +} diff --git a/src/main/resources/blacklist.csv b/src/main/resources/blacklist.csv new file mode 100644 index 0000000000..e2efc7ccaa --- /dev/null +++ b/src/main/resources/blacklist.csv @@ -0,0 +1,3 @@ +id,name +e8d88c24-668c-4b65-a658-44303bfbb805, 송인재 +9b46f523-03d4-41b2-a68e-0666f21c6f7d, 익명 From 72e3efeb7edcf473e9dd3cbd4233ea9bcd0292f1 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 12:39:42 +0900 Subject: [PATCH 037/383] feat: add findAll to FileCustomerRepository --- .../vouchermanagement/customer/FileCustomerRepository.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java index 4acb0479c5..14f5a77c88 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java @@ -20,7 +20,9 @@ public FileCustomerRepository() { @Override public List findAll() { - return null; + return customers.values() + .stream() + .toList(); } private void loadBlacklist() { From 757da648c2884a40bcde68d076408c5f1349cafa Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 12:44:19 +0900 Subject: [PATCH 038/383] feat: add isBlack to Customer --- .../com/programmers/vouchermanagement/customer/Customer.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/Customer.java index c2f098c704..b7634fbadb 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/Customer.java @@ -20,5 +20,9 @@ public Customer(UUID customerId, String name, boolean isBlack) { public UUID getCustomerId() { return customerId; } + + public boolean isBlack() { + return isBlack; + } } From ecbf535a636e5bda2a77fadf3637b7218c2c203a Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 12:44:51 +0900 Subject: [PATCH 039/383] refactor: replace findAll to findBlackCustomer and filter black customers --- .../vouchermanagement/customer/CustomerRepository.java | 2 +- .../vouchermanagement/customer/FileCustomerRepository.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java index 3a65ff4cf7..5029189b3b 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java @@ -3,5 +3,5 @@ import java.util.List; public interface CustomerRepository { - List findAll(); + List findBlackCustomers(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java index 14f5a77c88..0cd635147a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java @@ -19,9 +19,10 @@ public FileCustomerRepository() { } @Override - public List findAll() { + public List findBlackCustomers() { return customers.values() .stream() + .filter(Customer::isBlack) .toList(); } From a6525a7f063b550c0ca3f05ce0d659a630252b61 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 12:48:57 +0900 Subject: [PATCH 040/383] feat: add readBlacklist to CustomerService --- .../customer/CustomerService.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java new file mode 100644 index 0000000000..a6cf4bf7ab --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java @@ -0,0 +1,17 @@ +package com.programmers.vouchermanagement.customer; + +import java.util.List; + +public class CustomerService { + private final CustomerRepository customerRepository; + + public CustomerService(CustomerRepository customerRepository) { + this.customerRepository = customerRepository; + } + + public List readBlacklist() { + List blacklist = customerRepository.findBlackCustomers(); + //TODO: logger to inform no black customers exists + return blacklist; + } +} From e2abde12a93f2e0ef73be2b5ea311f91d2134bb3 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 13:04:27 +0900 Subject: [PATCH 041/383] feat: add readBlacklist to CustomerController --- .../customer/CustomerController.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java new file mode 100644 index 0000000000..fa01285fb3 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java @@ -0,0 +1,15 @@ +package com.programmers.vouchermanagement.customer; + +import java.util.List; + +public class CustomerController { + private final CustomerService customerService; + + public CustomerController(CustomerService customerService) { + this.customerService = customerService; + } + + public List readBlacklist() { + return customerService.readBlacklist(); + } +} From 65078b67ccba95653be1e3c40bf3e1222fb71f2a Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 13:05:14 +0900 Subject: [PATCH 042/383] enhance: add annotation to scan components regarding customer --- .../vouchermanagement/customer/CustomerController.java | 3 +++ .../vouchermanagement/customer/CustomerService.java | 8 ++++++++ .../customer/FileCustomerRepository.java | 3 +++ 3 files changed, 14 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java index fa01285fb3..43796da2f7 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java @@ -2,6 +2,9 @@ import java.util.List; +import org.springframework.stereotype.Controller; + +@Controller public class CustomerController { private final CustomerService customerService; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java index a6cf4bf7ab..b50a558daf 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java @@ -1,7 +1,11 @@ package com.programmers.vouchermanagement.customer; import java.util.List; +import java.util.NoSuchElementException; +import org.springframework.stereotype.Service; + +@Service public class CustomerService { private final CustomerRepository customerRepository; @@ -12,6 +16,10 @@ public CustomerService(CustomerRepository customerRepository) { public List readBlacklist() { List blacklist = customerRepository.findBlackCustomers(); //TODO: logger to inform no black customers exists + if (blacklist.isEmpty()) { + throw new NoSuchElementException("no blacklist"); + } + return blacklist; } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java index 0cd635147a..9cbf974207 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java @@ -9,6 +9,9 @@ import java.util.Map; import java.util.UUID; +import org.springframework.stereotype.Repository; + +@Repository public class FileCustomerRepository implements CustomerRepository { private static final String BLACKLIST_FILE_PATH = "src/main/resources/blacklist.csv"; private final Map customers; From 477830b11e63e1c4f7176a4f38bad576f909cb4e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 13:47:42 +0900 Subject: [PATCH 043/383] feat: implement CreateVoucherRequestDTO --- .../vouchermanagement/voucher/CreateVoucherRequestDTO.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java new file mode 100644 index 0000000000..ab61908ab2 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java @@ -0,0 +1,6 @@ +package com.programmers.vouchermanagement.voucher; + +import com.programmers.vouchermanagement.consolecomponent.CreateVoucherMenu; + +public record CreateVoucherRequestDTO(CreateVoucherMenu createVoucherMenu, long discountAmount) { +} From 97e564021b243d918b05b54da61bdc1fc46aed89 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 13:48:03 +0900 Subject: [PATCH 044/383] feat: implement CreateVoucherMenu --- .../consolecomponent/CreateVoucherMenu.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/consolecomponent/CreateVoucherMenu.java diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/CreateVoucherMenu.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/CreateVoucherMenu.java new file mode 100644 index 0000000000..67f48a13a5 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/CreateVoucherMenu.java @@ -0,0 +1,28 @@ +package com.programmers.vouchermanagement.consolecomponent; + +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; + +public enum CreateVoucherMenu { + FIXED("fixed"), + PERCENT("percent"); + + private final String menuName; + + CreateVoucherMenu(String menuName) { + this.menuName = menuName; + } + + //set static to tell that this method does not depend on a particular Menu value + public static Optional findCreateMenu(String input) { + return Arrays.stream(CreateVoucherMenu.values()) + .filter(menu -> menu.isMatching(input)) + .findFirst(); + } + + private boolean isMatching(String input) { + return Objects.equals(menuName, input); + } + +} From 1458fac937b2166cd6434a3df299cd981eeb0c32 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 13:49:15 +0900 Subject: [PATCH 045/383] enhance: apply DTO instead of voucher in parameter and convert --- .../voucher/VoucherService.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java index a2396b0243..8fcbda93a8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.NoSuchElementException; +import java.util.UUID; @Service public class VoucherService { @@ -20,8 +21,12 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public Voucher create(Voucher voucher) { - validateDiscount(voucher); + public Voucher create(CreateVoucherRequestDTO createVoucherRequestDTO) { + //TODO: static factory method + validation of discountValue + Voucher voucher = switch (createVoucherRequestDTO.createVoucherMenu()) { + case FIXED -> new FixedAmountVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountAmount()); + case PERCENT -> new PercentVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountAmount()); + }; voucherRepository.save(voucher); return voucher; } @@ -32,13 +37,6 @@ public List readAllVouchers() { if (vouchers.isEmpty()) { throw new NoSuchElementException(VOUCHER_NOT_FOUND_MESSAGE); } - return vouchers; } - - public void validateDiscount(Voucher voucher) { - if (!voucher.validatePositiveDiscount()) { - throw new IllegalArgumentException(INVALID_DISCOUNT_INPUT_MESSAGE); - } - } } From b67ba77376786e7e3c0168aabf5f5a2dceeb24e8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 13:50:07 +0900 Subject: [PATCH 046/383] enhance: replace Voucher with CreateVoucherRequestDTO --- .../consolecomponent/ConsoleManager.java | 34 +++++-------------- .../consolecomponent/MenuHandler.java | 5 +-- .../voucher/VoucherController.java | 4 +-- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index 5f17ab7b99..89ddb8281d 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -1,15 +1,12 @@ package com.programmers.vouchermanagement.consolecomponent; -import com.programmers.vouchermanagement.voucher.FixedAmountVoucher; -import com.programmers.vouchermanagement.voucher.PercentVoucher; +import com.programmers.vouchermanagement.voucher.CreateVoucherRequestDTO; import com.programmers.vouchermanagement.voucher.Voucher; - import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.springframework.stereotype.Component; import java.util.List; -import java.util.UUID; import static com.programmers.vouchermanagement.consolecomponent.Menu.findSelectedMenu; import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; @@ -28,8 +25,6 @@ public class ConsoleManager { Type **fixed** to create a fixed amount voucher. Type **percent** to create a percent discount voucher. """; - - //TODO: consider line separator as new line command may differ for every OS private static final String VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION = "Please type the amount/percent of discount of the voucher.%s".formatted(LINE_SEPARATOR); private static final String INVALID_VOUCHER_TYPE_MESSAGE = @@ -40,9 +35,9 @@ public class ConsoleManager { "The voucher(ID: %s) is successfully created."; private static final String INCORRECT_INPUT_MESSAGE = """ - Such input is incorrect. - Please input a correct command carefully. - """; + Such input is incorrect. + Please input a correct command carefully. + """; //--- private final TextIO textIO; @@ -60,26 +55,15 @@ public Menu selectMenu() { return findSelectedMenu(input); } - public Voucher instructCreate() { + public CreateVoucherRequestDTO instructCreate() { String createMenu = textIO.newStringInputReader() .read(CREATE_SELECTION_INSTRUCTION); + CreateVoucherMenu createVoucherMenu = CreateVoucherMenu.findCreateMenu(createMenu) + .orElseThrow(() -> new IllegalArgumentException(INCORRECT_INPUT_MESSAGE)); - //TODO: refactor order of inputs obtaining + error handling - long discountAmount = textIO.newLongInputReader() + long discountValue = textIO.newLongInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); - - // TODO: reconsider constructing models (Bean, factory method in DTO) - switch (createMenu) { - case "fixed" -> { - return new FixedAmountVoucher(UUID.randomUUID(), discountAmount); - } - - case "percent" -> { - return new PercentVoucher(UUID.randomUUID(), discountAmount); - } - - default -> throw new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE); - } + return new CreateVoucherRequestDTO(createVoucherMenu, discountValue); } public void printCreateResult(Voucher voucher) { diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index 7a4e44928f..b1d870432f 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.consolecomponent; +import com.programmers.vouchermanagement.voucher.CreateVoucherRequestDTO; import com.programmers.vouchermanagement.voucher.Voucher; import com.programmers.vouchermanagement.voucher.VoucherController; import org.springframework.stereotype.Component; @@ -53,8 +54,8 @@ private void executeMenu(Menu menu) { case EXIT -> consoleManager.printExit(); case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { - Voucher voucher = consoleManager.instructCreate(); - voucher = voucherController.create(voucher); + CreateVoucherRequestDTO createVoucherRequestDTO = consoleManager.instructCreate(); + Voucher voucher = voucherController.create(createVoucherRequestDTO); consoleManager.printCreateResult(voucher); } case LIST -> { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index 97e58d8a18..037d40334d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -17,8 +17,8 @@ public VoucherController(ConsoleManager consoleManager, VoucherService voucherSe } //TODO: add DTO - public Voucher create(Voucher voucher) { - return voucherService.create(voucher); + public Voucher create(CreateVoucherRequestDTO createVoucherRequestDTO) { + return voucherService.create(createVoucherRequestDTO); } public List readAllVouchers() { From fecf150a26d7a6f03d7f30610989ddaf80be3efa Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 13:53:30 +0900 Subject: [PATCH 047/383] style: rename findSelectedMenu to findMenu --- .../vouchermanagement/consolecomponent/ConsoleManager.java | 3 +-- .../programmers/vouchermanagement/consolecomponent/Menu.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index 89ddb8281d..d2e56f5190 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -8,7 +8,6 @@ import java.util.List; -import static com.programmers.vouchermanagement.consolecomponent.Menu.findSelectedMenu; import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; @Component @@ -52,7 +51,7 @@ public Menu selectMenu() { String input = textIO.newStringInputReader() .read(MENU_SELECTION_INSTRUCTION); - return findSelectedMenu(input); + return Menu.findMenu(input); } public CreateVoucherRequestDTO instructCreate() { diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java index 4e05716656..b87aca4518 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java @@ -20,7 +20,7 @@ private boolean isMatching(String input) { } //set static to tell that this method does not depend on a particular Menu value - public static Menu findSelectedMenu(String input) { + public static Menu findMenu(String input) { return Arrays.stream(Menu.values()) .filter(menu -> menu.isMatching(input)) .findFirst() From 7ad3ff00cd3f1fc00c2505e9d2618d476e1acd1e Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 14:25:32 +0900 Subject: [PATCH 048/383] refactor: resolve exception handling by handling exceptions in MenuHandler --- .../consolecomponent/ConsoleManager.java | 5 +++-- .../consolecomponent/MenuHandler.java | 8 +++++++- .../voucher/VoucherController.java | 19 ++++--------------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index d2e56f5190..98d105b863 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -26,6 +26,8 @@ public class ConsoleManager { """; private static final String VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION = "Please type the amount/percent of discount of the voucher.%s".formatted(LINE_SEPARATOR); + + //TODO: move this message to factory method private static final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; private static final String EXIT_MESSAGE = @@ -81,9 +83,8 @@ public void printIncorrectMenu() { textIO.getTextTerminal().println(INCORRECT_INPUT_MESSAGE); } - //TODO: add exception handling method externally public void printException(RuntimeException e) { - logger.error(e.getMessage()); textIO.getTextTerminal().println(e.getMessage()); + logger.error(e.getMessage()); } } diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java index b1d870432f..06f5513af0 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java @@ -29,7 +29,13 @@ public MenuHandler(ConsoleManager consoleManager, VoucherController voucherContr public boolean handleMenu() { Menu menu = selectMenu(); - executeMenu(menu); + + try { + executeMenu(menu); + } catch (RuntimeException e) { + consoleManager.printException(e); + } + return isValidMenu(menu); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java index 037d40334d..30b3c3b3d1 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java @@ -1,35 +1,24 @@ package com.programmers.vouchermanagement.voucher; -import com.programmers.vouchermanagement.consolecomponent.ConsoleManager; import org.springframework.stereotype.Controller; -import java.util.Collections; import java.util.List; @Controller public class VoucherController { - private final ConsoleManager consoleManager; private final VoucherService voucherService; - public VoucherController(ConsoleManager consoleManager, VoucherService voucherService) { - this.consoleManager = consoleManager; + //TODO: Response DTO and consider conversion to text format for GUI response + + public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } - //TODO: add DTO public Voucher create(CreateVoucherRequestDTO createVoucherRequestDTO) { return voucherService.create(createVoucherRequestDTO); } public List readAllVouchers() { - try { - return voucherService.readAllVouchers(); - } catch (RuntimeException e) { - //TODO: add exception handling method externally - consoleManager.printException(e); - - //TODO: reconsider return empty list from service - return Collections.emptyList(); - } + return voucherService.readAllVouchers(); } } From f99e477fa8bab502bb74556e8e2d1885f8ae249d Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 14:26:03 +0900 Subject: [PATCH 049/383] comment: add TODO --- .../programmers/vouchermanagement/voucher/VoucherService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java index 8fcbda93a8..6859e11e76 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java @@ -11,6 +11,8 @@ public class VoucherService { //messages private static final String VOUCHER_NOT_FOUND_MESSAGE = "There is no voucher registered."; + + //TODO: move this message to factory method private static final String INVALID_DISCOUNT_INPUT_MESSAGE = "Input should be a number greater than 0"; //--- From 746f6059902891cdae21b88e2bded9c0b13f6a3b Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 14:26:23 +0900 Subject: [PATCH 050/383] style: remove unused statements --- .../vouchermanagement/voucher/VoucherRepository.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java index be3e9cd00c..f2611300d8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java @@ -1,9 +1,6 @@ package com.programmers.vouchermanagement.voucher; -import com.programmers.vouchermanagement.voucher.Voucher; - import java.util.List; -import java.util.Optional; public interface VoucherRepository { void save(Voucher voucher); From d68c03da62e1bd04033381e0bba86a8d24d43f14 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 14:26:51 +0900 Subject: [PATCH 051/383] comment: add a conversation to be considered --- .../vouchermanagement/configuration/AppConfig.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java index 884b051279..fb1e732be6 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java @@ -10,6 +10,10 @@ @Configuration public class AppConfig { + // Conversation: + // Injecting logger to where it would be used + // VS + // Static logger to be used in wherever willing to use @Bean public Logger logger() { return LoggerFactory.getLogger(VoucherManagementApplication.class); From 9232909b01e36daef6e6c8c21d203344657b9311 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 14:49:28 +0900 Subject: [PATCH 052/383] chore: set logger to read from src --- src/main/resources/logback-spring.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index ff9931be2b..b65e0afbb2 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -1,5 +1,5 @@ - + @@ -13,7 +13,12 @@ - + + + + + + From 90a2c9d1ba25295e9108f53efaad905130153ae9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 16:52:31 +0900 Subject: [PATCH 053/383] chore: add jackson-databind dependency --- pom.xml | 86 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index e8eb588309..741cc758e0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,47 +1,53 @@ - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.1.4 - - - com.programmers - voucherManangement - 0.0.1-SNAPSHOT - voucherManagement - voucherManagement - - 17 - - - - org.springframework.boot - spring-boot-starter - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.1.4 + + + com.programmers + voucherManangement + 0.0.1-SNAPSHOT + voucherManagement + voucherManagement + + 17 + + + + org.springframework.boot + spring-boot-starter + - - org.springframework.boot - spring-boot-starter-test - test - + + org.springframework.boot + spring-boot-starter-test + test + - - org.beryx - text-io - 3.4.1 - - + + com.fasterxml.jackson.core + jackson-databind + 2.15.2 + - - - - org.springframework.boot - spring-boot-maven-plugin - - - + + org.beryx + text-io + 3.4.1 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + From 54ec062ccfdf8149f7c01904a9d21c0fe771582e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 18:31:48 +0900 Subject: [PATCH 054/383] enhance: add validation of discount value of vouchers --- .../voucher/FixedAmountVoucher.java | 14 +++++++++----- .../vouchermanagement/voucher/PercentVoucher.java | 14 +++++++++----- .../vouchermanagement/voucher/Voucher.java | 2 -- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java index 6ea6603e06..8c9e02e6ee 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java @@ -3,10 +3,13 @@ import java.util.UUID; public class FixedAmountVoucher implements Voucher { + private static final String INVALID_DISCOUNT_INPUT_MESSAGE = + "Input should be a number greater than 0"; private final UUID voucherID; private final long discountAmount; public FixedAmountVoucher(UUID voucherID, long discountAmount) { + validateDiscountAmount(discountAmount); this.voucherID = voucherID; this.discountAmount = discountAmount; } @@ -21,11 +24,6 @@ public long discount(long priceBeforeDiscount) { return priceBeforeDiscount - discountAmount; } - @Override - public boolean validatePositiveDiscount() { - return discountAmount > 0; - } - @Override public String toConsoleFormat() { return """ @@ -35,4 +33,10 @@ public String toConsoleFormat() { -------------------------""" .formatted(voucherID, discountAmount); } + + private void validateDiscountAmount(long discountAmount) { + if (discountAmount <= 0) { + throw new IllegalArgumentException(INVALID_DISCOUNT_INPUT_MESSAGE); + } + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java index 6338cff7f9..a48d171adc 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java @@ -3,10 +3,13 @@ import java.util.UUID; public class PercentVoucher implements Voucher { + private static final String INVALID_DISCOUNT_INPUT_MESSAGE = + "Input should be a number greater than 0 and smaller than 100"; private final UUID voucherID; private final long discountPercent; public PercentVoucher(UUID voucherID, long discountPercent) { + validateDiscountPercent(discountPercent); this.voucherID = voucherID; this.discountPercent = discountPercent; } @@ -21,11 +24,6 @@ public long discount(long priceBeforeDiscount) { return (long) (priceBeforeDiscount * (1 - discountPercent / 100D)); } - @Override - public boolean validatePositiveDiscount() { - return discountPercent > 0; - } - @Override public String toConsoleFormat() { return """ @@ -35,4 +33,10 @@ public String toConsoleFormat() { -------------------------""" .formatted(voucherID, discountPercent); } + + private void validateDiscountPercent(long discountPercent) { + if (discountPercent <= 0 || discountPercent > 100) { + throw new IllegalArgumentException(INVALID_DISCOUNT_INPUT_MESSAGE); + } + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java index 01489f9374..16ccfeb2ce 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java @@ -7,7 +7,5 @@ public interface Voucher { long discount(long priceBeforeDiscount); - boolean validatePositiveDiscount(); - String toConsoleFormat(); } From 52a57340ec61662e1a27bdb7069660fecf206946 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 18:32:56 +0900 Subject: [PATCH 055/383] enhance: print proper message for invalid discount value input --- .../consolecomponent/ConsoleManager.java | 8 +++----- .../vouchermanagement/voucher/VoucherService.java | 6 +----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java index 98d105b863..c3ec45d91d 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java @@ -26,10 +26,6 @@ public class ConsoleManager { """; private static final String VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION = "Please type the amount/percent of discount of the voucher.%s".formatted(LINE_SEPARATOR); - - //TODO: move this message to factory method - private static final String INVALID_VOUCHER_TYPE_MESSAGE = - "Voucher type should be either fixed amount or percent discount voucher."; private static final String EXIT_MESSAGE = "System exits."; private static final String CREATE_SUCCESS_MESSAGE = @@ -39,6 +35,8 @@ public class ConsoleManager { Such input is incorrect. Please input a correct command carefully. """; + private static final String INVALID_VOUCHER_TYPE_MESSAGE = + "Voucher type should be either fixed amount or percent discount voucher."; //--- private final TextIO textIO; @@ -60,7 +58,7 @@ public CreateVoucherRequestDTO instructCreate() { String createMenu = textIO.newStringInputReader() .read(CREATE_SELECTION_INSTRUCTION); CreateVoucherMenu createVoucherMenu = CreateVoucherMenu.findCreateMenu(createMenu) - .orElseThrow(() -> new IllegalArgumentException(INCORRECT_INPUT_MESSAGE)); + .orElseThrow(() -> new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE)); long discountValue = textIO.newLongInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java index 6859e11e76..ac49a80a89 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher; +import com.programmers.vouchermanagement.consolecomponent.CreateVoucherMenu; import org.springframework.stereotype.Service; import java.util.List; @@ -11,10 +12,6 @@ public class VoucherService { //messages private static final String VOUCHER_NOT_FOUND_MESSAGE = "There is no voucher registered."; - - //TODO: move this message to factory method - private static final String INVALID_DISCOUNT_INPUT_MESSAGE = - "Input should be a number greater than 0"; //--- private final VoucherRepository voucherRepository; @@ -24,7 +21,6 @@ public VoucherService(VoucherRepository voucherRepository) { } public Voucher create(CreateVoucherRequestDTO createVoucherRequestDTO) { - //TODO: static factory method + validation of discountValue Voucher voucher = switch (createVoucherRequestDTO.createVoucherMenu()) { case FIXED -> new FixedAmountVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountAmount()); case PERCENT -> new PercentVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountAmount()); From b45ab2f22afc5b8000d9666d1e7c1cf3b1d6c4fe Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 18:41:18 +0900 Subject: [PATCH 056/383] refactor: re-package the project --- .../io}/ConsoleManager.java | 8 +++++--- .../menu}/CreateVoucherMenu.java | 2 +- .../{consolecomponent => consoleapp/menu}/Menu.java | 2 +- .../menu}/MenuHandler.java | 9 +++++---- .../runner}/ConsoleAppRunner.java | 4 +++- .../vouchermanagement/customer/CustomerRepository.java | 7 ------- .../customer/{ => controller}/CustomerController.java | 5 ++++- .../customer/{ => domain}/Customer.java | 2 +- .../customer/repository/CustomerRepository.java | 9 +++++++++ .../{ => repository}/FileCustomerRepository.java | 4 +++- .../customer/{ => service}/CustomerService.java | 5 ++++- .../voucher/CreateVoucherRequestDTO.java | 6 ------ .../vouchermanagement/voucher/VoucherRepository.java | 8 -------- .../voucher/{ => controller}/VoucherController.java | 6 +++++- .../voucher/{ => domain}/FixedAmountVoucher.java | 2 +- .../voucher/{ => domain}/PercentVoucher.java | 2 +- .../voucher/{ => domain}/Voucher.java | 2 +- .../voucher/dto/CreateVoucherRequestDTO.java | 6 ++++++ .../{ => repository}/InMemoryVoucherRepository.java | 4 +++- .../voucher/repository/VoucherRepository.java | 10 ++++++++++ .../voucher/{ => service}/VoucherService.java | 9 +++++++-- 21 files changed, 70 insertions(+), 42 deletions(-) rename src/main/java/com/programmers/vouchermanagement/{consolecomponent => consoleapp/io}/ConsoleManager.java (90%) rename src/main/java/com/programmers/vouchermanagement/{consolecomponent => consoleapp/menu}/CreateVoucherMenu.java (92%) rename src/main/java/com/programmers/vouchermanagement/{consolecomponent => consoleapp/menu}/Menu.java (93%) rename src/main/java/com/programmers/vouchermanagement/{consolecomponent => consoleapp/menu}/MenuHandler.java (84%) rename src/main/java/com/programmers/vouchermanagement/{consolecomponent => consoleapp/runner}/ConsoleAppRunner.java (85%) delete mode 100644 src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java rename src/main/java/com/programmers/vouchermanagement/customer/{ => controller}/CustomerController.java (65%) rename src/main/java/com/programmers/vouchermanagement/customer/{ => domain}/Customer.java (90%) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java rename src/main/java/com/programmers/vouchermanagement/customer/{ => repository}/FileCustomerRepository.java (92%) rename src/main/java/com/programmers/vouchermanagement/customer/{ => service}/CustomerService.java (76%) delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java rename src/main/java/com/programmers/vouchermanagement/voucher/{ => controller}/VoucherController.java (68%) rename src/main/java/com/programmers/vouchermanagement/voucher/{ => domain}/FixedAmountVoucher.java (95%) rename src/main/java/com/programmers/vouchermanagement/voucher/{ => domain}/PercentVoucher.java (95%) rename src/main/java/com/programmers/vouchermanagement/voucher/{ => domain}/Voucher.java (72%) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java rename src/main/java/com/programmers/vouchermanagement/voucher/{ => repository}/InMemoryVoucherRepository.java (80%) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java rename src/main/java/com/programmers/vouchermanagement/voucher/{ => service}/VoucherService.java (73%) diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java similarity index 90% rename from src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java rename to src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index c3ec45d91d..0f1b6c32aa 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,7 +1,9 @@ -package com.programmers.vouchermanagement.consolecomponent; +package com.programmers.vouchermanagement.consoleapp.io; -import com.programmers.vouchermanagement.voucher.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.Voucher; +import com.programmers.vouchermanagement.consoleapp.menu.CreateVoucherMenu; +import com.programmers.vouchermanagement.consoleapp.menu.Menu; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; +import com.programmers.vouchermanagement.voucher.domain.Voucher; import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/CreateVoucherMenu.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/CreateVoucherMenu.java similarity index 92% rename from src/main/java/com/programmers/vouchermanagement/consolecomponent/CreateVoucherMenu.java rename to src/main/java/com/programmers/vouchermanagement/consoleapp/menu/CreateVoucherMenu.java index 67f48a13a5..bb377b55ef 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/CreateVoucherMenu.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/CreateVoucherMenu.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.consolecomponent; +package com.programmers.vouchermanagement.consoleapp.menu; import java.util.Arrays; import java.util.Objects; diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/Menu.java similarity index 93% rename from src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java rename to src/main/java/com/programmers/vouchermanagement/consoleapp/menu/Menu.java index b87aca4518..691cf3bc23 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/Menu.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/Menu.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.consolecomponent; +package com.programmers.vouchermanagement.consoleapp.menu; import java.util.Arrays; import java.util.Objects; diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java similarity index 84% rename from src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java rename to src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 06f5513af0..adaa749cae 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -1,8 +1,9 @@ -package com.programmers.vouchermanagement.consolecomponent; +package com.programmers.vouchermanagement.consoleapp.menu; -import com.programmers.vouchermanagement.voucher.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.Voucher; -import com.programmers.vouchermanagement.voucher.VoucherController; +import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.controller.VoucherController; import org.springframework.stereotype.Component; import java.util.List; diff --git a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java similarity index 85% rename from src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java rename to src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java index 7fa81a15a7..d8ca0144f9 100644 --- a/src/main/java/com/programmers/vouchermanagement/consolecomponent/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java @@ -1,10 +1,12 @@ -package com.programmers.vouchermanagement.consolecomponent; +package com.programmers.vouchermanagement.consoleapp.runner; import org.slf4j.Logger; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; +import com.programmers.vouchermanagement.consoleapp.menu.MenuHandler; + @Component public class ConsoleAppRunner implements ApplicationRunner { private final MenuHandler menuHandler; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java deleted file mode 100644 index 5029189b3b..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/customer/CustomerRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.programmers.vouchermanagement.customer; - -import java.util.List; - -public interface CustomerRepository { - List findBlackCustomers(); -} diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java similarity index 65% rename from src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java rename to src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 43796da2f7..5494d8d8b0 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -1,9 +1,12 @@ -package com.programmers.vouchermanagement.customer; +package com.programmers.vouchermanagement.customer.controller; import java.util.List; import org.springframework.stereotype.Controller; +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.service.CustomerService; + @Controller public class CustomerController { private final CustomerService customerService; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java similarity index 90% rename from src/main/java/com/programmers/vouchermanagement/customer/Customer.java rename to src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index b7634fbadb..858682ad98 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.customer; +package com.programmers.vouchermanagement.customer.domain; import java.util.UUID; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java new file mode 100644 index 0000000000..70ad8fb58f --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -0,0 +1,9 @@ +package com.programmers.vouchermanagement.customer.repository; + +import java.util.List; + +import com.programmers.vouchermanagement.customer.domain.Customer; + +public interface CustomerRepository { + List findBlackCustomers(); +} diff --git a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java similarity index 92% rename from src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java rename to src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index 9cbf974207..65a8cd15cd 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.customer; +package com.programmers.vouchermanagement.customer.repository; import java.io.BufferedReader; import java.io.FileReader; @@ -11,6 +11,8 @@ import org.springframework.stereotype.Repository; +import com.programmers.vouchermanagement.customer.domain.Customer; + @Repository public class FileCustomerRepository implements CustomerRepository { private static final String BLACKLIST_FILE_PATH = "src/main/resources/blacklist.csv"; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java similarity index 76% rename from src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java rename to src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index b50a558daf..97a7d8a393 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -1,10 +1,13 @@ -package com.programmers.vouchermanagement.customer; +package com.programmers.vouchermanagement.customer.service; import java.util.List; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.repository.CustomerRepository; + @Service public class CustomerService { private final CustomerRepository customerRepository; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java deleted file mode 100644 index ab61908ab2..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/CreateVoucherRequestDTO.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.programmers.vouchermanagement.voucher; - -import com.programmers.vouchermanagement.consolecomponent.CreateVoucherMenu; - -public record CreateVoucherRequestDTO(CreateVoucherMenu createVoucherMenu, long discountAmount) { -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java deleted file mode 100644 index f2611300d8..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.programmers.vouchermanagement.voucher; - -import java.util.List; - -public interface VoucherRepository { - void save(Voucher voucher); - List findAll(); -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java similarity index 68% rename from src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java rename to src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 30b3c3b3d1..426562a4b7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,9 +1,13 @@ -package com.programmers.vouchermanagement.voucher; +package com.programmers.vouchermanagement.voucher.controller; import org.springframework.stereotype.Controller; import java.util.List; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; +import com.programmers.vouchermanagement.voucher.service.VoucherService; + @Controller public class VoucherController { private final VoucherService voucherService; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java similarity index 95% rename from src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java rename to src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java index 8c9e02e6ee..6fc4f093f7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher; +package com.programmers.vouchermanagement.voucher.domain; import java.util.UUID; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java similarity index 95% rename from src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java rename to src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java index a48d171adc..cc00bb6711 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher; +package com.programmers.vouchermanagement.voucher.domain; import java.util.UUID; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java similarity index 72% rename from src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java rename to src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 16ccfeb2ce..7809da4fbb 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher; +package com.programmers.vouchermanagement.voucher.domain; import java.util.UUID; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java new file mode 100644 index 0000000000..667196eef3 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java @@ -0,0 +1,6 @@ +package com.programmers.vouchermanagement.voucher.dto; + +import com.programmers.vouchermanagement.consoleapp.menu.CreateVoucherMenu; + +public record CreateVoucherRequestDTO(CreateVoucherMenu createVoucherMenu, long discountAmount) { +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java similarity index 80% rename from src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java rename to src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java index 88766047e0..e46658bc1f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java @@ -1,9 +1,11 @@ -package com.programmers.vouchermanagement.voucher; +package com.programmers.vouchermanagement.voucher.repository; import java.util.*; import org.springframework.stereotype.Repository; +import com.programmers.vouchermanagement.voucher.domain.Voucher; + @Repository public class InMemoryVoucherRepository implements VoucherRepository { private final Map vouchers; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java new file mode 100644 index 0000000000..c5545b4769 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -0,0 +1,10 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import java.util.List; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; + +public interface VoucherRepository { + void save(Voucher voucher); + List findAll(); +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java similarity index 73% rename from src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java rename to src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index ac49a80a89..4077b3c246 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,6 +1,11 @@ -package com.programmers.vouchermanagement.voucher; +package com.programmers.vouchermanagement.voucher.service; + +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; +import com.programmers.vouchermanagement.voucher.domain.FixedAmountVoucher; +import com.programmers.vouchermanagement.voucher.domain.PercentVoucher; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; -import com.programmers.vouchermanagement.consolecomponent.CreateVoucherMenu; import org.springframework.stereotype.Service; import java.util.List; From f9d9ce05254868af8276b7934282defe446e49f0 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 19:20:35 +0900 Subject: [PATCH 057/383] refactor: rename CreateVoucherMenu to VoucherType --- .../consoleapp/menu/CreateVoucherMenu.java | 28 ----------------- .../voucher/domain/VoucherType.java | 31 +++++++++++++++++++ .../voucher/dto/CreateVoucherRequestDTO.java | 4 +-- 3 files changed, 33 insertions(+), 30 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/consoleapp/menu/CreateVoucherMenu.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/CreateVoucherMenu.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/CreateVoucherMenu.java deleted file mode 100644 index bb377b55ef..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/CreateVoucherMenu.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.programmers.vouchermanagement.consoleapp.menu; - -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; - -public enum CreateVoucherMenu { - FIXED("fixed"), - PERCENT("percent"); - - private final String menuName; - - CreateVoucherMenu(String menuName) { - this.menuName = menuName; - } - - //set static to tell that this method does not depend on a particular Menu value - public static Optional findCreateMenu(String input) { - return Arrays.stream(CreateVoucherMenu.values()) - .filter(menu -> menu.isMatching(input)) - .findFirst(); - } - - private boolean isMatching(String input) { - return Objects.equals(menuName, input); - } - -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java new file mode 100644 index 0000000000..393e0bd6f0 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -0,0 +1,31 @@ +package com.programmers.vouchermanagement.voucher.domain; + +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; + +public enum VoucherType { + FIXED("Fixed Amount"), + PERCENT("Percent"); + + private final String typeName; + + VoucherType(String typeName) { + this.typeName = typeName; + } + + //set static to tell that this method does not depend on a particular Menu value + public static Optional findCreateMenu(String input) { + return Arrays.stream(VoucherType.values()) + .filter(menu -> menu.isMatching(input)) + .findFirst(); + } + + private boolean isMatching(String input) { + return Objects.equals(this.name().toLowerCase(), input); + } + + public String displayTypeName() { + return typeName; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java index 667196eef3..41d3e454f6 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java @@ -1,6 +1,6 @@ package com.programmers.vouchermanagement.voucher.dto; -import com.programmers.vouchermanagement.consoleapp.menu.CreateVoucherMenu; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; -public record CreateVoucherRequestDTO(CreateVoucherMenu createVoucherMenu, long discountAmount) { +public record CreateVoucherRequestDTO(VoucherType voucherType, long discountValue) { } From c9d6b5102248090428b1d2a0f73c923d19ace722 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 19:21:22 +0900 Subject: [PATCH 058/383] feat: add VoucherResponseDTO --- .../voucher/dto/VoucherResponseDTO.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponseDTO.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponseDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponseDTO.java new file mode 100644 index 0000000000..e20be98192 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponseDTO.java @@ -0,0 +1,29 @@ +package com.programmers.vouchermanagement.voucher.dto; + +import java.util.UUID; + +import com.programmers.vouchermanagement.voucher.domain.VoucherType; + +public class VoucherResponseDTO { + private final UUID voucherId; + private final long discountValue; + private final String voucherType; + + public VoucherResponseDTO(UUID voucherId, long discountValue, VoucherType voucherType) { + this.voucherId = voucherId; + this.discountValue = discountValue; + this.voucherType = voucherType.displayTypeName(); + } + + public UUID getVoucherId() { + return voucherId; + } + + public long getDiscountValue() { + return discountValue; + } + + public String getVoucherType() { + return voucherType; + } +} From 4b57c425c5356b0d053a0e14df7fea7fe65fc4b9 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 19:22:04 +0900 Subject: [PATCH 059/383] enhance: implement conversion method of Voucher to ResponseDTO --- .../voucher/domain/FixedAmountVoucher.java | 11 ++++------- .../voucher/domain/PercentVoucher.java | 11 ++++------- .../vouchermanagement/voucher/domain/Voucher.java | 4 +++- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java index 6fc4f093f7..178db87150 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java @@ -2,6 +2,8 @@ import java.util.UUID; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; + public class FixedAmountVoucher implements Voucher { private static final String INVALID_DISCOUNT_INPUT_MESSAGE = "Input should be a number greater than 0"; @@ -25,13 +27,8 @@ public long discount(long priceBeforeDiscount) { } @Override - public String toConsoleFormat() { - return """ - Voucher ID : %s - Voucher Type : Fixed Amount Voucher - Discount Amount : %s - -------------------------""" - .formatted(voucherID, discountAmount); + public VoucherResponseDTO toResponseDTO() { + return new VoucherResponseDTO(voucherID, discountAmount, VoucherType.FIXED); } private void validateDiscountAmount(long discountAmount) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java index cc00bb6711..29bd88c623 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java @@ -2,6 +2,8 @@ import java.util.UUID; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; + public class PercentVoucher implements Voucher { private static final String INVALID_DISCOUNT_INPUT_MESSAGE = "Input should be a number greater than 0 and smaller than 100"; @@ -25,13 +27,8 @@ public long discount(long priceBeforeDiscount) { } @Override - public String toConsoleFormat() { - return """ - Voucher ID : %s - Voucher Type : Percent Discount Voucher - Discount Percentage : %s%% - -------------------------""" - .formatted(voucherID, discountPercent); + public VoucherResponseDTO toResponseDTO() { + return new VoucherResponseDTO(voucherID, discountPercent, VoucherType.PERCENT); } private void validateDiscountPercent(long discountPercent) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 7809da4fbb..5f97d700c3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -2,10 +2,12 @@ import java.util.UUID; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; + public interface Voucher { UUID getVoucherId(); long discount(long priceBeforeDiscount); - String toConsoleFormat(); + VoucherResponseDTO toResponseDTO(); } From 86c95a96b5d7029dea24040ecb247ba79eda3198 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 19:22:52 +0900 Subject: [PATCH 060/383] enhance: apply VoucherResponseDTO instead of Voucher --- .../consoleapp/menu/MenuHandler.java | 11 ++++++----- .../voucher/controller/VoucherController.java | 7 +++---- .../voucher/service/VoucherService.java | 17 ++++++++++------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index adaa749cae..0ab8c03450 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -2,8 +2,9 @@ import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.controller.VoucherController; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; + import org.springframework.stereotype.Component; import java.util.List; @@ -62,12 +63,12 @@ private void executeMenu(Menu menu) { case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { CreateVoucherRequestDTO createVoucherRequestDTO = consoleManager.instructCreate(); - Voucher voucher = voucherController.create(createVoucherRequestDTO); - consoleManager.printCreateResult(voucher); + VoucherResponseDTO voucherResponse = voucherController.create(createVoucherRequestDTO); + consoleManager.printCreateResult(voucherResponse); } case LIST -> { - List vouchers = voucherController.readAllVouchers(); - consoleManager.printReadAll(vouchers); + List voucherResponses = voucherController.readAllVouchers(); + consoleManager.printReadAll(voucherResponses); } } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 426562a4b7..09852dcc7c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -6,23 +6,22 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; import com.programmers.vouchermanagement.voucher.service.VoucherService; @Controller public class VoucherController { private final VoucherService voucherService; - //TODO: Response DTO and consider conversion to text format for GUI response - public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } - public Voucher create(CreateVoucherRequestDTO createVoucherRequestDTO) { + public VoucherResponseDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { return voucherService.create(createVoucherRequestDTO); } - public List readAllVouchers() { + public List readAllVouchers() { return voucherService.readAllVouchers(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 4077b3c246..39148f4c57 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -4,6 +4,7 @@ import com.programmers.vouchermanagement.voucher.domain.FixedAmountVoucher; import com.programmers.vouchermanagement.voucher.domain.PercentVoucher; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; @@ -25,21 +26,23 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public Voucher create(CreateVoucherRequestDTO createVoucherRequestDTO) { - Voucher voucher = switch (createVoucherRequestDTO.createVoucherMenu()) { - case FIXED -> new FixedAmountVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountAmount()); - case PERCENT -> new PercentVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountAmount()); + public VoucherResponseDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { + Voucher voucher = switch (createVoucherRequestDTO.voucherType()) { + case FIXED -> new FixedAmountVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountValue()); + case PERCENT -> new PercentVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountValue()); }; voucherRepository.save(voucher); - return voucher; + return voucher.toResponseDTO(); } - public List readAllVouchers() { + public List readAllVouchers() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { throw new NoSuchElementException(VOUCHER_NOT_FOUND_MESSAGE); } - return vouchers; + return vouchers.stream() + .map(Voucher::toResponseDTO) + .toList(); } } From 51a1e66aeae766aa46585484b43ee8baf14ec480 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 19:24:36 +0900 Subject: [PATCH 061/383] refactor: assign business of formatting of passed VoucherResponseDTO to view --- .../consoleapp/io/ConsoleManager.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 0f1b6c32aa..52c1d8de7c 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,9 +1,10 @@ package com.programmers.vouchermanagement.consoleapp.io; -import com.programmers.vouchermanagement.consoleapp.menu.CreateVoucherMenu; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; + import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.springframework.stereotype.Component; @@ -59,20 +60,31 @@ public Menu selectMenu() { public CreateVoucherRequestDTO instructCreate() { String createMenu = textIO.newStringInputReader() .read(CREATE_SELECTION_INSTRUCTION); - CreateVoucherMenu createVoucherMenu = CreateVoucherMenu.findCreateMenu(createMenu) + VoucherType voucherType = VoucherType.findCreateMenu(createMenu) .orElseThrow(() -> new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE)); long discountValue = textIO.newLongInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); - return new CreateVoucherRequestDTO(createVoucherMenu, discountValue); + return new CreateVoucherRequestDTO(voucherType, discountValue); + } + + public void printCreateResult(VoucherResponseDTO voucherResponse) { + textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.getVoucherId())); } - public void printCreateResult(Voucher voucher) { - textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucher.getVoucherId())); + public void printReadAll(List voucherResponses) { + voucherResponses.forEach(voucherResponse -> textIO.getTextTerminal().println(formatVoucherDTO(voucherResponse))); } - public void printReadAll(List vouchers) { - vouchers.forEach(voucher -> textIO.getTextTerminal().println(voucher.toConsoleFormat())); + private String formatVoucherDTO(VoucherResponseDTO voucherResponseDTO) { + return """ + Voucher ID : %s + Voucher Type : %s Discount Voucher + Discount Amount : %s + -------------------------""" + .formatted(voucherResponseDTO.getVoucherId(), + voucherResponseDTO.getVoucherType(), + voucherResponseDTO.getDiscountValue()); } public void printExit() { From 1fe5ee60184c8d0de9f27a71446bf0d3500cad88 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 23:07:11 +0900 Subject: [PATCH 062/383] chore: fix logback to work for both INFO and ERROR levels --- src/main/resources/logback-spring.xml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index b65e0afbb2..248e05345f 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -4,7 +4,12 @@ - + + + ERROR + ACCEPT + DENY + logs/access-%d{yyyy-MM-dd}.log @@ -13,12 +18,8 @@ - - - - + - From 3650a520911656cfad093c7b30a5d9c8ca88f75c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 23:32:47 +0900 Subject: [PATCH 063/383] enhance: change VoucherResponseDTO to GeneralVoucherDTO for using generally --- ...ResponseDTO.java => GeneralVoucherDTO.java} | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) rename src/main/java/com/programmers/vouchermanagement/voucher/dto/{VoucherResponseDTO.java => GeneralVoucherDTO.java} (58%) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponseDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/GeneralVoucherDTO.java similarity index 58% rename from src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponseDTO.java rename to src/main/java/com/programmers/vouchermanagement/voucher/dto/GeneralVoucherDTO.java index e20be98192..106b4c191f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponseDTO.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/GeneralVoucherDTO.java @@ -1,18 +1,18 @@ package com.programmers.vouchermanagement.voucher.dto; -import java.util.UUID; - import com.programmers.vouchermanagement.voucher.domain.VoucherType; -public class VoucherResponseDTO { +import java.util.UUID; + +public class GeneralVoucherDTO { private final UUID voucherId; private final long discountValue; - private final String voucherType; + private final VoucherType voucherType; - public VoucherResponseDTO(UUID voucherId, long discountValue, VoucherType voucherType) { + public GeneralVoucherDTO(UUID voucherId, long discountValue, VoucherType voucherType) { this.voucherId = voucherId; this.discountValue = discountValue; - this.voucherType = voucherType.displayTypeName(); + this.voucherType = voucherType; } public UUID getVoucherId() { @@ -24,6 +24,10 @@ public long getDiscountValue() { } public String getVoucherType() { - return voucherType; + return voucherType.name().toLowerCase(); + } + + public String getVoucherTypeName() { + return voucherType.displayTypeName(); } } From 7f66269ba62d7c176a9cbfaa605d984b1d28f60a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 23:34:09 +0900 Subject: [PATCH 064/383] enhance: apply GeneralVoucherDTO where it used --- .../consoleapp/io/ConsoleManager.java | 14 +++++++------- .../consoleapp/menu/MenuHandler.java | 6 +++--- .../voucher/controller/VoucherController.java | 7 +++---- .../voucher/domain/FixedAmountVoucher.java | 13 +++++++++---- .../voucher/domain/PercentVoucher.java | 11 ++++++++--- .../vouchermanagement/voucher/domain/Voucher.java | 8 +++++--- .../voucher/service/VoucherService.java | 10 +++++----- 7 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 52c1d8de7c..9e99eb3790 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -3,7 +3,7 @@ import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; import org.beryx.textio.TextIO; import org.slf4j.Logger; @@ -68,23 +68,23 @@ public CreateVoucherRequestDTO instructCreate() { return new CreateVoucherRequestDTO(voucherType, discountValue); } - public void printCreateResult(VoucherResponseDTO voucherResponse) { + public void printCreateResult(GeneralVoucherDTO voucherResponse) { textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.getVoucherId())); } - public void printReadAll(List voucherResponses) { + public void printReadAll(List voucherResponses) { voucherResponses.forEach(voucherResponse -> textIO.getTextTerminal().println(formatVoucherDTO(voucherResponse))); } - private String formatVoucherDTO(VoucherResponseDTO voucherResponseDTO) { + private String formatVoucherDTO(GeneralVoucherDTO generalVoucherDTO) { return """ Voucher ID : %s Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------""" - .formatted(voucherResponseDTO.getVoucherId(), - voucherResponseDTO.getVoucherType(), - voucherResponseDTO.getDiscountValue()); + .formatted(generalVoucherDTO.getVoucherId(), + generalVoucherDTO.getVoucherTypeName(), + generalVoucherDTO.getDiscountValue()); } public void printExit() { diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 0ab8c03450..8d356d2585 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -3,7 +3,7 @@ import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; import com.programmers.vouchermanagement.voucher.controller.VoucherController; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; import org.springframework.stereotype.Component; @@ -63,11 +63,11 @@ private void executeMenu(Menu menu) { case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { CreateVoucherRequestDTO createVoucherRequestDTO = consoleManager.instructCreate(); - VoucherResponseDTO voucherResponse = voucherController.create(createVoucherRequestDTO); + GeneralVoucherDTO voucherResponse = voucherController.create(createVoucherRequestDTO); consoleManager.printCreateResult(voucherResponse); } case LIST -> { - List voucherResponses = voucherController.readAllVouchers(); + List voucherResponses = voucherController.readAllVouchers(); consoleManager.printReadAll(voucherResponses); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 09852dcc7c..905176ea7c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -4,9 +4,8 @@ import java.util.List; -import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; import com.programmers.vouchermanagement.voucher.service.VoucherService; @Controller @@ -17,11 +16,11 @@ public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } - public VoucherResponseDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { + public GeneralVoucherDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { return voucherService.create(createVoucherRequestDTO); } - public List readAllVouchers() { + public List readAllVouchers() { return voucherService.readAllVouchers(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java index 178db87150..85bc4ada64 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java @@ -1,8 +1,8 @@ package com.programmers.vouchermanagement.voucher.domain; -import java.util.UUID; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; +import java.util.UUID; public class FixedAmountVoucher implements Voucher { private static final String INVALID_DISCOUNT_INPUT_MESSAGE = @@ -21,14 +21,19 @@ public UUID getVoucherId() { return voucherID; } + @Override + public long getDiscountValue() { + return discountAmount; + } + @Override public long discount(long priceBeforeDiscount) { return priceBeforeDiscount - discountAmount; } @Override - public VoucherResponseDTO toResponseDTO() { - return new VoucherResponseDTO(voucherID, discountAmount, VoucherType.FIXED); + public GeneralVoucherDTO toVoucherDTO() { + return new GeneralVoucherDTO(voucherID, discountAmount, VoucherType.FIXED); } private void validateDiscountAmount(long discountAmount) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java index 29bd88c623..88731ae3d9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java @@ -2,7 +2,7 @@ import java.util.UUID; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; public class PercentVoucher implements Voucher { private static final String INVALID_DISCOUNT_INPUT_MESSAGE = @@ -21,14 +21,19 @@ public UUID getVoucherId() { return voucherID; } + @Override + public long getDiscountValue() { + return discountPercent; + } + @Override public long discount(long priceBeforeDiscount) { return (long) (priceBeforeDiscount * (1 - discountPercent / 100D)); } @Override - public VoucherResponseDTO toResponseDTO() { - return new VoucherResponseDTO(voucherID, discountPercent, VoucherType.PERCENT); + public GeneralVoucherDTO toVoucherDTO() { + return new GeneralVoucherDTO(voucherID, discountPercent, VoucherType.PERCENT); } private void validateDiscountPercent(long discountPercent) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 5f97d700c3..974e9f9093 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -1,13 +1,15 @@ package com.programmers.vouchermanagement.voucher.domain; -import java.util.UUID; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; +import java.util.UUID; public interface Voucher { UUID getVoucherId(); + long getDiscountValue(); + long discount(long priceBeforeDiscount); - VoucherResponseDTO toResponseDTO(); + GeneralVoucherDTO toVoucherDTO(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 39148f4c57..e3f2a4c78a 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -4,7 +4,7 @@ import com.programmers.vouchermanagement.voucher.domain.FixedAmountVoucher; import com.programmers.vouchermanagement.voucher.domain.PercentVoucher; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponseDTO; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; @@ -26,23 +26,23 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public VoucherResponseDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { + public GeneralVoucherDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { Voucher voucher = switch (createVoucherRequestDTO.voucherType()) { case FIXED -> new FixedAmountVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountValue()); case PERCENT -> new PercentVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountValue()); }; voucherRepository.save(voucher); - return voucher.toResponseDTO(); + return voucher.toVoucherDTO(); } - public List readAllVouchers() { + public List readAllVouchers() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { throw new NoSuchElementException(VOUCHER_NOT_FOUND_MESSAGE); } return vouchers.stream() - .map(Voucher::toResponseDTO) + .map(Voucher::toVoucherDTO) .toList(); } } From 09f9bdeb5a287883f9328dbfdb377521f0d58711 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 19 Oct 2023 23:35:03 +0900 Subject: [PATCH 065/383] feat: implement FileVoucherRepository for write/read from json file --- .../repository/FileVoucherRepository.java | 97 +++++++++++++++++++ src/main/resources/voucher.json | 9 ++ 2 files changed, 106 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java create mode 100644 src/main/resources/voucher.json diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java new file mode 100644 index 0000000000..e3b70779a3 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -0,0 +1,97 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.programmers.vouchermanagement.voucher.domain.FixedAmountVoucher; +import com.programmers.vouchermanagement.voucher.domain.PercentVoucher; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; + +@Repository +@Profile("prod") +public class FileVoucherRepository implements VoucherRepository { + private static final String FILE_PATH = "src/main/resources/voucher.json"; + private final ObjectMapper objectMapper = new ObjectMapper(); + private final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; + + private Map vouchers; + + public FileVoucherRepository() { + this.vouchers = new HashMap<>(); + loadVouchers(); + } + + @Override + public void save(Voucher voucher) { + vouchers.put(voucher.getVoucherId(), voucher); + saveFile(); + } + + @Override + public List findAll() { + return vouchers.values().stream().toList(); + } + + private void loadVouchers() { + try { + File file = new File(FILE_PATH); + Map[] voucherObjects = objectMapper.readValue(file, Map[].class); + vouchers = objectsToVouchers(voucherObjects); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Map objectsToVouchers(Map[] voucherObjects) { + Map vouchersFromJSON = new HashMap<>(); + Arrays.stream(voucherObjects).forEach(voucherObject -> { + Voucher voucher = objectToVoucher(voucherObject); + vouchers.put(voucher.getVoucherId(), voucher); + }); + return vouchersFromJSON; + } + + private Voucher objectToVoucher(Map voucherObject) { + UUID voucherId = UUID.fromString((String) voucherObject.get("voucher_id")); + long discountValue = Long.parseLong(String.valueOf(voucherObject.get("discount_value"))); + String voucherTypeName = (String) voucherObject.get("voucher_type"); + VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) + .orElseThrow(() -> new NoSuchElementException(INVALID_VOUCHER_TYPE_MESSAGE)); + return switch (voucherType) { + case FIXED -> new FixedAmountVoucher(voucherId, discountValue); + case PERCENT -> new PercentVoucher(voucherId, discountValue); + }; + } + + public void saveFile() { + try (FileWriter fileWriter = new FileWriter(FILE_PATH)) { + List> voucherObjects = new ArrayList<>(); + if (!vouchers.isEmpty()) { + vouchers.values().forEach(voucher -> { + HashMap voucherObject = voucherToObject(voucher.toVoucherDTO()); + voucherObjects.add(voucherObject); + }); + } + String jsonStr = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(voucherObjects); + fileWriter.write(jsonStr); + fileWriter.flush(); + } catch (Exception e) { + throw new RuntimeException("File Exception"); + } + } + + private HashMap voucherToObject(GeneralVoucherDTO generalVoucherDTO) { + HashMap voucherObject = new HashMap<>(); + voucherObject.put("voucher_id", generalVoucherDTO.getVoucherId().toString()); + voucherObject.put("discount_value", generalVoucherDTO.getDiscountValue()); + voucherObject.put("voucher_type", generalVoucherDTO.getVoucherType()); + return voucherObject; + } +} diff --git a/src/main/resources/voucher.json b/src/main/resources/voucher.json new file mode 100644 index 0000000000..d9428d5c40 --- /dev/null +++ b/src/main/resources/voucher.json @@ -0,0 +1,9 @@ +[ { + "voucher_type" : "percent", + "voucher_id" : "ad9f0529-6f4e-4a36-b44e-d7d7b407c9a1", + "discount_value" : 100 +}, { + "voucher_type" : "fixed", + "voucher_id" : "ba65ee06-ae98-48cd-b31d-dfabb8c889a4", + "discount_value" : 100 +} ] \ No newline at end of file From 531e39841daf2caa4f90baf9d9602ae49036bc92 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 23:39:00 +0900 Subject: [PATCH 066/383] enhance: set profile and add application.yaml --- .../VoucherManagementApplication.java | 4 ++- .../customer/service/CustomerService.java | 2 -- .../properties/AppProperties.java | 32 +++++++++++++++++++ .../properties/Resources.java | 22 +++++++++++++ .../repository/InMemoryVoucherRepository.java | 2 ++ src/main/resources/application-dev.yaml | 9 ++++++ src/main/resources/application-prod.yaml | 11 +++++++ 7 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java create mode 100644 src/main/java/com/programmers/vouchermanagement/properties/Resources.java create mode 100644 src/main/resources/application-dev.yaml create mode 100644 src/main/resources/application-prod.yaml diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java index df8683ebea..e287c9046e 100644 --- a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java +++ b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java @@ -7,7 +7,9 @@ public class VoucherManagementApplication { public static void main(String[] args) { - SpringApplication.run(VoucherManagementApplication.class, args); + var application = new SpringApplication(VoucherManagementApplication.class); + application.setAdditionalProfiles("dev"); + application.run(args); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 97a7d8a393..9b638b357f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -18,11 +18,9 @@ public CustomerService(CustomerRepository customerRepository) { public List readBlacklist() { List blacklist = customerRepository.findBlackCustomers(); - //TODO: logger to inform no black customers exists if (blacklist.isEmpty()) { throw new NoSuchElementException("no blacklist"); } - return blacklist; } } diff --git a/src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java b/src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java new file mode 100644 index 0000000000..2615a00394 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java @@ -0,0 +1,32 @@ +package com.programmers.vouchermanagement.properties; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "file") +@EnableConfigurationProperties +public class AppProperties { + private Resources resources; + private Map domains = new HashMap<>(); + + public Resources getResources() { + return resources; + } + + public Map getDomains() { + return domains; + } + + public void setResources(Resources resources) { + this.resources = resources; + } + + public void setDomains(Map domains) { + this.domains = domains; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java new file mode 100644 index 0000000000..b98cf44a02 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java @@ -0,0 +1,22 @@ +package com.programmers.vouchermanagement.properties; + +public class Resources { + private String path; + private String buildPath; + + public String getPath() { + return path; + } + + public String getBuildPath() { + return buildPath; + } + + public void setPath(String path) { + this.path = path; + } + + public void setBuildPath(String buildPath) { + this.buildPath = buildPath; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java index e46658bc1f..783af8df55 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java @@ -2,11 +2,13 @@ import java.util.*; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; @Repository +@Profile("dev") public class InMemoryVoucherRepository implements VoucherRepository { private final Map vouchers; diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml new file mode 100644 index 0000000000..b0a42c3cf9 --- /dev/null +++ b/src/main/resources/application-dev.yaml @@ -0,0 +1,9 @@ +file: + resources: + path: /src/main/resources/ + build-path: /build/resources/main/ + + domains: + customer: + file-name: blacklist.csv + diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml new file mode 100644 index 0000000000..325db3b47b --- /dev/null +++ b/src/main/resources/application-prod.yaml @@ -0,0 +1,11 @@ +file: + resources: + path: /src/main/resources/ + build-path: /build/resources/main/ + + domains: + customer: + file-name: blacklist.csv + + voucher: + file-name: voucher.json From a895dcbbac25a75a9b343a65a7b57d1c99f13c46 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 23:40:03 +0900 Subject: [PATCH 067/383] chore: remove application.properties --- src/main/resources/application.properties | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/main/resources/application.properties diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789179..0000000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - From 4e994ca9025d2ae28a3fa9947c1cf612bb623686 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 19 Oct 2023 23:56:06 +0900 Subject: [PATCH 068/383] enhance: apply application properties to file path for corresponding profiles --- .../VoucherManagementApplication.java | 2 +- .../consoleapp/runner/ConsoleAppRunner.java | 1 + .../customer/repository/FileCustomerRepository.java | 7 ++++++- .../voucher/repository/FileVoucherRepository.java | 12 ++++++++---- src/main/resources/application-dev.yaml | 4 ++-- src/main/resources/application-prod.yaml | 4 ++-- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java index e287c9046e..75485f0977 100644 --- a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java +++ b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java @@ -8,7 +8,7 @@ public class VoucherManagementApplication { public static void main(String[] args) { var application = new SpringApplication(VoucherManagementApplication.class); - application.setAdditionalProfiles("dev"); + application.setAdditionalProfiles("prod"); application.run(args); } diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java index d8ca0144f9..fe9e201410 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java @@ -6,6 +6,7 @@ import org.springframework.stereotype.Component; import com.programmers.vouchermanagement.consoleapp.menu.MenuHandler; +import com.programmers.vouchermanagement.properties.AppProperties; @Component public class ConsoleAppRunner implements ApplicationRunner { diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index 65a8cd15cd..9ce52e4481 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -9,16 +9,21 @@ import java.util.Map; import java.util.UUID; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.properties.AppProperties; @Repository +@Profile({"dev", "prod"}) public class FileCustomerRepository implements CustomerRepository { private static final String BLACKLIST_FILE_PATH = "src/main/resources/blacklist.csv"; + private final String filePath; private final Map customers; - public FileCustomerRepository() { + public FileCustomerRepository(AppProperties appProperties) { + this.filePath = appProperties.getResources().getPath() + appProperties.getDomains().get("customer.file-name"); this.customers = new HashMap<>(); loadBlacklist(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index e3b70779a3..1ab0d7f534 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import com.fasterxml.jackson.databind.ObjectMapper; +import com.programmers.vouchermanagement.properties.AppProperties; import com.programmers.vouchermanagement.voucher.domain.FixedAmountVoucher; import com.programmers.vouchermanagement.voucher.domain.PercentVoucher; import com.programmers.vouchermanagement.voucher.domain.Voucher; @@ -17,13 +18,16 @@ @Repository @Profile("prod") public class FileVoucherRepository implements VoucherRepository { - private static final String FILE_PATH = "src/main/resources/voucher.json"; +// private static final String FILE_PATH="src/main/resources/voucher.json"; private final ObjectMapper objectMapper = new ObjectMapper(); private final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; + private final String filePath; private Map vouchers; - public FileVoucherRepository() { + public FileVoucherRepository(AppProperties appProperties) { + this.filePath = appProperties.getResources().getPath() + appProperties.getDomains().get("voucher.file-name"); + System.out.println(filePath); this.vouchers = new HashMap<>(); loadVouchers(); } @@ -41,7 +45,7 @@ public List findAll() { private void loadVouchers() { try { - File file = new File(FILE_PATH); + File file = new File(filePath); Map[] voucherObjects = objectMapper.readValue(file, Map[].class); vouchers = objectsToVouchers(voucherObjects); } catch (IOException e) { @@ -71,7 +75,7 @@ private Voucher objectToVoucher(Map voucherObject) { } public void saveFile() { - try (FileWriter fileWriter = new FileWriter(FILE_PATH)) { + try (FileWriter fileWriter = new FileWriter(filePath)) { List> voucherObjects = new ArrayList<>(); if (!vouchers.isEmpty()) { vouchers.values().forEach(voucher -> { diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index b0a42c3cf9..d79aa9c10f 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -1,7 +1,7 @@ file: resources: - path: /src/main/resources/ - build-path: /build/resources/main/ + path: src/main/resources/ + build-path: build/resources/main/ domains: customer: diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml index 325db3b47b..c21b2d66c5 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application-prod.yaml @@ -1,7 +1,7 @@ file: resources: - path: /src/main/resources/ - build-path: /build/resources/main/ + path: src/main/resources/ + build-path: build/resources/main/ domains: customer: From 2a7934e66967dae445c45fe8ef44ceba3807ae2b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 22 Oct 2023 19:02:12 +0900 Subject: [PATCH 069/383] fix: fix feature loading data from json file that return Empty Map --- .../voucher/repository/FileVoucherRepository.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 1ab0d7f534..d9911d64df 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -18,18 +18,17 @@ @Repository @Profile("prod") public class FileVoucherRepository implements VoucherRepository { -// private static final String FILE_PATH="src/main/resources/voucher.json"; private final ObjectMapper objectMapper = new ObjectMapper(); private final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; private final String filePath; - private Map vouchers; + private final Map vouchers; public FileVoucherRepository(AppProperties appProperties) { this.filePath = appProperties.getResources().getPath() + appProperties.getDomains().get("voucher.file-name"); System.out.println(filePath); this.vouchers = new HashMap<>(); - loadVouchers(); + loadFile(); } @Override @@ -43,23 +42,21 @@ public List findAll() { return vouchers.values().stream().toList(); } - private void loadVouchers() { + private void loadFile() { try { File file = new File(filePath); Map[] voucherObjects = objectMapper.readValue(file, Map[].class); - vouchers = objectsToVouchers(voucherObjects); + loadVouchers(voucherObjects); } catch (IOException e) { throw new RuntimeException(e); } } - private Map objectsToVouchers(Map[] voucherObjects) { - Map vouchersFromJSON = new HashMap<>(); + private void loadVouchers(Map[] voucherObjects) { Arrays.stream(voucherObjects).forEach(voucherObject -> { Voucher voucher = objectToVoucher(voucherObject); vouchers.put(voucher.getVoucherId(), voucher); }); - return vouchersFromJSON; } private Voucher objectToVoucher(Map voucherObject) { From 352ca7424c6c92337e7fb709bc9b171df0800308 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 22 Oct 2023 19:44:54 +0900 Subject: [PATCH 070/383] chore: add some gradle files to ignore to .gitignore --- .gitignore | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.gitignore b/.gitignore index 549e00a2a9..1bd5e9e555 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,35 @@ build/ ### VS Code ### .vscode/ + +# Created by https://www.toptal.com/developers/gitignore/api/gradle +# Edit at https://www.toptal.com/developers/gitignore?templates=gradle + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle Patch ### +# Java heap dump +*.hprof + +# End of https://www.toptal.com/developers/gitignore/api/gradle \ No newline at end of file From 56422f437a9f85aed86adc260f46c9e97e8fd62d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 22 Oct 2023 19:45:09 +0900 Subject: [PATCH 071/383] chore: gradle init --- build.gradle | 43 ++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 249 +++++++++++++++++++++++ gradlew.bat | 92 +++++++++ settings.gradle | 5 + 6 files changed, 396 insertions(+) create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..34586bb01f --- /dev/null +++ b/build.gradle @@ -0,0 +1,43 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id 'java-library' + id 'maven-publish' +} + +repositories { + mavenLocal() + maven { + url = uri('https://repo.maven.apache.org/maven2/') + } +} + +dependencies { + api 'org.springframework.boot:spring-boot-starter:3.1.4' + api 'com.fasterxml.jackson.core:jackson-databind:2.15.2' + api 'org.beryx:text-io:3.4.1' + testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' +} + +group = 'com.programmers' +version = '0.0.1-SNAPSHOT' +description = 'voucherManagement' +java.sourceCompatibility = JavaVersion.VERSION_17 + +publishing { + publications { + maven(MavenPublication) { + from(components.java) + } + } +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +tasks.withType(Javadoc) { + options.encoding = 'UTF-8' +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7f93135c49b765f8051ef9d0a6055ff8e46073d8 GIT binary patch literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..ac72c34e8a --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000000..0adc8e1a53 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original 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 POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# 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 ;; #( + MSYS* | 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 + if ! command -v java >/dev/null 2>&1 + then + 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 +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# 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"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000..93e3f59f13 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@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=. +@rem This is normally unused +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% equ 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% equ 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! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000000..9d318df298 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'voucherManangement' From 900efa120e2894db87a776491c9101f751edc5b8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 22 Oct 2023 19:45:38 +0900 Subject: [PATCH 072/383] chore: remove maven files --- .mvn/wrapper/maven-wrapper.jar | Bin 62547 -> 0 bytes .mvn/wrapper/maven-wrapper.properties | 2 - mvnw | 308 -------------------------- mvnw.cmd | 205 ----------------- pom.xml | 53 ----- 5 files changed, 568 deletions(-) delete mode 100644 .mvn/wrapper/maven-wrapper.jar delete mode 100644 .mvn/wrapper/maven-wrapper.properties delete mode 100644 mvnw delete mode 100644 mvnw.cmd delete mode 100644 pom.xml diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index cb28b0e37c7d206feb564310fdeec0927af4123a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62547 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 A?*IS* diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 5f0536eb74..0000000000 --- a/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/mvnw b/mvnw deleted file mode 100644 index 66df285428..0000000000 --- a/mvnw +++ /dev/null @@ -1,308 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.2.0 -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "$(uname)" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME - else - JAVA_HOME="/Library/Java/Home"; export JAVA_HOME - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=$(java-config --jre-home) - fi -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --unix "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --unix "$CLASSPATH") -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && - JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="$(which javac)" - if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=$(which readlink) - if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then - if $darwin ; then - javaHome="$(dirname "\"$javaExecutable\"")" - javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" - else - javaExecutable="$(readlink -f "\"$javaExecutable\"")" - fi - javaHome="$(dirname "\"$javaExecutable\"")" - javaHome=$(expr "$javaHome" : '\(.*\)/bin') - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - 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 - else - JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=$(cd "$wdir/.." || exit 1; pwd) - fi - # end of workaround - done - printf '%s' "$(cd "$basedir" || exit 1; pwd)" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - # Remove \r in case we run on Windows within Git Bash - # and check out the repository with auto CRLF management - # enabled. Otherwise, we may read lines that are delimited with - # \r\n and produce $'-Xarg\r' rather than -Xarg due to word - # splitting rules. - tr -s '\r\n' ' ' < "$1" - fi -} - -log() { - if [ "$MVNW_VERBOSE" = true ]; then - printf '%s\n' "$1" - fi -} - -BASE_DIR=$(find_maven_basedir "$(dirname "$0")") -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR -log "$MAVEN_PROJECTBASEDIR" - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" -if [ -r "$wrapperJarPath" ]; then - log "Found $wrapperJarPath" -else - log "Couldn't find $wrapperJarPath, downloading it ..." - - if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - fi - while IFS="=" read -r key value; do - # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) - safeValue=$(echo "$value" | tr -d '\r') - case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; - esac - done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" - log "Downloading from: $wrapperUrl" - - if $cygwin; then - wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") - fi - - if command -v wget > /dev/null; then - log "Found wget ... using wget" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - log "Found curl ... using curl" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - fi - else - log "Falling back to using Java to download" - javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaSource=$(cygpath --path --windows "$javaSource") - javaClass=$(cygpath --path --windows "$javaClass") - fi - if [ -e "$javaSource" ]; then - if [ ! -e "$javaClass" ]; then - log " - Compiling MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/javac" "$javaSource") - fi - if [ -e "$javaClass" ]; then - log " - Running MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -# If specified, validate the SHA-256 sum of the Maven wrapper jar file -wrapperSha256Sum="" -while IFS="=" read -r key value; do - case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; - esac -done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" -if [ -n "$wrapperSha256Sum" ]; then - wrapperSha256Result=false - if command -v sha256sum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then - wrapperSha256Result=true - fi - elif command -v shasum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then - wrapperSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." - echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." - exit 1 - fi - if [ $wrapperSha256Result = false ]; then - echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 - echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 - echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 - exit 1 - fi -fi - -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --windows "$CLASSPATH") - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -# shellcheck disable=SC2086 # safe args -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd deleted file mode 100644 index 95ba6f54ac..0000000000 --- a/mvnw.cmd +++ /dev/null @@ -1,205 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. 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, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 741cc758e0..0000000000 --- a/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.1.4 - - - com.programmers - voucherManangement - 0.0.1-SNAPSHOT - voucherManagement - voucherManagement - - 17 - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - com.fasterxml.jackson.core - jackson-databind - 2.15.2 - - - - org.beryx - text-io - 3.4.1 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - From 128dd344683135a1ad5b1c014974792370456102 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 23 Oct 2023 09:41:29 +0900 Subject: [PATCH 073/383] chore: add gradle test task --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 34586bb01f..d1c03979c3 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,10 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' } +test { + useJUnitPlatform() +} + group = 'com.programmers' version = '0.0.1-SNAPSHOT' description = 'voucherManagement' From f258fcf71b4eda7eeb69debe74f4904f3b4cb76a Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 10:45:40 +0900 Subject: [PATCH 074/383] chore: remove maven publishing plug-in --- build.gradle | 12 +----------- .../VoucherManagementApplicationTests.java | 13 ------------- 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 src/test/java/com/programmers/vouchermanagement/VoucherManagementApplicationTests.java diff --git a/build.gradle b/build.gradle index d1c03979c3..42743f3b2b 100644 --- a/build.gradle +++ b/build.gradle @@ -4,11 +4,9 @@ plugins { id 'java-library' - id 'maven-publish' } repositories { - mavenLocal() maven { url = uri('https://repo.maven.apache.org/maven2/') } @@ -30,18 +28,10 @@ version = '0.0.1-SNAPSHOT' description = 'voucherManagement' java.sourceCompatibility = JavaVersion.VERSION_17 -publishing { - publications { - maven(MavenPublication) { - from(components.java) - } - } -} - tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } tasks.withType(Javadoc) { options.encoding = 'UTF-8' -} \ No newline at end of file +} diff --git a/src/test/java/com/programmers/vouchermanagement/VoucherManagementApplicationTests.java b/src/test/java/com/programmers/vouchermanagement/VoucherManagementApplicationTests.java deleted file mode 100644 index 85414204ad..0000000000 --- a/src/test/java/com/programmers/vouchermanagement/VoucherManagementApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.programmers.vouchermanagement; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class VoucherManagementApplicationTests { - - @Test - void contextLoads() { - } - -} From 21fa609f79ae9f67583c491441e1c20a067b0e94 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 10:54:14 +0900 Subject: [PATCH 075/383] refactor: specify hard-coded string to constant value --- .../customer/repository/FileCustomerRepository.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index 9ce52e4481..70698149f6 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; @@ -18,7 +19,7 @@ @Repository @Profile({"dev", "prod"}) public class FileCustomerRepository implements CustomerRepository { - private static final String BLACKLIST_FILE_PATH = "src/main/resources/blacklist.csv"; + private static final String COMMA_SEPARATOR = ", "; private final String filePath; private final Map customers; @@ -39,11 +40,11 @@ public List findBlackCustomers() { private void loadBlacklist() { List blacklist = new ArrayList<>(); - try (BufferedReader br = new BufferedReader(new FileReader(BLACKLIST_FILE_PATH))) { + try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { br.readLine(); // skip the first line String str; while ((str = br.readLine()) != null) { - String[] line = str.split(", "); + String[] line = str.split(COMMA_SEPARATOR); UUID blackCustomerId = UUID.fromString(line[0]); String name = line[1]; From 043afda5789e6a3ce8d7f7bea6e643cfddd407ad Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 11:05:34 +0900 Subject: [PATCH 076/383] enhance: log and handle IOException in FileCustomerRepository --- .../customer/repository/FileCustomerRepository.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index 70698149f6..85bce2612e 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -3,13 +3,15 @@ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; @@ -19,7 +21,10 @@ @Repository @Profile({"dev", "prod"}) public class FileCustomerRepository implements CustomerRepository { + private static final Logger logger = LoggerFactory.getLogger(FileCustomerRepository.class); private static final String COMMA_SEPARATOR = ", "; + private static final String IO_EXCEPTION_LOG_MESSAGE = "Error raised while reading blacklist"; + private final String filePath; private final Map customers; @@ -37,7 +42,7 @@ public List findBlackCustomers() { .toList(); } - private void loadBlacklist() { + private void loadBlacklist() throws UncheckedIOException { List blacklist = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { @@ -54,8 +59,8 @@ private void loadBlacklist() { blacklist.add(blackCustomer); } } catch (IOException e) { - e.printStackTrace(); - //TODO: add logger + logger.error(IO_EXCEPTION_LOG_MESSAGE, e); + throw new UncheckedIOException(e); } blacklist.forEach(blackCustomer -> customers.put(blackCustomer.getCustomerId(), blackCustomer)); From 701f82b4dd9f7f6f1ce298538cb204c6fe70970f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 23 Oct 2023 11:08:24 +0900 Subject: [PATCH 077/383] refactor: remove unnecessary printing --- .../voucher/repository/FileVoucherRepository.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index d9911d64df..a9a04e57fb 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -20,13 +20,11 @@ public class FileVoucherRepository implements VoucherRepository { private final ObjectMapper objectMapper = new ObjectMapper(); private final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; - private final String filePath; private final Map vouchers; public FileVoucherRepository(AppProperties appProperties) { this.filePath = appProperties.getResources().getPath() + appProperties.getDomains().get("voucher.file-name"); - System.out.println(filePath); this.vouchers = new HashMap<>(); loadFile(); } From c8764ce49b9c3bc89a10bbd9f38a732d107bd0e8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 23 Oct 2023 11:22:08 +0900 Subject: [PATCH 078/383] refactor: add name getter --- .../vouchermanagement/customer/domain/Customer.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 858682ad98..58e3b6cb51 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -24,5 +24,9 @@ public UUID getCustomerId() { public boolean isBlack() { return isBlack; } + + public String getName() { + return name; + } } From fe9a689ea240d9df0363a344b41671334c9dd184 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 23 Oct 2023 11:25:31 +0900 Subject: [PATCH 079/383] feat: add blacklist menu --- .../vouchermanagement/consoleapp/menu/Menu.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/Menu.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/Menu.java index 691cf3bc23..f585eea062 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/Menu.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/Menu.java @@ -7,6 +7,7 @@ public enum Menu { EXIT("exit"), CREATE("create"), LIST("list"), + BLACKLIST("blacklist"), INCORRECT_MENU("incorrect menu"); private final String menuName; @@ -15,10 +16,6 @@ public enum Menu { this.menuName = menuName; } - private boolean isMatching(String input) { - return Objects.equals(menuName, input); - } - //set static to tell that this method does not depend on a particular Menu value public static Menu findMenu(String input) { return Arrays.stream(Menu.values()) @@ -27,6 +24,10 @@ public static Menu findMenu(String input) { .orElse(INCORRECT_MENU); } + private boolean isMatching(String input) { + return Objects.equals(menuName, input); + } + public boolean isExit() { return this == Menu.EXIT; } From 627b88fc8d80d75437c24e26898ad622a6fff010 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 23 Oct 2023 11:26:50 +0900 Subject: [PATCH 080/383] feat: enable to read blacklist --- .../consoleapp/io/ConsoleManager.java | 19 ++++++++++++++++--- .../consoleapp/menu/MenuHandler.java | 16 ++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 9e99eb3790..7fd2eb5956 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,10 +1,10 @@ package com.programmers.vouchermanagement.consoleapp.io; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.consoleapp.menu.Menu; +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; - import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.springframework.stereotype.Component; @@ -21,6 +21,7 @@ public class ConsoleManager { Type **exit** to exit the program. Type **create** to create a new voucher. Type **list** to list all vouchers. + Type **blacklist** to list all customers in blacklist. """; private static final String CREATE_SELECTION_INSTRUCTION = """ Please select the type of voucher to create. @@ -72,10 +73,22 @@ public void printCreateResult(GeneralVoucherDTO voucherResponse) { textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.getVoucherId())); } - public void printReadAll(List voucherResponses) { + public void printReadAllVouchers(List voucherResponses) { voucherResponses.forEach(voucherResponse -> textIO.getTextTerminal().println(formatVoucherDTO(voucherResponse))); } + public void printReadBlacklist(List customerResponses) { + customerResponses.forEach(customerResponse -> textIO.getTextTerminal().println(formatCustomer(customerResponse))); + } + + private String formatCustomer(Customer customer) { + return """ + Customer ID : %s + Customer Name : %s + -------------------------""" + .formatted(customer.getCustomerId(), customer.getName()); + } + private String formatVoucherDTO(GeneralVoucherDTO generalVoucherDTO) { return """ Voucher ID : %s diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 8d356d2585..9fd87a5f83 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -1,10 +1,11 @@ package com.programmers.vouchermanagement.consoleapp.menu; import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; +import com.programmers.vouchermanagement.customer.controller.CustomerController; +import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.controller.VoucherController; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; - import org.springframework.stereotype.Component; import java.util.List; @@ -18,10 +19,12 @@ public class MenuHandler { private final ConsoleManager consoleManager; private final VoucherController voucherController; + private final CustomerController customerController; - public MenuHandler(ConsoleManager consoleManager, VoucherController voucherController) { + public MenuHandler(ConsoleManager consoleManager, VoucherController voucherController, CustomerController customerController) { this.consoleManager = consoleManager; this.voucherController = voucherController; + this.customerController = customerController; } // Options.. @@ -68,7 +71,12 @@ private void executeMenu(Menu menu) { } case LIST -> { List voucherResponses = voucherController.readAllVouchers(); - consoleManager.printReadAll(voucherResponses); + consoleManager.printReadAllVouchers(voucherResponses); + } + //TODO: customerDTO + case BLACKLIST -> { + List customerResponses = customerController.readBlacklist(); + consoleManager.printReadBlacklist(customerResponses); } } } From 6fb304c3c28a0ec76b6f2b2a4f881294971fafd6 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 23 Oct 2023 15:12:25 +0900 Subject: [PATCH 081/383] refactor: make voucher a concrete class depending on voucherType in which has logics --- .../voucher/domain/FixedAmountVoucher.java | 44 --------------- .../voucher/domain/PercentVoucher.java | 44 --------------- .../voucher/domain/Voucher.java | 30 ++++++++-- .../voucher/domain/VoucherType.java | 55 ++++++++++++++++++- 4 files changed, 77 insertions(+), 96 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java deleted file mode 100644 index 85bc4ada64..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/FixedAmountVoucher.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.programmers.vouchermanagement.voucher.domain; - -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; - -import java.util.UUID; - -public class FixedAmountVoucher implements Voucher { - private static final String INVALID_DISCOUNT_INPUT_MESSAGE = - "Input should be a number greater than 0"; - private final UUID voucherID; - private final long discountAmount; - - public FixedAmountVoucher(UUID voucherID, long discountAmount) { - validateDiscountAmount(discountAmount); - this.voucherID = voucherID; - this.discountAmount = discountAmount; - } - - @Override - public UUID getVoucherId() { - return voucherID; - } - - @Override - public long getDiscountValue() { - return discountAmount; - } - - @Override - public long discount(long priceBeforeDiscount) { - return priceBeforeDiscount - discountAmount; - } - - @Override - public GeneralVoucherDTO toVoucherDTO() { - return new GeneralVoucherDTO(voucherID, discountAmount, VoucherType.FIXED); - } - - private void validateDiscountAmount(long discountAmount) { - if (discountAmount <= 0) { - throw new IllegalArgumentException(INVALID_DISCOUNT_INPUT_MESSAGE); - } - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java deleted file mode 100644 index 88731ae3d9..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/PercentVoucher.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.programmers.vouchermanagement.voucher.domain; - -import java.util.UUID; - -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; - -public class PercentVoucher implements Voucher { - private static final String INVALID_DISCOUNT_INPUT_MESSAGE = - "Input should be a number greater than 0 and smaller than 100"; - private final UUID voucherID; - private final long discountPercent; - - public PercentVoucher(UUID voucherID, long discountPercent) { - validateDiscountPercent(discountPercent); - this.voucherID = voucherID; - this.discountPercent = discountPercent; - } - - @Override - public UUID getVoucherId() { - return voucherID; - } - - @Override - public long getDiscountValue() { - return discountPercent; - } - - @Override - public long discount(long priceBeforeDiscount) { - return (long) (priceBeforeDiscount * (1 - discountPercent / 100D)); - } - - @Override - public GeneralVoucherDTO toVoucherDTO() { - return new GeneralVoucherDTO(voucherID, discountPercent, VoucherType.PERCENT); - } - - private void validateDiscountPercent(long discountPercent) { - if (discountPercent <= 0 || discountPercent > 100) { - throw new IllegalArgumentException(INVALID_DISCOUNT_INPUT_MESSAGE); - } - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 974e9f9093..e92fdcca18 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -2,14 +2,34 @@ import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; +import java.math.BigDecimal; import java.util.UUID; -public interface Voucher { - UUID getVoucherId(); +public class Voucher { + private static final String INVALID_DISCOUNT_INPUT_MESSAGE = + "Input should be a number greater than 0 and smaller than 100"; + private final UUID voucherID; + private final BigDecimal discountValue; + private final VoucherType voucherType; - long getDiscountValue(); + public Voucher(UUID voucherID, VoucherType voucherType, BigDecimal discountValue) { + this.voucherID = voucherID; + this.voucherType = voucherType; + this.voucherType.validateDiscountValue(discountValue); + this.discountValue = discountValue; + } - long discount(long priceBeforeDiscount); + public UUID getVoucherId() { + return voucherID; + } - GeneralVoucherDTO toVoucherDTO(); + public BigDecimal getDiscountValue() { + return discountValue; + } + + public BigDecimal discount(BigDecimal priceBeforeDiscount) { + return voucherType.discount(discountValue, priceBeforeDiscount); + } + + ; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index 393e0bd6f0..7e7b9e9ac7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -1,17 +1,31 @@ package com.programmers.vouchermanagement.voucher.domain; +import javax.swing.plaf.PanelUI; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Arrays; import java.util.Objects; import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Consumer; public enum VoucherType { - FIXED("Fixed Amount"), - PERCENT("Percent"); + FIXED("Fixed Amount", getFixedBiFunction(), validateDiscountAmount()), + PERCENT("Percent", getPercentBiFunction(), validateDiscountPercent()); + + private static final String INVALID_DISCOUNT_AMOUNT_MESSAGE = + "Input should be a number greater than 0"; + private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = + "Input should be a number greater than 0 and smaller than 100"; private final String typeName; + private final BiFunction discountCalculator; + private final Consumer validator; - VoucherType(String typeName) { + VoucherType(String typeName, BiFunction discountCalculator, Consumer validator) { this.typeName = typeName; + this.discountCalculator = discountCalculator; + this.validator = validator; } //set static to tell that this method does not depend on a particular Menu value @@ -21,6 +35,41 @@ public static Optional findCreateMenu(String input) { .findFirst(); } + private static BiFunction getFixedBiFunction() { + return (discountValue, priceBeforeDiscount) -> priceBeforeDiscount.subtract(discountValue); + } + + private static BiFunction getPercentBiFunction() { + return (discountValue, priceBeforeDiscount) -> { + BigDecimal discounted = BigDecimal.valueOf(100).subtract(discountValue); + return priceBeforeDiscount.multiply(discounted).divide(BigDecimal.valueOf(100), RoundingMode.FLOOR); + }; + } + + private static Consumer validateDiscountAmount() { + return (discountValue) -> { + if (discountValue.compareTo(BigDecimal.ZERO) <= 0) { + throw new IllegalArgumentException(INVALID_DISCOUNT_AMOUNT_MESSAGE); + } + }; + } + + private static Consumer validateDiscountPercent() { + return (discountValue) -> { + if (discountValue.compareTo(BigDecimal.ZERO) <= 0 || discountValue.compareTo(BigDecimal.valueOf(100)) > 0) { + throw new IllegalArgumentException(INVALID_DISCOUNT_PERCENT_MESSAGE); + } + }; + } + + public void validateDiscountValue(BigDecimal discountValue) { + validator.accept(discountValue); + } + + public BigDecimal discount(BigDecimal discountValue, BigDecimal priceBeforeDiscount) { + return discountCalculator.apply(discountValue, priceBeforeDiscount); + } + private boolean isMatching(String input) { return Objects.equals(this.name().toLowerCase(), input); } From 343a505c8d45a29e48b952188b9ad09c40f859f3 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 16:13:24 +0900 Subject: [PATCH 082/383] refactor: edit voucher DTOs to use record and apply throughout the project --- .../consoleapp/menu/MenuHandler.java | 10 +++--- .../voucher/controller/VoucherController.java | 10 +++--- ...uestDTO.java => CreateVoucherRequest.java} | 4 ++- .../voucher/dto/GeneralVoucherDTO.java | 33 ------------------- .../voucher/dto/VoucherResponse.java | 13 ++++++++ .../repository/FileVoucherRepository.java | 26 +++++++-------- .../voucher/service/VoucherService.java | 19 ++++------- 7 files changed, 44 insertions(+), 71 deletions(-) rename src/main/java/com/programmers/vouchermanagement/voucher/dto/{CreateVoucherRequestDTO.java => CreateVoucherRequest.java} (52%) delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/GeneralVoucherDTO.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 9fd87a5f83..11e5986379 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -4,8 +4,8 @@ import com.programmers.vouchermanagement.customer.controller.CustomerController; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.controller.VoucherController; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import org.springframework.stereotype.Component; import java.util.List; @@ -65,12 +65,12 @@ private void executeMenu(Menu menu) { case EXIT -> consoleManager.printExit(); case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { - CreateVoucherRequestDTO createVoucherRequestDTO = consoleManager.instructCreate(); - GeneralVoucherDTO voucherResponse = voucherController.create(createVoucherRequestDTO); + CreateVoucherRequest createVoucherRequest = consoleManager.instructCreate(); + VoucherResponse voucherResponse = voucherController.create(createVoucherRequest); consoleManager.printCreateResult(voucherResponse); } case LIST -> { - List voucherResponses = voucherController.readAllVouchers(); + List voucherResponses = voucherController.readAllVouchers(); consoleManager.printReadAllVouchers(voucherResponses); } //TODO: customerDTO diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 905176ea7c..3f1c61e697 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -4,8 +4,8 @@ import java.util.List; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; @Controller @@ -16,11 +16,11 @@ public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } - public GeneralVoucherDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { - return voucherService.create(createVoucherRequestDTO); + public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + return voucherService.create(createVoucherRequest); } - public List readAllVouchers() { + public List readAllVouchers() { return voucherService.readAllVouchers(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java similarity index 52% rename from src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java rename to src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java index 41d3e454f6..69f62dea49 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequestDTO.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java @@ -1,6 +1,8 @@ package com.programmers.vouchermanagement.voucher.dto; +import java.math.BigDecimal; + import com.programmers.vouchermanagement.voucher.domain.VoucherType; -public record CreateVoucherRequestDTO(VoucherType voucherType, long discountValue) { +public record CreateVoucherRequest(BigDecimal discountValue, VoucherType voucherType) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/GeneralVoucherDTO.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/GeneralVoucherDTO.java deleted file mode 100644 index 106b4c191f..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/GeneralVoucherDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.programmers.vouchermanagement.voucher.dto; - -import com.programmers.vouchermanagement.voucher.domain.VoucherType; - -import java.util.UUID; - -public class GeneralVoucherDTO { - private final UUID voucherId; - private final long discountValue; - private final VoucherType voucherType; - - public GeneralVoucherDTO(UUID voucherId, long discountValue, VoucherType voucherType) { - this.voucherId = voucherId; - this.discountValue = discountValue; - this.voucherType = voucherType; - } - - public UUID getVoucherId() { - return voucherId; - } - - public long getDiscountValue() { - return discountValue; - } - - public String getVoucherType() { - return voucherType.name().toLowerCase(); - } - - public String getVoucherTypeName() { - return voucherType.displayTypeName(); - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java new file mode 100644 index 0000000000..ce304a78e5 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -0,0 +1,13 @@ +package com.programmers.vouchermanagement.voucher.dto; + +import java.math.BigDecimal; +import java.util.UUID; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; + +public record VoucherResponse(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { + public static VoucherResponse from(Voucher voucher) { + return new VoucherResponse(voucher.getVoucherId(), voucher.getDiscountValue(), voucher.getVoucherType()); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index a9a04e57fb..0fb73c5b2f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -2,17 +2,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.programmers.vouchermanagement.properties.AppProperties; -import com.programmers.vouchermanagement.voucher.domain.FixedAmountVoucher; -import com.programmers.vouchermanagement.voucher.domain.PercentVoucher; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.math.BigDecimal; import java.util.*; @Repository @@ -58,15 +57,12 @@ private void loadVouchers(Map[] voucherObjects) { } private Voucher objectToVoucher(Map voucherObject) { - UUID voucherId = UUID.fromString((String) voucherObject.get("voucher_id")); - long discountValue = Long.parseLong(String.valueOf(voucherObject.get("discount_value"))); - String voucherTypeName = (String) voucherObject.get("voucher_type"); + UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get("voucher_id"))); + BigDecimal discountValue = new BigDecimal(String.valueOf(voucherObject.get("discount_value"))); + String voucherTypeName = String.valueOf(voucherObject.get("voucher_type")); VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) .orElseThrow(() -> new NoSuchElementException(INVALID_VOUCHER_TYPE_MESSAGE)); - return switch (voucherType) { - case FIXED -> new FixedAmountVoucher(voucherId, discountValue); - case PERCENT -> new PercentVoucher(voucherId, discountValue); - }; + return new Voucher(voucherId, discountValue, voucherType); } public void saveFile() { @@ -74,7 +70,7 @@ public void saveFile() { List> voucherObjects = new ArrayList<>(); if (!vouchers.isEmpty()) { vouchers.values().forEach(voucher -> { - HashMap voucherObject = voucherToObject(voucher.toVoucherDTO()); + HashMap voucherObject = voucherToObject(VoucherResponse.from(voucher)); voucherObjects.add(voucherObject); }); } @@ -86,11 +82,11 @@ public void saveFile() { } } - private HashMap voucherToObject(GeneralVoucherDTO generalVoucherDTO) { + private HashMap voucherToObject(VoucherResponse voucherResponse) { HashMap voucherObject = new HashMap<>(); - voucherObject.put("voucher_id", generalVoucherDTO.getVoucherId().toString()); - voucherObject.put("discount_value", generalVoucherDTO.getDiscountValue()); - voucherObject.put("voucher_type", generalVoucherDTO.getVoucherType()); + voucherObject.put("voucher_id", voucherResponse.voucherId().toString()); + voucherObject.put("discount_value", voucherResponse.discountValue().toString()); + voucherObject.put("voucher_type", voucherResponse.voucherType().name()); return voucherObject; } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index e3f2a4c78a..3ca6d474d5 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,10 +1,8 @@ package com.programmers.vouchermanagement.voucher.service; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.domain.FixedAmountVoucher; -import com.programmers.vouchermanagement.voucher.domain.PercentVoucher; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; @@ -26,23 +24,20 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public GeneralVoucherDTO create(CreateVoucherRequestDTO createVoucherRequestDTO) { - Voucher voucher = switch (createVoucherRequestDTO.voucherType()) { - case FIXED -> new FixedAmountVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountValue()); - case PERCENT -> new PercentVoucher(UUID.randomUUID(), createVoucherRequestDTO.discountValue()); - }; + public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType()); voucherRepository.save(voucher); - return voucher.toVoucherDTO(); + return VoucherResponse.from(voucher); } - public List readAllVouchers() { + public List readAllVouchers() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { throw new NoSuchElementException(VOUCHER_NOT_FOUND_MESSAGE); } return vouchers.stream() - .map(Voucher::toVoucherDTO) + .map(VoucherResponse::from) .toList(); } } From 07bf069b431296265e84c449c5b1b8aa052ee09c Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 16:13:52 +0900 Subject: [PATCH 083/383] refactor: add VoucherType getter --- .../vouchermanagement/voucher/domain/Voucher.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index e92fdcca18..d8e10980d4 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -1,32 +1,34 @@ package com.programmers.vouchermanagement.voucher.domain; -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; - import java.math.BigDecimal; import java.util.UUID; public class Voucher { private static final String INVALID_DISCOUNT_INPUT_MESSAGE = "Input should be a number greater than 0 and smaller than 100"; - private final UUID voucherID; + private final UUID voucherId; private final BigDecimal discountValue; private final VoucherType voucherType; - public Voucher(UUID voucherID, VoucherType voucherType, BigDecimal discountValue) { - this.voucherID = voucherID; + public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { + this.voucherId = voucherId; this.voucherType = voucherType; this.voucherType.validateDiscountValue(discountValue); this.discountValue = discountValue; } public UUID getVoucherId() { - return voucherID; + return voucherId; } public BigDecimal getDiscountValue() { return discountValue; } + public VoucherType getVoucherType() { + return voucherType; + } + public BigDecimal discount(BigDecimal priceBeforeDiscount) { return voucherType.discount(discountValue, priceBeforeDiscount); } From eb88fe47429fcfe45c7999ff05e93272c6cf05ec Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 16:17:14 +0900 Subject: [PATCH 084/383] feat: add isPercent teller --- .../vouchermanagement/voucher/domain/VoucherType.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index 7e7b9e9ac7..01a01abe6b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -1,6 +1,5 @@ package com.programmers.vouchermanagement.voucher.domain; -import javax.swing.plaf.PanelUI; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Arrays; @@ -74,6 +73,10 @@ private boolean isMatching(String input) { return Objects.equals(this.name().toLowerCase(), input); } + public boolean isPercent() { + return this == PERCENT; + } + public String displayTypeName() { return typeName; } From d153bb642b61b743b4718510e8c96a36c0bdbd20 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 16:17:47 +0900 Subject: [PATCH 085/383] refactor: apply changes of DTOs and BigDecimal --- .../consoleapp/io/ConsoleManager.java | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 7fd2eb5956..53d99f309e 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,17 +1,19 @@ package com.programmers.vouchermanagement.consoleapp.io; -import com.programmers.vouchermanagement.consoleapp.menu.Menu; -import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequestDTO; -import com.programmers.vouchermanagement.voucher.dto.GeneralVoucherDTO; +import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; + +import java.math.BigDecimal; +import java.util.List; + import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.springframework.stereotype.Component; -import java.util.List; - -import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; +import com.programmers.vouchermanagement.consoleapp.menu.Menu; +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; @Component public class ConsoleManager { @@ -58,22 +60,24 @@ public Menu selectMenu() { return Menu.findMenu(input); } - public CreateVoucherRequestDTO instructCreate() { + public CreateVoucherRequest instructCreate() { String createMenu = textIO.newStringInputReader() .read(CREATE_SELECTION_INSTRUCTION); VoucherType voucherType = VoucherType.findCreateMenu(createMenu) .orElseThrow(() -> new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE)); - long discountValue = textIO.newLongInputReader() + String discountValueInput = textIO.newStringInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); - return new CreateVoucherRequestDTO(voucherType, discountValue); + + BigDecimal discountValue = new BigDecimal(discountValueInput); + return new CreateVoucherRequest(discountValue, voucherType); } - public void printCreateResult(GeneralVoucherDTO voucherResponse) { - textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.getVoucherId())); + public void printCreateResult(VoucherResponse voucherResponse) { + textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.voucherId())); } - public void printReadAllVouchers(List voucherResponses) { + public void printReadAllVouchers(List voucherResponses) { voucherResponses.forEach(voucherResponse -> textIO.getTextTerminal().println(formatVoucherDTO(voucherResponse))); } @@ -89,15 +93,16 @@ private String formatCustomer(Customer customer) { .formatted(customer.getCustomerId(), customer.getName()); } - private String formatVoucherDTO(GeneralVoucherDTO generalVoucherDTO) { + private String formatVoucherDTO(VoucherResponse voucherResponse) { return """ Voucher ID : %s Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------""" - .formatted(generalVoucherDTO.getVoucherId(), - generalVoucherDTO.getVoucherTypeName(), - generalVoucherDTO.getDiscountValue()); + .formatted(voucherResponse.voucherId(), + voucherResponse.voucherType().displayTypeName(), + voucherResponse.discountValue() + + (voucherResponse.voucherType().isPercent() ? " %" : "")); } public void printExit() { From d2b04186f0daa836d4cae6b6cc3ed5252c4f7008 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 16:19:12 +0900 Subject: [PATCH 086/383] refactor: remove unnecessary message --- .../programmers/vouchermanagement/voucher/domain/Voucher.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index d8e10980d4..f06c1b6252 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -4,8 +4,6 @@ import java.util.UUID; public class Voucher { - private static final String INVALID_DISCOUNT_INPUT_MESSAGE = - "Input should be a number greater than 0 and smaller than 100"; private final UUID voucherId; private final BigDecimal discountValue; private final VoucherType voucherType; @@ -32,6 +30,4 @@ public VoucherType getVoucherType() { public BigDecimal discount(BigDecimal priceBeforeDiscount) { return voucherType.discount(discountValue, priceBeforeDiscount); } - - ; } From ba8298bfeed57206c7312b89298ad8463e85ab63 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 23 Oct 2023 16:40:08 +0900 Subject: [PATCH 087/383] refactor: introduce constant --- .../consoleapp/io/ConsoleManager.java | 21 ++++++++++--------- .../customer/service/CustomerService.java | 3 ++- .../voucher/domain/VoucherType.java | 11 +++++----- .../repository/FileVoucherRepository.java | 20 +++++++++++------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 53d99f309e..3200e8ffd9 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,19 +1,18 @@ package com.programmers.vouchermanagement.consoleapp.io; -import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; - -import java.math.BigDecimal; -import java.util.List; - -import org.beryx.textio.TextIO; -import org.slf4j.Logger; -import org.springframework.stereotype.Component; - import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import org.beryx.textio.TextIO; +import org.slf4j.Logger; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.List; + +import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; @Component public class ConsoleManager { @@ -43,6 +42,8 @@ public class ConsoleManager { """; private static final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; + private static final String PERCENTAGE = " %"; + private static final String EMPTY = ""; //--- private final TextIO textIO; @@ -102,7 +103,7 @@ private String formatVoucherDTO(VoucherResponse voucherResponse) { .formatted(voucherResponse.voucherId(), voucherResponse.voucherType().displayTypeName(), voucherResponse.discountValue() + - (voucherResponse.voucherType().isPercent() ? " %" : "")); + (voucherResponse.voucherType().isPercent() ? PERCENTAGE : EMPTY)); } public void printExit() { diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 9b638b357f..625ef7b1fe 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -10,6 +10,7 @@ @Service public class CustomerService { + private static final String NO_BLACKLIST = "no blacklist"; private final CustomerRepository customerRepository; public CustomerService(CustomerRepository customerRepository) { @@ -19,7 +20,7 @@ public CustomerService(CustomerRepository customerRepository) { public List readBlacklist() { List blacklist = customerRepository.findBlackCustomers(); if (blacklist.isEmpty()) { - throw new NoSuchElementException("no blacklist"); + throw new NoSuchElementException(NO_BLACKLIST); } return blacklist; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index 01a01abe6b..b69dd7ba77 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -16,7 +16,8 @@ public enum VoucherType { "Input should be a number greater than 0"; private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = "Input should be a number greater than 0 and smaller than 100"; - + private static final int COMPARATOR_FLAG = 0; + private static final BigDecimal MAX_PERCENT = BigDecimal.valueOf(100); private final String typeName; private final BiFunction discountCalculator; private final Consumer validator; @@ -40,14 +41,14 @@ private static BiFunction getFixedBiFunction private static BiFunction getPercentBiFunction() { return (discountValue, priceBeforeDiscount) -> { - BigDecimal discounted = BigDecimal.valueOf(100).subtract(discountValue); - return priceBeforeDiscount.multiply(discounted).divide(BigDecimal.valueOf(100), RoundingMode.FLOOR); + BigDecimal discounted = MAX_PERCENT.subtract(discountValue); + return priceBeforeDiscount.multiply(discounted).divide(MAX_PERCENT, RoundingMode.FLOOR); }; } private static Consumer validateDiscountAmount() { return (discountValue) -> { - if (discountValue.compareTo(BigDecimal.ZERO) <= 0) { + if (discountValue.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG) { throw new IllegalArgumentException(INVALID_DISCOUNT_AMOUNT_MESSAGE); } }; @@ -55,7 +56,7 @@ private static Consumer validateDiscountAmount() { private static Consumer validateDiscountPercent() { return (discountValue) -> { - if (discountValue.compareTo(BigDecimal.ZERO) <= 0 || discountValue.compareTo(BigDecimal.valueOf(100)) > 0) { + if (discountValue.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG || discountValue.compareTo(MAX_PERCENT) > COMPARATOR_FLAG) { throw new IllegalArgumentException(INVALID_DISCOUNT_PERCENT_MESSAGE); } }; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 0fb73c5b2f..f90c87e278 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -17,8 +17,12 @@ @Repository @Profile("prod") public class FileVoucherRepository implements VoucherRepository { + private static final String VOUCHER_ID_KEY = "voucher_id"; + private static final String DISCOUNT_VALUE_KEY = "discount_value"; + private static final String VOUCHER_TYPE_KEY = "voucher_type"; + private static final String FILE_EXCEPTION = "Error raised while opening the file."; + private static final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; private final ObjectMapper objectMapper = new ObjectMapper(); - private final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; private final String filePath; private final Map vouchers; @@ -57,9 +61,9 @@ private void loadVouchers(Map[] voucherObjects) { } private Voucher objectToVoucher(Map voucherObject) { - UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get("voucher_id"))); - BigDecimal discountValue = new BigDecimal(String.valueOf(voucherObject.get("discount_value"))); - String voucherTypeName = String.valueOf(voucherObject.get("voucher_type")); + UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(VOUCHER_ID_KEY))); + BigDecimal discountValue = new BigDecimal(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); + String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) .orElseThrow(() -> new NoSuchElementException(INVALID_VOUCHER_TYPE_MESSAGE)); return new Voucher(voucherId, discountValue, voucherType); @@ -78,15 +82,15 @@ public void saveFile() { fileWriter.write(jsonStr); fileWriter.flush(); } catch (Exception e) { - throw new RuntimeException("File Exception"); + throw new RuntimeException(FILE_EXCEPTION); } } private HashMap voucherToObject(VoucherResponse voucherResponse) { HashMap voucherObject = new HashMap<>(); - voucherObject.put("voucher_id", voucherResponse.voucherId().toString()); - voucherObject.put("discount_value", voucherResponse.discountValue().toString()); - voucherObject.put("voucher_type", voucherResponse.voucherType().name()); + voucherObject.put(VOUCHER_ID_KEY, voucherResponse.voucherId().toString()); + voucherObject.put(DISCOUNT_VALUE_KEY, voucherResponse.discountValue().toString()); + voucherObject.put(VOUCHER_TYPE_KEY, voucherResponse.voucherType().name()); return voucherObject; } } From 4d3e86d937c49c0134757844ac0295acfb25e63f Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 17:06:40 +0900 Subject: [PATCH 088/383] chore: fix project name --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 9d318df298..015d9795e7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,4 +2,4 @@ * This file was generated by the Gradle 'init' task. */ -rootProject.name = 'voucherManangement' +rootProject.name = 'voucherManagement' From e3d5f9c08d2eeafeaea3a3e8c5d3ee39afdf2130 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 23 Oct 2023 17:07:28 +0900 Subject: [PATCH 089/383] chore: add spring boot to gradle plugin --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 42743f3b2b..2fabff13e4 100644 --- a/build.gradle +++ b/build.gradle @@ -4,8 +4,11 @@ plugins { id 'java-library' + id 'org.springframework.boot' version '3.1.4' } +apply plugin: 'io.spring.dependency-management' + repositories { maven { url = uri('https://repo.maven.apache.org/maven2/') From 62cdb553f3e33dc9c87a7ee4c2c71fb5831ae55e Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 10:29:32 +0900 Subject: [PATCH 090/383] comment: remove additional comments --- .../vouchermanagement/configuration/AppConfig.java | 12 ------------ .../consoleapp/menu/MenuHandler.java | 11 ++++++----- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java index fb1e732be6..bbcea60f67 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java @@ -1,24 +1,12 @@ package com.programmers.vouchermanagement.configuration; -import com.programmers.vouchermanagement.VoucherManagementApplication; import org.beryx.textio.TextIO; import org.beryx.textio.TextIoFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { - // Conversation: - // Injecting logger to where it would be used - // VS - // Static logger to be used in wherever willing to use - @Bean - public Logger logger() { - return LoggerFactory.getLogger(VoucherManagementApplication.class); - } - @Bean public TextIO textIO() { return TextIoFactory.getTextIO(); diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 11e5986379..97bdfc1e92 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -6,12 +6,17 @@ import com.programmers.vouchermanagement.voucher.controller.VoucherController; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.util.List; @Component public class MenuHandler { + private static final Logger logger = LoggerFactory.getLogger(MenuHandler.class); + //messages private static final String INCORRECT_MESSAGE = "This menu is not executable."; @@ -27,11 +32,6 @@ public MenuHandler(ConsoleManager consoleManager, VoucherController voucherContr this.customerController = customerController; } - // Options.. - // ConsoleAppRunner (recursive run) --> MenuHandler --> Menu - // ConsoleAppRunner --> Menu <-- MenuHandler - // ConsoleAppRunner --> Menu - public boolean handleMenu() { Menu menu = selectMenu(); @@ -54,6 +54,7 @@ private boolean isValidMenu(Menu menu) { } if (menu.isIncorrect()) { + logger.error(INCORRECT_MESSAGE); throw new IllegalArgumentException(INCORRECT_MESSAGE); } From 72fefad14a5182edf3b7f8f5bc5ac9247771fbb7 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 10:30:03 +0900 Subject: [PATCH 091/383] refactor: return empty list instead of throwing an exception --- .../customer/service/CustomerService.java | 4 ++-- .../voucher/service/VoucherService.java | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 625ef7b1fe..433edc23e3 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.customer.service; +import java.util.Collections; import java.util.List; -import java.util.NoSuchElementException; import org.springframework.stereotype.Service; @@ -20,7 +20,7 @@ public CustomerService(CustomerRepository customerRepository) { public List readBlacklist() { List blacklist = customerRepository.findBlackCustomers(); if (blacklist.isEmpty()) { - throw new NoSuchElementException(NO_BLACKLIST); + return Collections.emptyList(); } return blacklist; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 3ca6d474d5..927fa89902 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -7,17 +7,13 @@ import org.springframework.stereotype.Service; +import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; import java.util.UUID; @Service public class VoucherService { - //messages - private static final String VOUCHER_NOT_FOUND_MESSAGE = - "There is no voucher registered."; - //--- - private final VoucherRepository voucherRepository; public VoucherService(VoucherRepository voucherRepository) { @@ -34,8 +30,9 @@ public List readAllVouchers() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { - throw new NoSuchElementException(VOUCHER_NOT_FOUND_MESSAGE); + return Collections.emptyList(); } + return vouchers.stream() .map(VoucherResponse::from) .toList(); From 136e092d755afad05cc4824a20988d74f61a56bb Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 10:30:21 +0900 Subject: [PATCH 092/383] refactor: remove unused logic --- .../voucher/domain/VoucherType.java | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index b69dd7ba77..e2f485d780 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -9,43 +9,32 @@ import java.util.function.Consumer; public enum VoucherType { - FIXED("Fixed Amount", getFixedBiFunction(), validateDiscountAmount()), - PERCENT("Percent", getPercentBiFunction(), validateDiscountPercent()); + FIXED("Fixed Amount", validateDiscountAmount()), + PERCENT("Percent", validateDiscountPercent()); + //messages private static final String INVALID_DISCOUNT_AMOUNT_MESSAGE = "Input should be a number greater than 0"; private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = "Input should be a number greater than 0 and smaller than 100"; private static final int COMPARATOR_FLAG = 0; private static final BigDecimal MAX_PERCENT = BigDecimal.valueOf(100); + //--- + private final String typeName; - private final BiFunction discountCalculator; private final Consumer validator; - VoucherType(String typeName, BiFunction discountCalculator, Consumer validator) { + VoucherType(String typeName, Consumer validator) { this.typeName = typeName; - this.discountCalculator = discountCalculator; this.validator = validator; } - //set static to tell that this method does not depend on a particular Menu value public static Optional findCreateMenu(String input) { return Arrays.stream(VoucherType.values()) .filter(menu -> menu.isMatching(input)) .findFirst(); } - private static BiFunction getFixedBiFunction() { - return (discountValue, priceBeforeDiscount) -> priceBeforeDiscount.subtract(discountValue); - } - - private static BiFunction getPercentBiFunction() { - return (discountValue, priceBeforeDiscount) -> { - BigDecimal discounted = MAX_PERCENT.subtract(discountValue); - return priceBeforeDiscount.multiply(discounted).divide(MAX_PERCENT, RoundingMode.FLOOR); - }; - } - private static Consumer validateDiscountAmount() { return (discountValue) -> { if (discountValue.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG) { @@ -66,10 +55,6 @@ public void validateDiscountValue(BigDecimal discountValue) { validator.accept(discountValue); } - public BigDecimal discount(BigDecimal discountValue, BigDecimal priceBeforeDiscount) { - return discountCalculator.apply(discountValue, priceBeforeDiscount); - } - private boolean isMatching(String input) { return Objects.equals(this.name().toLowerCase(), input); } From f97f0d90ad94e545ea6986148a8f9e216afc2ebf Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 10:30:34 +0900 Subject: [PATCH 093/383] refactor: remove unused logic --- .../programmers/vouchermanagement/voucher/domain/Voucher.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index f06c1b6252..6ef27bd1c9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -26,8 +26,4 @@ public BigDecimal getDiscountValue() { public VoucherType getVoucherType() { return voucherType; } - - public BigDecimal discount(BigDecimal priceBeforeDiscount) { - return voucherType.discount(discountValue, priceBeforeDiscount); - } } From c51adaf58f8d51b12e17d3db4e9e04eb314f2730 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 10:31:22 +0900 Subject: [PATCH 094/383] refactor: use individual loggers --- .../consoleapp/io/ConsoleManager.java | 12 ++++--- .../consoleapp/runner/ConsoleAppRunner.java | 8 ++--- .../repository/FileVoucherRepository.java | 36 ++++++++++++++----- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 3200e8ffd9..a5f1025cb5 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -7,6 +7,7 @@ import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import org.beryx.textio.TextIO; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.math.BigDecimal; @@ -16,6 +17,7 @@ @Component public class ConsoleManager { + private static final Logger logger = LoggerFactory.getLogger(ConsoleManager.class); //messages private static final String MENU_SELECTION_INSTRUCTION = """ === Voucher Program === @@ -47,11 +49,9 @@ public class ConsoleManager { //--- private final TextIO textIO; - private final Logger logger; - public ConsoleManager(TextIO textIO, Logger logger) { + public ConsoleManager(TextIO textIO) { this.textIO = textIO; - this.logger = logger; } public Menu selectMenu() { @@ -65,7 +65,10 @@ public CreateVoucherRequest instructCreate() { String createMenu = textIO.newStringInputReader() .read(CREATE_SELECTION_INSTRUCTION); VoucherType voucherType = VoucherType.findCreateMenu(createMenu) - .orElseThrow(() -> new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE)); + .orElseThrow(() -> { + logger.error(INVALID_VOUCHER_TYPE_MESSAGE); + return new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE); + }); String discountValueInput = textIO.newStringInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); @@ -116,6 +119,5 @@ public void printIncorrectMenu() { public void printException(RuntimeException e) { textIO.getTextTerminal().println(e.getMessage()); - logger.error(e.getMessage()); } } diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java index fe9e201410..dbcee2b70d 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java @@ -1,21 +1,21 @@ package com.programmers.vouchermanagement.consoleapp.runner; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import com.programmers.vouchermanagement.consoleapp.menu.MenuHandler; -import com.programmers.vouchermanagement.properties.AppProperties; @Component public class ConsoleAppRunner implements ApplicationRunner { + private static final Logger logger = LoggerFactory.getLogger(ConsoleAppRunner.class); + private final MenuHandler menuHandler; - private final Logger logger; - public ConsoleAppRunner(MenuHandler menuHandler, Logger logger) { + public ConsoleAppRunner(MenuHandler menuHandler) { this.menuHandler = menuHandler; - this.logger = logger; } @Override diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index f90c87e278..7d58a667db 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -1,27 +1,44 @@ package com.programmers.vouchermanagement.voucher.repository; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + import com.fasterxml.jackson.databind.ObjectMapper; import com.programmers.vouchermanagement.properties.AppProperties; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Repository; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.math.BigDecimal; -import java.util.*; @Repository @Profile("prod") public class FileVoucherRepository implements VoucherRepository { + private static final Logger logger = LoggerFactory.getLogger(FileVoucherRepository.class); + + //constants private static final String VOUCHER_ID_KEY = "voucher_id"; private static final String DISCOUNT_VALUE_KEY = "discount_value"; private static final String VOUCHER_TYPE_KEY = "voucher_type"; private static final String FILE_EXCEPTION = "Error raised while opening the file."; + + //messages + private static final String IO_EXCEPTION_LOG_MESSAGE = "Error raised while reading vouchers"; private static final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; + private final ObjectMapper objectMapper = new ObjectMapper(); private final String filePath; private final Map vouchers; @@ -49,7 +66,8 @@ private void loadFile() { Map[] voucherObjects = objectMapper.readValue(file, Map[].class); loadVouchers(voucherObjects); } catch (IOException e) { - throw new RuntimeException(e); + logger.error(IO_EXCEPTION_LOG_MESSAGE); + throw new UncheckedIOException(e); } } From 45042149bf2bbe36b43cbfffaa4601d88cb0cb22 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 10:32:34 +0900 Subject: [PATCH 095/383] refactor: remove unnecessary throwing --- .../customer/repository/FileCustomerRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index 85bce2612e..c80bc07532 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -42,7 +42,7 @@ public List findBlackCustomers() { .toList(); } - private void loadBlacklist() throws UncheckedIOException { + private void loadBlacklist() { List blacklist = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { @@ -59,7 +59,7 @@ private void loadBlacklist() throws UncheckedIOException { blacklist.add(blackCustomer); } } catch (IOException e) { - logger.error(IO_EXCEPTION_LOG_MESSAGE, e); + logger.error(IO_EXCEPTION_LOG_MESSAGE); throw new UncheckedIOException(e); } From 664404de4eba27e55b1115e8885cbff90f8c27d3 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 10:59:31 +0900 Subject: [PATCH 096/383] refactor: validate discount value on creating CreateVoucherRequest --- .../consoleapp/io/ConsoleManager.java | 3 +- .../voucher/domain/Voucher.java | 1 - .../voucher/domain/VoucherType.java | 37 ++----------------- 3 files changed, 5 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index a5f1025cb5..220b7f8a6b 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -2,6 +2,7 @@ import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.util.Validator; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; @@ -72,8 +73,8 @@ public CreateVoucherRequest instructCreate() { String discountValueInput = textIO.newStringInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); - BigDecimal discountValue = new BigDecimal(discountValueInput); + Validator.validateDiscountValue(voucherType, discountValue); return new CreateVoucherRequest(discountValue, voucherType); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 6ef27bd1c9..104eba2138 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -11,7 +11,6 @@ public class Voucher { public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { this.voucherId = voucherId; this.voucherType = voucherType; - this.voucherType.validateDiscountValue(discountValue); this.discountValue = discountValue; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index e2f485d780..125d35c4b4 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -9,24 +9,13 @@ import java.util.function.Consumer; public enum VoucherType { - FIXED("Fixed Amount", validateDiscountAmount()), - PERCENT("Percent", validateDiscountPercent()); - - //messages - private static final String INVALID_DISCOUNT_AMOUNT_MESSAGE = - "Input should be a number greater than 0"; - private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = - "Input should be a number greater than 0 and smaller than 100"; - private static final int COMPARATOR_FLAG = 0; - private static final BigDecimal MAX_PERCENT = BigDecimal.valueOf(100); - //--- + FIXED("Fixed Amount"), + PERCENT("Percent"); private final String typeName; - private final Consumer validator; - VoucherType(String typeName, Consumer validator) { + VoucherType(String typeName) { this.typeName = typeName; - this.validator = validator; } public static Optional findCreateMenu(String input) { @@ -35,26 +24,6 @@ public static Optional findCreateMenu(String input) { .findFirst(); } - private static Consumer validateDiscountAmount() { - return (discountValue) -> { - if (discountValue.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG) { - throw new IllegalArgumentException(INVALID_DISCOUNT_AMOUNT_MESSAGE); - } - }; - } - - private static Consumer validateDiscountPercent() { - return (discountValue) -> { - if (discountValue.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG || discountValue.compareTo(MAX_PERCENT) > COMPARATOR_FLAG) { - throw new IllegalArgumentException(INVALID_DISCOUNT_PERCENT_MESSAGE); - } - }; - } - - public void validateDiscountValue(BigDecimal discountValue) { - validator.accept(discountValue); - } - private boolean isMatching(String input) { return Objects.equals(this.name().toLowerCase(), input); } From 8216c80c6b2bf2960428e05f4285da4f6924e258 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:29:02 +0900 Subject: [PATCH 097/383] style: rename file to start with error --- src/main/resources/logback-spring.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 248e05345f..2a17a4b164 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -11,7 +11,7 @@ DENY - logs/access-%d{yyyy-MM-dd}.log + logs/error-%d{yyyy-MM-dd}.log ${FILE_LOG_PATTERN} From 06e49c56015015fa19c7ba96f5547aa1216d6443 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:29:45 +0900 Subject: [PATCH 098/383] refactor: continue the program while logging error for incorrect menu --- .../vouchermanagement/consoleapp/menu/MenuHandler.java | 1 - .../consoleapp/runner/ConsoleAppRunner.java | 10 +--------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 97bdfc1e92..d22c2d8235 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -55,7 +55,6 @@ private boolean isValidMenu(Menu menu) { if (menu.isIncorrect()) { logger.error(INCORRECT_MESSAGE); - throw new IllegalArgumentException(INCORRECT_MESSAGE); } return true; diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java index dbcee2b70d..356a8dd074 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java @@ -1,7 +1,5 @@ package com.programmers.vouchermanagement.consoleapp.runner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @@ -10,8 +8,6 @@ @Component public class ConsoleAppRunner implements ApplicationRunner { - private static final Logger logger = LoggerFactory.getLogger(ConsoleAppRunner.class); - private final MenuHandler menuHandler; public ConsoleAppRunner(MenuHandler menuHandler) { @@ -22,11 +18,7 @@ public ConsoleAppRunner(MenuHandler menuHandler) { public void run(ApplicationArguments args) { boolean isRunning = true; while (isRunning) { - try { - isRunning = menuHandler.handleMenu(); - } catch (RuntimeException e) { - logger.error(e.getMessage()); - } + isRunning = menuHandler.handleMenu(); } } } From f6cf7929fe87fe73affabc3cdc24a55414e7ebfc Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:30:23 +0900 Subject: [PATCH 099/383] refactor: compare lower cases to make not case-sensitive --- .../vouchermanagement/voucher/domain/VoucherType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index 125d35c4b4..2e24051290 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -25,7 +25,7 @@ public static Optional findCreateMenu(String input) { } private boolean isMatching(String input) { - return Objects.equals(this.name().toLowerCase(), input); + return Objects.equals(this.name().toLowerCase(), input.toLowerCase()); } public boolean isPercent() { From 784c62e39264b2dca497b95d7c712503df9d1582 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:31:28 +0900 Subject: [PATCH 100/383] refactor: enable VoucherResponse to tell more information --- .../voucher/dto/VoucherResponse.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java index ce304a78e5..a8fe420d5d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -6,8 +6,34 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -public record VoucherResponse(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { +public class VoucherResponse { + private final UUID voucherId; + private final BigDecimal discountValue; + private final VoucherType voucherType; + + private VoucherResponse(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { + this.voucherId = voucherId; + this.discountValue = discountValue; + this.voucherType = voucherType; + } + public static VoucherResponse from(Voucher voucher) { return new VoucherResponse(voucher.getVoucherId(), voucher.getDiscountValue(), voucher.getVoucherType()); } + + public UUID getVoucherId() { + return voucherId; + } + + public BigDecimal getDiscountValue() { + return discountValue; + } + + public boolean isPercentVoucher() { + return voucherType.isPercent(); + } + + public String getVoucherTypeName() { + return voucherType.displayTypeName(); + } } From 97e025b4626393995b0a25e50921da985364f7e5 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:32:37 +0900 Subject: [PATCH 101/383] refactor: use domain object for mapping from the file --- .../repository/FileVoucherRepository.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 7d58a667db..068e63c90d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -22,7 +22,6 @@ import com.programmers.vouchermanagement.properties.AppProperties; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; @Repository @Profile("prod") @@ -83,7 +82,10 @@ private Voucher objectToVoucher(Map voucherObject) { BigDecimal discountValue = new BigDecimal(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) - .orElseThrow(() -> new NoSuchElementException(INVALID_VOUCHER_TYPE_MESSAGE)); + .orElseThrow(() -> { + logger.error(INVALID_VOUCHER_TYPE_MESSAGE); + return new NoSuchElementException(INVALID_VOUCHER_TYPE_MESSAGE); + }); return new Voucher(voucherId, discountValue, voucherType); } @@ -92,7 +94,7 @@ public void saveFile() { List> voucherObjects = new ArrayList<>(); if (!vouchers.isEmpty()) { vouchers.values().forEach(voucher -> { - HashMap voucherObject = voucherToObject(VoucherResponse.from(voucher)); + HashMap voucherObject = voucherToObject(voucher); voucherObjects.add(voucherObject); }); } @@ -104,11 +106,11 @@ public void saveFile() { } } - private HashMap voucherToObject(VoucherResponse voucherResponse) { + private HashMap voucherToObject(Voucher voucher) { HashMap voucherObject = new HashMap<>(); - voucherObject.put(VOUCHER_ID_KEY, voucherResponse.voucherId().toString()); - voucherObject.put(DISCOUNT_VALUE_KEY, voucherResponse.discountValue().toString()); - voucherObject.put(VOUCHER_TYPE_KEY, voucherResponse.voucherType().name()); + voucherObject.put(VOUCHER_ID_KEY, voucher.getVoucherId().toString()); + voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue().toString()); + voucherObject.put(VOUCHER_TYPE_KEY, voucher.getVoucherType().name()); return voucherObject; } } From 5bdf0fa9e8d69e06ad2bbd0f9512b40f3b43debd Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:36:41 +0900 Subject: [PATCH 102/383] refactor: apply change of VoucherResponse and add printing no content --- .../consoleapp/io/ConsoleManager.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 220b7f8a6b..de9bf91675 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,20 +1,21 @@ package com.programmers.vouchermanagement.consoleapp.io; +import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; + +import java.math.BigDecimal; +import java.util.List; + +import org.beryx.textio.TextIO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.util.Validator; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; -import org.beryx.textio.TextIO; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.math.BigDecimal; -import java.util.List; - -import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; @Component public class ConsoleManager { @@ -47,6 +48,7 @@ public class ConsoleManager { "Voucher type should be either fixed amount or percent discount voucher."; private static final String PERCENTAGE = " %"; private static final String EMPTY = ""; + private static final String NO_CONTENT = "There is no %s stored yet!"; //--- private final TextIO textIO; @@ -79,14 +81,20 @@ public CreateVoucherRequest instructCreate() { } public void printCreateResult(VoucherResponse voucherResponse) { - textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.voucherId())); + textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.getVoucherId())); } public void printReadAllVouchers(List voucherResponses) { + if (voucherResponses.isEmpty()) { + textIO.getTextTerminal().println(NO_CONTENT.formatted("voucher")); + } voucherResponses.forEach(voucherResponse -> textIO.getTextTerminal().println(formatVoucherDTO(voucherResponse))); } public void printReadBlacklist(List customerResponses) { + if (customerResponses.isEmpty()) { + textIO.getTextTerminal().println(NO_CONTENT.formatted("black customer")); + } customerResponses.forEach(customerResponse -> textIO.getTextTerminal().println(formatCustomer(customerResponse))); } @@ -104,10 +112,10 @@ private String formatVoucherDTO(VoucherResponse voucherResponse) { Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------""" - .formatted(voucherResponse.voucherId(), - voucherResponse.voucherType().displayTypeName(), - voucherResponse.discountValue() + - (voucherResponse.voucherType().isPercent() ? PERCENTAGE : EMPTY)); + .formatted(voucherResponse.getVoucherId(), + voucherResponse.getVoucherTypeName(), + voucherResponse.getDiscountValue() + + (voucherResponse.isPercentVoucher() ? PERCENTAGE : EMPTY)); } public void printExit() { From ba74b81d022b6f40bd7cdfb972c0805091aa83a6 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:37:01 +0900 Subject: [PATCH 103/383] refactor: remove unused import statements --- .../vouchermanagement/voucher/domain/VoucherType.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index 2e24051290..257a4c442d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -1,12 +1,8 @@ package com.programmers.vouchermanagement.voucher.domain; -import java.math.BigDecimal; -import java.math.RoundingMode; import java.util.Arrays; import java.util.Objects; import java.util.Optional; -import java.util.function.BiFunction; -import java.util.function.Consumer; public enum VoucherType { FIXED("Fixed Amount"), From b21b153a51cbd4be9c5daa34e383071c4a74d20c Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 24 Oct 2023 11:37:25 +0900 Subject: [PATCH 104/383] feat: add validator --- .../vouchermanagement/util/Validator.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/util/Validator.java diff --git a/src/main/java/com/programmers/vouchermanagement/util/Validator.java b/src/main/java/com/programmers/vouchermanagement/util/Validator.java new file mode 100644 index 0000000000..83cf951cc1 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/util/Validator.java @@ -0,0 +1,43 @@ +package com.programmers.vouchermanagement.util; + +import java.math.BigDecimal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.programmers.vouchermanagement.voucher.domain.VoucherType; + +public class Validator { + private static final Logger logger = LoggerFactory.getLogger(Validator.class); + + //constants + private static final int COMPARATOR_FLAG = 0; + private static final BigDecimal MAX_PERCENT = BigDecimal.valueOf(100); + + //messages + private static final String INVALID_DISCOUNT_AMOUNT_MESSAGE = + "Input should be a number greater than 0"; + private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = + "Input should be a number greater than 0 and smaller than 100"; + + public static void validateDiscountValue(VoucherType voucherType, BigDecimal discountValue) { + switch (voucherType) { + case FIXED -> validateDiscountAmount(discountValue); + case PERCENT -> validateDiscountPercent(discountValue); + } + } + + private static void validateDiscountAmount(BigDecimal discountAmount) { + if (discountAmount.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG) { + logger.error(INVALID_DISCOUNT_AMOUNT_MESSAGE); + throw new IllegalArgumentException(INVALID_DISCOUNT_AMOUNT_MESSAGE); + } + } + + private static void validateDiscountPercent(BigDecimal discountPercent) { + if (discountPercent.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG || discountPercent.compareTo(MAX_PERCENT) > COMPARATOR_FLAG) { + logger.error(INVALID_DISCOUNT_PERCENT_MESSAGE); + throw new IllegalArgumentException(INVALID_DISCOUNT_PERCENT_MESSAGE); + } + } +} From 4edeb71df2258c9203ace29fe984d2e2504a49f3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 25 Oct 2023 13:22:58 +0900 Subject: [PATCH 105/383] enhance: apply @ConstructorBinding at properties --- .../VoucherManagementApplication.java | 12 ++++---- .../repository/FileCustomerRepository.java | 21 +++++--------- .../properties/AppProperties.java | 29 ++----------------- .../vouchermanagement/properties/Domain.java | 4 +++ .../properties/Resources.java | 20 +------------ .../repository/FileVoucherRepository.java | 29 +++++++------------ 6 files changed, 34 insertions(+), 81 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/properties/Domain.java diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java index 75485f0977..dde3bdb2ad 100644 --- a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java +++ b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java @@ -2,14 +2,16 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; @SpringBootApplication +@ConfigurationPropertiesScan public class VoucherManagementApplication { - public static void main(String[] args) { - var application = new SpringApplication(VoucherManagementApplication.class); - application.setAdditionalProfiles("prod"); - application.run(args); - } + public static void main(String[] args) { + var application = new SpringApplication(VoucherManagementApplication.class); + application.setAdditionalProfiles("prod"); + application.run(args); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index c80bc07532..fd8157ec66 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -1,22 +1,17 @@ package com.programmers.vouchermanagement.customer.repository; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.properties.AppProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; -import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.properties.AppProperties; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.*; @Repository @Profile({"dev", "prod"}) @@ -29,7 +24,7 @@ public class FileCustomerRepository implements CustomerRepository { private final Map customers; public FileCustomerRepository(AppProperties appProperties) { - this.filePath = appProperties.getResources().getPath() + appProperties.getDomains().get("customer.file-name"); + this.filePath = appProperties.resources().path() + appProperties.domains().get("customer").fileName(); this.customers = new HashMap<>(); loadBlacklist(); } diff --git a/src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java b/src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java index 2615a00394..edd42aa8dc 100644 --- a/src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java +++ b/src/main/java/com/programmers/vouchermanagement/properties/AppProperties.java @@ -1,32 +1,9 @@ package com.programmers.vouchermanagement.properties; -import java.util.HashMap; -import java.util.Map; - import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "file") -@EnableConfigurationProperties -public class AppProperties { - private Resources resources; - private Map domains = new HashMap<>(); - public Resources getResources() { - return resources; - } - - public Map getDomains() { - return domains; - } - - public void setResources(Resources resources) { - this.resources = resources; - } +import java.util.Map; - public void setDomains(Map domains) { - this.domains = domains; - } +@ConfigurationProperties(prefix = "file") +public record AppProperties(Resources resources, Map domains) { } diff --git a/src/main/java/com/programmers/vouchermanagement/properties/Domain.java b/src/main/java/com/programmers/vouchermanagement/properties/Domain.java new file mode 100644 index 0000000000..e0c6981776 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/properties/Domain.java @@ -0,0 +1,4 @@ +package com.programmers.vouchermanagement.properties; + +public record Domain(String fileName) { +} diff --git a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java index b98cf44a02..4643c891c0 100644 --- a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java +++ b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java @@ -1,22 +1,4 @@ package com.programmers.vouchermanagement.properties; -public class Resources { - private String path; - private String buildPath; - - public String getPath() { - return path; - } - - public String getBuildPath() { - return buildPath; - } - - public void setPath(String path) { - this.path = path; - } - - public void setBuildPath(String buildPath) { - this.buildPath = buildPath; - } +public record Resources(String path, String buildPath) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 068e63c90d..9d7b7efbab 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -1,27 +1,20 @@ package com.programmers.vouchermanagement.voucher.repository; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.UUID; - +import com.fasterxml.jackson.databind.ObjectMapper; +import com.programmers.vouchermanagement.properties.AppProperties; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.programmers.vouchermanagement.properties.AppProperties; -import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.math.BigDecimal; +import java.util.*; @Repository @Profile("prod") @@ -43,7 +36,7 @@ public class FileVoucherRepository implements VoucherRepository { private final Map vouchers; public FileVoucherRepository(AppProperties appProperties) { - this.filePath = appProperties.getResources().getPath() + appProperties.getDomains().get("voucher.file-name"); + this.filePath = appProperties.resources().path() + appProperties.domains().get("voucher").fileName(); this.vouchers = new HashMap<>(); loadFile(); } From 9103530da98b967af4b2bafe72752ecce3cdfe38 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 25 Oct 2023 13:36:04 +0900 Subject: [PATCH 106/383] refactor: remove build path --- .../com/programmers/vouchermanagement/properties/Resources.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java index 4643c891c0..f6dc65373f 100644 --- a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java +++ b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java @@ -1,4 +1,4 @@ package com.programmers.vouchermanagement.properties; -public record Resources(String path, String buildPath) { +public record Resources(String path) { } From 8548a92a325b0e17fbd56fb5ddb3d2a0a420ad3b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 25 Oct 2023 13:36:04 +0900 Subject: [PATCH 107/383] refactor: remove build path --- .../com/programmers/vouchermanagement/properties/Resources.java | 2 +- src/main/resources/application-dev.yaml | 1 - src/main/resources/application-prod.yaml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java index 4643c891c0..f6dc65373f 100644 --- a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java +++ b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java @@ -1,4 +1,4 @@ package com.programmers.vouchermanagement.properties; -public record Resources(String path, String buildPath) { +public record Resources(String path) { } diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index d79aa9c10f..acb8d270fc 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -1,7 +1,6 @@ file: resources: path: src/main/resources/ - build-path: build/resources/main/ domains: customer: diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml index c21b2d66c5..f370d0c63d 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application-prod.yaml @@ -1,7 +1,6 @@ file: resources: path: src/main/resources/ - build-path: build/resources/main/ domains: customer: From 464303edd74ae4f450968402dc6344b6981ba40d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 25 Oct 2023 13:47:09 +0900 Subject: [PATCH 108/383] Revert "refactor: remove build path" This reverts commit 8548a92a325b0e17fbd56fb5ddb3d2a0a420ad3b. --- .../com/programmers/vouchermanagement/properties/Resources.java | 2 +- src/main/resources/application-dev.yaml | 1 + src/main/resources/application-prod.yaml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java index f6dc65373f..4643c891c0 100644 --- a/src/main/java/com/programmers/vouchermanagement/properties/Resources.java +++ b/src/main/java/com/programmers/vouchermanagement/properties/Resources.java @@ -1,4 +1,4 @@ package com.programmers.vouchermanagement.properties; -public record Resources(String path) { +public record Resources(String path, String buildPath) { } diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index acb8d270fc..d79aa9c10f 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -1,6 +1,7 @@ file: resources: path: src/main/resources/ + build-path: build/resources/main/ domains: customer: diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml index f370d0c63d..c21b2d66c5 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application-prod.yaml @@ -1,6 +1,7 @@ file: resources: path: src/main/resources/ + build-path: build/resources/main/ domains: customer: From c07b83a23074900ce177f8e508675cc1b210d186 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 02:19:02 +0900 Subject: [PATCH 109/383] chore: add jdbc dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 2fabff13e4..7ec7fbed63 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ dependencies { api 'org.springframework.boot:spring-boot-starter:3.1.4' api 'com.fasterxml.jackson.core:jackson-databind:2.15.2' api 'org.beryx:text-io:3.4.1' + implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.1.5' testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' } From 4cb0b579c42bd9775d5229f251df7aa82d3fb7f8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 02:19:31 +0900 Subject: [PATCH 110/383] chore: add Database schema --- src/main/resources/schema.sql | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/resources/schema.sql diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000000..0d38c30ed8 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,21 @@ +CREATE TABLE customers +( + id BINARY(16) PRIMARY KEY, + name varchar(20) NOT NULL, + CONSTRAINT name UNIQUE (name) +); + +CREATE TABLE vouchers +( + id BINARY(16) PRIMARY KEY, + type enum ('FIXED', 'PERCENT') NOT NULL, + discount_value varchar(50) NOT NULL, + created_at datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) +); + +CREATE TABLE voucher_own_info +( + id INT PRIMARY KEY AUTO_INCREMENT, + customer_id BINARY(16) NOT NULL REFERENCES customers (id) ON DELETE CASCADE, + voucher_id BINARY(16) NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE +); \ No newline at end of file From 1c849b18d6537b623ed53b9e4a0607b2f3f44888 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 02:19:31 +0900 Subject: [PATCH 111/383] chore: add Database schema --- src/main/resources/schema.sql | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/resources/schema.sql diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000000..f7bf44e84b --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,21 @@ +CREATE TABLE customers +( + id BINARY(16) PRIMARY KEY, + name varchar(20) NOT NULL, + CONSTRAINT name UNIQUE (name) +); + +CREATE TABLE vouchers +( + id BINARY(16) PRIMARY KEY, + type enum ('FIXED', 'PERCENT') NOT NULL, + discount_value varchar(50) NOT NULL, + created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) +); + +CREATE TABLE voucher_customer_own_info +( + id INT PRIMARY KEY AUTO_INCREMENT, + customer_id BINARY(16) NOT NULL REFERENCES customers (id) ON DELETE CASCADE, + voucher_id BINARY(16) NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE +); \ No newline at end of file From 1aa29fb396c4d1181b40c08b56a299d7eb918713 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 15:26:48 +0900 Subject: [PATCH 112/383] chore: add mysql-connector-java dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 7ec7fbed63..6d38cbe0d4 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,7 @@ dependencies { api 'com.fasterxml.jackson.core:jackson-databind:2.15.2' api 'org.beryx:text-io:3.4.1' implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.1.5' + runtimeOnly(implementation 'mysql:mysql-connector-java:8.0.33') testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' } From 4a2ea5d21f0f5d8cd7283e9475d10292daf08705 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 16:41:57 +0900 Subject: [PATCH 113/383] feat: implement JDBCVoucherRepository --- .../repository/JDBCVoucherRepository.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java new file mode 100644 index 0000000000..cf033b7b8b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java @@ -0,0 +1,73 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Primary; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.math.BigDecimal; +import java.nio.ByteBuffer; +import java.util.*; + +@Repository +@Primary +public class JDBCVoucherRepository implements VoucherRepository { + private static final Logger logger = LoggerFactory.getLogger(JDBCVoucherRepository.class); + private static final String INSERT_QUERY = "INSERT INTO test.vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discountValue)"; + private static final String FIND_BY_ID_QUERY = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; + private static final String FIND_ALL_QUERY = "SELECT * FROM test.vouchers"; + private static final RowMapper voucherRowMapper = (resultSet, i) -> { + UUID id = toUUID(resultSet.getBytes("id")); + BigDecimal discountValue = resultSet.getBigDecimal("discount_value"); + String voucherTypeStr = resultSet.getString("type"); + + return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); + }; + private final NamedParameterJdbcTemplate jdbcTemplate; + + public JDBCVoucherRepository(NamedParameterJdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + static UUID toUUID(byte[] bytes) { + var byteBuffer = ByteBuffer.wrap(bytes); + return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); + } + + private Map toParamMap(Voucher voucher) { + Map paramMap = new HashMap<>(); + paramMap.put("id", voucher.getVoucherId().toString().getBytes()); + paramMap.put("type", voucher.getVoucherType().name()); + paramMap.put("discountValue", voucher.getDiscountValue()); + return paramMap; + } + + @Override + public void save(Voucher voucher) { + int update = jdbcTemplate.update(INSERT_QUERY, toParamMap(voucher)); + if (update != 1) { + throw new RuntimeException("Noting was inserted"); + } + } + + @Override + public List findAll() { + return jdbcTemplate.query(FIND_ALL_QUERY, voucherRowMapper); + } + + public Optional findById(UUID id) { + try { + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID_QUERY, + Collections.singletonMap("id", id.toString().getBytes()), + voucherRowMapper)); + } catch (EmptyResultDataAccessException e) { + logger.error("Got empty result", e); + return Optional.empty(); + } + } +} From 3bfb167f1070f53d3915a2ad65169be229b4513c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 16:42:56 +0900 Subject: [PATCH 114/383] feat: configure dataSource and add JdbcTemplate,NamedParameterJdbcTemplate Beans --- .../configuration/AppConfig.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java index bbcea60f67..129cb840ed 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java @@ -1,9 +1,15 @@ package com.programmers.vouchermanagement.configuration; +import com.zaxxer.hikari.HikariDataSource; import org.beryx.textio.TextIO; import org.beryx.textio.TextIoFactory; +import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; + +import javax.sql.DataSource; @Configuration public class AppConfig { @@ -11,4 +17,27 @@ public class AppConfig { public TextIO textIO() { return TextIoFactory.getTextIO(); } + + @Bean + public DataSource dataSource() { + var dataSource = DataSourceBuilder.create() + .url("jdbc:mysql://localhost:3306/test") + .username("root") + .password("980726") + .type(HikariDataSource.class) + .build(); + dataSource.setMaximumPoolSize(1000); + dataSource.setMinimumIdle(100); + return dataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + return new NamedParameterJdbcTemplate(jdbcTemplate); + } } From 8103a6686c64fecb6ee3d2ea856b6d3bacaab789 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 16:43:11 +0900 Subject: [PATCH 115/383] test: test JDBCVoucherRepository --- .../repository/JDBCVoucherRepositoryTest.java | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java new file mode 100644 index 0000000000..def3769b98 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java @@ -0,0 +1,102 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.zaxxer.hikari.HikariDataSource; +import org.junit.jupiter.api.*; +import org.junit.platform.commons.logging.Logger; +import org.junit.platform.commons.logging.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class JDBCVoucherRepositoryTest { + private static final Logger logger = LoggerFactory.getLogger(JDBCVoucherRepositoryTest.class); + @Autowired + JDBCVoucherRepository jdbcVoucherRepository; + @Autowired + DataSource dataSource; + + @Test + @Order(1) + @DisplayName("HikariConnectionPool 연결할 수 있다.") + public void testHikariConnectionPool() { + assertThat(dataSource.getClass().getName()).isEqualTo("com.zaxxer.hikari.HikariDataSource"); + } + + @Test + @Order(2) + @DisplayName("고정 금액 할인 바우처를 추가할 수 있다.") + void saveFixedAmountVoucherSucceed() { + Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); + jdbcVoucherRepository.save(newVoucher); + Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); + assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); + } + + @Test + @Order(3) + @DisplayName("퍼센트 할인 바우처를 추가할 수 있다.") + void savePercentVoucherSucceed() { + Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(50), VoucherType.PERCENT); + jdbcVoucherRepository.save(newVoucher); + Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); + assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); + } + + @Test + @Order(4) + @DisplayName("모든 바우처를 조회할 수 있다.") + void finsAllVoucherSucceed() { + List vouchers = jdbcVoucherRepository.findAll(); + assertThat(vouchers.isEmpty()).isFalse(); + } + + @Configuration + @ComponentScan( + basePackages = {"com.programmers.vouchermanagement.voucher.repository"} + ) + static class Config { + @Bean + public DataSource dataSource() { + var dataSource = DataSourceBuilder.create() + .url("jdbc:mysql://localhost:3306/test") + .username("root") + .password("980726") + .type(HikariDataSource.class) + .build(); + dataSource.setMaximumPoolSize(1000); + dataSource.setMinimumIdle(100); + return dataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + return new NamedParameterJdbcTemplate(jdbcTemplate); + } + } + +} \ No newline at end of file From feb40992d75c313e42753e3918283a75928e89a3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 16:43:11 +0900 Subject: [PATCH 116/383] test: test JDBCVoucherRepository --- .../repository/JDBCVoucherRepositoryTest.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java new file mode 100644 index 0000000000..065cc015fb --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java @@ -0,0 +1,99 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.zaxxer.hikari.HikariDataSource; +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class JDBCVoucherRepositoryTest { + @Autowired + JDBCVoucherRepository jdbcVoucherRepository; + @Autowired + DataSource dataSource; + + @Test + @Order(1) + @DisplayName("HikariConnectionPool 연결할 수 있다.") + public void testHikariConnectionPool() { + assertThat(dataSource.getClass().getName()).isEqualTo("com.zaxxer.hikari.HikariDataSource"); + } + + @Test + @Order(2) + @DisplayName("고정 금액 할인 바우처를 추가할 수 있다.") + void saveFixedAmountVoucherSucceed() { + Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); + jdbcVoucherRepository.save(newVoucher); + Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); + assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); + } + + @Test + @Order(3) + @DisplayName("퍼센트 할인 바우처를 추가할 수 있다.") + void savePercentVoucherSucceed() { + Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(50), VoucherType.PERCENT); + jdbcVoucherRepository.save(newVoucher); + Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); + assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); + } + + @Test + @Order(4) + @DisplayName("모든 바우처를 조회할 수 있다.") + void finsAllVoucherSucceed() { + List vouchers = jdbcVoucherRepository.findAll(); + assertThat(vouchers.isEmpty()).isFalse(); + } + + @Configuration + @ComponentScan( + basePackages = {"com.programmers.vouchermanagement.voucher.repository"} + ) + static class Config { + @Bean + public DataSource dataSource() { + var dataSource = DataSourceBuilder.create() + .url("jdbc:mysql://localhost:3306/test") + .username("root") + .password("980726") + .type(HikariDataSource.class) + .build(); + dataSource.setMaximumPoolSize(1000); + dataSource.setMinimumIdle(100); + return dataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + return new NamedParameterJdbcTemplate(jdbcTemplate); + } + } + +} \ No newline at end of file From 933cad00175f0fb9ce2287ce82e87939c771140f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:28:48 +0900 Subject: [PATCH 117/383] style: change method name from findBlackCustomers to findAllBlackCustomer --- .../customer/repository/CustomerRepository.java | 2 +- .../customer/repository/FileCustomerRepository.java | 2 +- .../customer/service/CustomerService.java | 11 +++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java index 70ad8fb58f..a06f236bc9 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -5,5 +5,5 @@ import com.programmers.vouchermanagement.customer.domain.Customer; public interface CustomerRepository { - List findBlackCustomers(); + List findAllBlackCustomer(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index fd8157ec66..fd73461f98 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -30,7 +30,7 @@ public FileCustomerRepository(AppProperties appProperties) { } @Override - public List findBlackCustomers() { + public List findAllBlackCustomer() { return customers.values() .stream() .filter(Customer::isBlack) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 433edc23e3..4b2a688fdb 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -1,12 +1,11 @@ package com.programmers.vouchermanagement.customer.service; -import java.util.Collections; -import java.util.List; - -import org.springframework.stereotype.Service; - import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; @Service public class CustomerService { @@ -18,7 +17,7 @@ public CustomerService(CustomerRepository customerRepository) { } public List readBlacklist() { - List blacklist = customerRepository.findBlackCustomers(); + List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { return Collections.emptyList(); } From f92d55c6fb7e72d6e5a9c70c39f9e0b2a84062df Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:29:49 +0900 Subject: [PATCH 118/383] refactor: add 'black' field to customers schema --- src/main/resources/schema.sql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index f7bf44e84b..572e9fb1b6 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,7 +1,8 @@ CREATE TABLE customers ( - id BINARY(16) PRIMARY KEY, - name varchar(20) NOT NULL, + id BINARY(16) PRIMARY KEY, + name varchar(20) NOT NULL, + black boolean not null, CONSTRAINT name UNIQUE (name) ); From 072309a28335b48f48ba3b67928ab92e09c5b31e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:30:18 +0900 Subject: [PATCH 119/383] feat: implement JDBCCustomerRepository --- .../repository/JDBCCustomerRepository.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepository.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepository.java new file mode 100644 index 0000000000..5d795f20d1 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepository.java @@ -0,0 +1,60 @@ +package com.programmers.vouchermanagement.customer.repository; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Repository +@Primary +public class JDBCCustomerRepository implements CustomerRepository { + private static final Logger logger = LoggerFactory.getLogger(JDBCCustomerRepository.class); + private static final String FIND_ALL_BLACK_CUSTOMER_QUERY = "SELECT * FROM test.customers WHERE black = TRUE"; + private static final String INSERT_QUERY = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; + private static final RowMapper customerRowMapper = (resultSet, i) -> { + UUID id = toUUID(resultSet.getBytes("id")); + String name = resultSet.getString("name"); + boolean isBlack = resultSet.getBoolean("black"); + + return new Customer(id, name, isBlack); + }; + private final NamedParameterJdbcTemplate jdbcTemplate; + + public JDBCCustomerRepository(NamedParameterJdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + static UUID toUUID(byte[] bytes) { + var byteBuffer = ByteBuffer.wrap(bytes); + return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); + } + + private Map toParamMap(Customer customer) { + Map paramMap = new HashMap<>(); + paramMap.put("id", customer.getCustomerId().toString().getBytes()); + paramMap.put("name", customer.getName()); + paramMap.put("black", customer.isBlack()); + return paramMap; + } + + @Override + public List findAllBlackCustomer() { + return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER_QUERY, customerRowMapper); + } + + public void save(Customer customer) { + int update = jdbcTemplate.update(INSERT_QUERY, toParamMap(customer)); + if (update != 1) { + throw new RuntimeException("Noting was inserted"); + } + } +} From 25d43608af4f6764f230a674181f284c7a9b59e8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:30:30 +0900 Subject: [PATCH 120/383] test: test JDBCCustomerRepository --- .../JDBCCustomerRepositoryTest.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepositoryTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepositoryTest.java new file mode 100644 index 0000000000..342beb93d9 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepositoryTest.java @@ -0,0 +1,70 @@ +package com.programmers.vouchermanagement.customer.repository; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.zaxxer.hikari.HikariDataSource; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import javax.sql.DataSource; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class JDBCCustomerRepositoryTest { + @Autowired + JDBCCustomerRepository jdbcCustomerRepository; + @Autowired + DataSource dataSource; + + @Test + @DisplayName("블랙리스트를 조회할 수 있다.") + void findAllBlackCustomerSucceed() { + jdbcCustomerRepository.save(new Customer(UUID.randomUUID(), "이세희7", false)); + jdbcCustomerRepository.save(new Customer(UUID.randomUUID(), "이세희8", true)); + jdbcCustomerRepository.save(new Customer(UUID.randomUUID(), "이세희9", false)); + List customers = jdbcCustomerRepository.findAllBlackCustomer(); + assertThat(customers.isEmpty()).isFalse(); + assertThat(customers.stream().filter(customer -> !customer.isBlack()).toList()).isEmpty(); + } + + @Configuration + @ComponentScan( + basePackages = {"com.programmers.vouchermanagement.customer.repository"} + ) + static class Config { + @Bean + public DataSource dataSource() { + var dataSource = DataSourceBuilder.create() + .url("jdbc:mysql://localhost:3306/test") + .username("root") + .password("980726") + .type(HikariDataSource.class) + .build(); + dataSource.setMaximumPoolSize(1000); + dataSource.setMinimumIdle(100); + return dataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + return new NamedParameterJdbcTemplate(jdbcTemplate); + } + } +} \ No newline at end of file From e0de266196696ac76d0c870098fa7eb8b216e906 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:50:06 +0900 Subject: [PATCH 121/383] docs: add log directory to .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1bd5e9e555..15abd7ac7b 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,6 @@ gradle-app.setting # Java heap dump *.hprof -# End of https://www.toptal.com/developers/gitignore/api/gradle \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/gradle + +logs/ \ No newline at end of file From 78f4e2a9303edccefe364c41a0af747e2888ab56 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:50:43 +0900 Subject: [PATCH 122/383] feat: implement delete by id feature at JDBCVoucherRepository --- .../voucher/repository/JDBCVoucherRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java index cf033b7b8b..d7611ac171 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java @@ -28,6 +28,7 @@ public class JDBCVoucherRepository implements VoucherRepository { return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); }; + private static final String DELETE_VOUCHER_QUERY = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; private final NamedParameterJdbcTemplate jdbcTemplate; public JDBCVoucherRepository(NamedParameterJdbcTemplate jdbcTemplate) { @@ -70,4 +71,11 @@ public Optional findById(UUID id) { return Optional.empty(); } } + + public void delete(UUID id) { + int update = jdbcTemplate.update(DELETE_VOUCHER_QUERY, Collections.singletonMap("id", id.toString().getBytes())); + if (update != 1) { + throw new RuntimeException("Noting was deleted"); + } + } } From ad9e0498e3bebe2f776e9d7aac13eb0576c34d4d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:51:52 +0900 Subject: [PATCH 123/383] test: test delete method at JDBCVoucherRepository --- .../repository/JDBCVoucherRepositoryTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java index 065cc015fb..2a88479101 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java @@ -67,6 +67,18 @@ void finsAllVoucherSucceed() { assertThat(vouchers.isEmpty()).isFalse(); } + @Test + @Order(5) + @DisplayName("바우처를 아이디로 삭제할 수 있다.") + void deleteVoucherSucceed() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + jdbcVoucherRepository.save(voucher); + + jdbcVoucherRepository.delete(voucher.getVoucherId()); + + assertThat(jdbcVoucherRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); + } + @Configuration @ComponentScan( basePackages = {"com.programmers.vouchermanagement.voucher.repository"} From 335151c365531bcff8b4f2e3c8af6b89b34a15dd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 19:52:21 +0900 Subject: [PATCH 124/383] style: format JDBCVoucherRepositoryTest codes --- .../voucher/repository/JDBCVoucherRepositoryTest.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java index 2a88479101..7761420663 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java @@ -43,7 +43,9 @@ public void testHikariConnectionPool() { void saveFixedAmountVoucherSucceed() { Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); jdbcVoucherRepository.save(newVoucher); + Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); } @@ -54,7 +56,9 @@ void saveFixedAmountVoucherSucceed() { void savePercentVoucherSucceed() { Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(50), VoucherType.PERCENT); jdbcVoucherRepository.save(newVoucher); + Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); } @@ -62,8 +66,9 @@ void savePercentVoucherSucceed() { @Test @Order(4) @DisplayName("모든 바우처를 조회할 수 있다.") - void finsAllVoucherSucceed() { + void findAllVoucherSucceed() { List vouchers = jdbcVoucherRepository.findAll(); + assertThat(vouchers.isEmpty()).isFalse(); } From df34e66f16a9813675af53b14c16c9f5812954aa Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 20:02:26 +0900 Subject: [PATCH 125/383] feat: implement voucher update feature at JDBCVoucherRepository --- .../voucher/repository/JDBCVoucherRepository.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java index d7611ac171..f9b71427e0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java @@ -21,6 +21,8 @@ public class JDBCVoucherRepository implements VoucherRepository { private static final String INSERT_QUERY = "INSERT INTO test.vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discountValue)"; private static final String FIND_BY_ID_QUERY = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; private static final String FIND_ALL_QUERY = "SELECT * FROM test.vouchers"; + private static final String DELETE_VOUCHER_QUERY = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; + private static final String UPDATE_VOUCHER_QUERY = "UPDATE test.vouchers SET type = :type, discount_value = :discountValue WHERE id = UUID_TO_BIN(:id)"; private static final RowMapper voucherRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes("id")); BigDecimal discountValue = resultSet.getBigDecimal("discount_value"); @@ -28,7 +30,6 @@ public class JDBCVoucherRepository implements VoucherRepository { return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); }; - private static final String DELETE_VOUCHER_QUERY = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; private final NamedParameterJdbcTemplate jdbcTemplate; public JDBCVoucherRepository(NamedParameterJdbcTemplate jdbcTemplate) { @@ -78,4 +79,11 @@ public void delete(UUID id) { throw new RuntimeException("Noting was deleted"); } } + + public void update(Voucher voucher) { + int update = jdbcTemplate.update(UPDATE_VOUCHER_QUERY, toParamMap(voucher)); + if (update != 1) { + throw new RuntimeException("Noting was updated"); + } + } } From 4f0c5ce0a501f280e70fb3f3710de55baf1fb2ee Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 20:02:41 +0900 Subject: [PATCH 126/383] test: test voucher update feature at JDBCVoucherRepository --- .../repository/JDBCVoucherRepositoryTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java index 7761420663..dc927914b0 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java @@ -84,6 +84,22 @@ void deleteVoucherSucceed() { assertThat(jdbcVoucherRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); } + @Test + @Order(6) + @DisplayName("바우처를 업데이트 할 수 있다.") + void updateVoucherSucceed() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + jdbcVoucherRepository.save(voucher); + + Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), BigDecimal.valueOf(100), VoucherType.PERCENT); + jdbcVoucherRepository.update(updatedVoucher); + + Optional retrievedVoucher = jdbcVoucherRepository.findById(voucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); + assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); + assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(updatedVoucher.getVoucherType()); + } + @Configuration @ComponentScan( basePackages = {"com.programmers.vouchermanagement.voucher.repository"} From 23f25bdd9232d323dc194474199aed565a0471d8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 20:09:35 +0900 Subject: [PATCH 127/383] style: change method name at Service, Controller at all domains --- .../consoleapp/menu/MenuHandler.java | 5 ++--- .../customer/controller/CustomerController.java | 4 ++-- .../customer/service/CustomerService.java | 2 +- .../voucher/controller/VoucherController.java | 11 +++++------ .../voucher/service/VoucherService.java | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index d22c2d8235..c03a078baa 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -6,7 +6,6 @@ import com.programmers.vouchermanagement.voucher.controller.VoucherController; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -66,7 +65,7 @@ private void executeMenu(Menu menu) { case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { CreateVoucherRequest createVoucherRequest = consoleManager.instructCreate(); - VoucherResponse voucherResponse = voucherController.create(createVoucherRequest); + VoucherResponse voucherResponse = voucherController.createVoucher(createVoucherRequest); consoleManager.printCreateResult(voucherResponse); } case LIST -> { @@ -75,7 +74,7 @@ private void executeMenu(Menu menu) { } //TODO: customerDTO case BLACKLIST -> { - List customerResponses = customerController.readBlacklist(); + List customerResponses = customerController.readAllBlackCustomer(); consoleManager.printReadBlacklist(customerResponses); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 5494d8d8b0..559566723a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -15,7 +15,7 @@ public CustomerController(CustomerService customerService) { this.customerService = customerService; } - public List readBlacklist() { - return customerService.readBlacklist(); + public List readAllBlackCustomer() { + return customerService.readAllBlackCustomer(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 4b2a688fdb..4c2aa2c70c 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -16,7 +16,7 @@ public CustomerService(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } - public List readBlacklist() { + public List readAllBlackCustomer() { List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { return Collections.emptyList(); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 3f1c61e697..9bffef4238 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,12 +1,11 @@ package com.programmers.vouchermanagement.voucher.controller; -import org.springframework.stereotype.Controller; - -import java.util.List; - import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; +import org.springframework.stereotype.Controller; + +import java.util.List; @Controller public class VoucherController { @@ -16,8 +15,8 @@ public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } - public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { - return voucherService.create(createVoucherRequest); + public VoucherResponse createVoucher(CreateVoucherRequest createVoucherRequest) { + return voucherService.createVoucher(createVoucherRequest); } public List readAllVouchers() { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 927fa89902..6b75383ab8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -20,7 +20,7 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + public VoucherResponse createVoucher(CreateVoucherRequest createVoucherRequest) { Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType()); voucherRepository.save(voucher); return VoucherResponse.from(voucher); From 6130a4049ad73796e4760c3a9d1ca1f1d9c8cd4d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 20:17:54 +0900 Subject: [PATCH 128/383] feat: declare update, delete, findById mathod at VoucherRepository --- .../voucher/repository/VoucherRepository.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index c5545b4769..90ff74574d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -1,10 +1,19 @@ package com.programmers.vouchermanagement.voucher.repository; -import java.util.List; - import com.programmers.vouchermanagement.voucher.domain.Voucher; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + public interface VoucherRepository { void save(Voucher voucher); + List findAll(); + + Optional findById(UUID id); + + void delete(UUID id); + + void update(Voucher voucher); } From 235adfb30b39d1401682d7ed2fd78ac7c4303f40 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 20:18:16 +0900 Subject: [PATCH 129/383] feat: implement update, delete, findById mathod at FileVoucherRepository --- .../repository/FileVoucherRepository.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 9d7b7efbab..fbba89b266 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -52,6 +52,23 @@ public List findAll() { return vouchers.values().stream().toList(); } + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(vouchers.get(id)); + } + + @Override + public void delete(UUID id) { + vouchers.remove(id); + saveFile(); + } + + @Override + public void update(Voucher voucher) { + vouchers.put(voucher.getVoucherId(), voucher); + saveFile(); + } + private void loadFile() { try { File file = new File(filePath); From 500c79b79952d0f7eba0cf423eba7fc57817950f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 20:18:22 +0900 Subject: [PATCH 130/383] feat: implement update, delete, findById mathod at InMemoryVoucherRepository --- .../repository/InMemoryVoucherRepository.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java index 783af8df55..07be35bf9b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java @@ -1,11 +1,10 @@ package com.programmers.vouchermanagement.voucher.repository; -import java.util.*; - +import com.programmers.vouchermanagement.voucher.domain.Voucher; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; -import com.programmers.vouchermanagement.voucher.domain.Voucher; +import java.util.*; @Repository @Profile("dev") @@ -25,4 +24,19 @@ public void save(Voucher voucher) { public List findAll() { return vouchers.values().stream().toList(); } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(vouchers.get(id)); + } + + @Override + public void delete(UUID id) { + vouchers.remove(id); + } + + @Override + public void update(Voucher voucher) { + vouchers.put(voucher.getVoucherId(), voucher); + } } From e53b3ad882750c68116b48e426cb7af7642a343a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 20:19:01 +0900 Subject: [PATCH 131/383] enhance: add @Override annotation update, delete, findById method at JDBCVoucherRepository --- .../voucher/repository/JDBCVoucherRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java index f9b71427e0..f6f3b6505f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java @@ -62,6 +62,7 @@ public List findAll() { return jdbcTemplate.query(FIND_ALL_QUERY, voucherRowMapper); } + @Override public Optional findById(UUID id) { try { return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID_QUERY, @@ -73,6 +74,7 @@ public Optional findById(UUID id) { } } + @Override public void delete(UUID id) { int update = jdbcTemplate.update(DELETE_VOUCHER_QUERY, Collections.singletonMap("id", id.toString().getBytes())); if (update != 1) { @@ -80,6 +82,7 @@ public void delete(UUID id) { } } + @Override public void update(Voucher voucher) { int update = jdbcTemplate.update(UPDATE_VOUCHER_QUERY, toParamMap(voucher)); if (update != 1) { From 7c4693e0bec8618eb15ea1fe17c520e20757a141 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 21:33:01 +0900 Subject: [PATCH 132/383] test: add application.yaml, blacklist.csv, voucher.json to test directory for test --- src/test/resources/application.yaml | 9 +++++++++ src/test/resources/blacklist.csv | 3 +++ src/test/resources/voucher.json | 9 +++++++++ 3 files changed, 21 insertions(+) create mode 100644 src/test/resources/application.yaml create mode 100644 src/test/resources/blacklist.csv create mode 100644 src/test/resources/voucher.json diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml new file mode 100644 index 0000000000..2f9a705608 --- /dev/null +++ b/src/test/resources/application.yaml @@ -0,0 +1,9 @@ +file: + resources: + path: src/test/resources/ + + domains: + customer: + file-name: blacklist.csv + voucher: + file-name: voucher.json \ No newline at end of file diff --git a/src/test/resources/blacklist.csv b/src/test/resources/blacklist.csv new file mode 100644 index 0000000000..e2efc7ccaa --- /dev/null +++ b/src/test/resources/blacklist.csv @@ -0,0 +1,3 @@ +id,name +e8d88c24-668c-4b65-a658-44303bfbb805, 송인재 +9b46f523-03d4-41b2-a68e-0666f21c6f7d, 익명 diff --git a/src/test/resources/voucher.json b/src/test/resources/voucher.json new file mode 100644 index 0000000000..d9428d5c40 --- /dev/null +++ b/src/test/resources/voucher.json @@ -0,0 +1,9 @@ +[ { + "voucher_type" : "percent", + "voucher_id" : "ad9f0529-6f4e-4a36-b44e-d7d7b407c9a1", + "discount_value" : 100 +}, { + "voucher_type" : "fixed", + "voucher_id" : "ba65ee06-ae98-48cd-b31d-dfabb8c889a4", + "discount_value" : 100 +} ] \ No newline at end of file From f9d221665d452e165b6535729b48131c90e7e868 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 21:34:49 +0900 Subject: [PATCH 133/383] fix: check that voucher does not exist, when delete voucher by id --- .../voucher/repository/FileVoucherRepository.java | 3 ++- .../voucher/repository/InMemoryVoucherRepository.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index fbba89b266..f1b24cf514 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -59,12 +59,13 @@ public Optional findById(UUID id) { @Override public void delete(UUID id) { - vouchers.remove(id); + Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException("Noting was deleted")); saveFile(); } @Override public void update(Voucher voucher) { + Optional.ofNullable(vouchers.get(voucher.getVoucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); vouchers.put(voucher.getVoucherId(), voucher); saveFile(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java index 07be35bf9b..a84b0c5df1 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java @@ -32,11 +32,12 @@ public Optional findById(UUID id) { @Override public void delete(UUID id) { - vouchers.remove(id); + Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException("Noting was deleted")); } @Override public void update(Voucher voucher) { + Optional.ofNullable(vouchers.get(voucher.getVoucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); vouchers.put(voucher.getVoucherId(), voucher); } } From a2fdaeb9b36f0bbbe17eb203d2efa0cbf834eebb Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 21:35:08 +0900 Subject: [PATCH 134/383] test: test InMemoryVoucherRepository --- .../InMemoryVoucherRepositoryTest.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepositoryTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepositoryTest.java new file mode 100644 index 0000000000..b8a4f464a5 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepositoryTest.java @@ -0,0 +1,55 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import java.math.BigDecimal; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class InMemoryVoucherRepositoryTest { + InMemoryVoucherRepository inMemoryVoucherRepository = new InMemoryVoucherRepository(); + + @Test + @DisplayName("바우처를 아이디로 삭제할 수 있다.") + void deleteVoucherSucceed() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + inMemoryVoucherRepository.save(voucher); + + inMemoryVoucherRepository.delete(voucher.getVoucherId()); + + assertThat(inMemoryVoucherRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); + } + + @Test + @DisplayName("없는 바우처를 삭제하면 실패한다.") + void deleteNonExistVoucherFail() { + UUID NonExistVoucherId = UUID.randomUUID(); + + assertThrows(RuntimeException.class, () -> { + inMemoryVoucherRepository.delete(NonExistVoucherId); + }); + } + + @Test + @DisplayName("바우처를 업데이트 할 수 있다.") + void updateVoucherSucceed() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + inMemoryVoucherRepository.save(voucher); + + Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), BigDecimal.valueOf(100), VoucherType.PERCENT); + inMemoryVoucherRepository.update(updatedVoucher); + + Optional retrievedVoucher = inMemoryVoucherRepository.findById(voucher.getVoucherId()); + assertThat(retrievedVoucher.isEmpty()).isFalse(); + assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); + assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(updatedVoucher.getVoucherType()); + } +} \ No newline at end of file From 3c562bd9253a6eddd5a08a5b03d0533d14355bf7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 21:35:31 +0900 Subject: [PATCH 135/383] test: test delete feature when voucher does not exist --- .../repository/JDBCVoucherRepositoryTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java index dc927914b0..aae4876aab 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java @@ -20,6 +20,7 @@ import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; @SpringJUnitConfig @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @@ -86,6 +87,17 @@ void deleteVoucherSucceed() { @Test @Order(6) + @DisplayName("없는 바우처를 삭제하면 실패한다.") + void deleteNonExistVoucherFail() { + UUID NonExistVoucherId = UUID.randomUUID(); + + assertThrows(RuntimeException.class, () -> { + jdbcVoucherRepository.delete(NonExistVoucherId); + }); + } + + @Test + @Order(7) @DisplayName("바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); From 043b747c433539ff1c52df7be752c07ca73b048b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 23:38:49 +0900 Subject: [PATCH 136/383] feat: implement readVoucherById, deleteVoucher, updateVoucher at VoucherService --- .../voucher/service/VoucherService.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 6b75383ab8..4ae2bc778d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,15 +1,13 @@ package com.programmers.vouchermanagement.voucher.service; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; - import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; -import java.util.NoSuchElementException; import java.util.UUID; @Service @@ -37,4 +35,19 @@ public List readAllVouchers() { .map(VoucherResponse::from) .toList(); } + + public void readVoucherById(UUID voucherId) { + voucherRepository.findById(voucherId); + + + } + + public void deleteVoucher(UUID voucherId) { + voucherRepository.delete(voucherId); + } + + public void updateVoucher(Voucher voucher) { + voucherRepository.update(voucher); + } + } From 858da10a0a0ab16e0f00a5f7d76227e60c84856c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 26 Oct 2023 23:39:15 +0900 Subject: [PATCH 137/383] test: test readVoucherById, deleteVoucher, updateVoucher of VoucherService --- .../voucher/service/VoucherServiceTest.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java new file mode 100644 index 0000000000..230456e62c --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -0,0 +1,94 @@ +package com.programmers.vouchermanagement.voucher.service; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(SpringExtension.class) +class VoucherServiceTest { + @InjectMocks + VoucherService voucherService; + @Mock + VoucherRepository voucherRepository; + @Mock + UUID mockId; + @Mock + Voucher mockVoucher; + + @Test + @DisplayName("단위 테스트를 위해 Service에 Mock 객체(Repository) 주입") + void initTest() { + assertThat(voucherRepository).isNotNull(); + assertThat(voucherService).isNotNull(); + } + + @Test + @DisplayName("고정 할인 금액 바우처 객체를 생성할 수 있다.") + void createFixedAmountVoucherSucceed() { + CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(BigDecimal.valueOf(1000), VoucherType.FIXED); + voucherService.createVoucher(createVoucherRequest); + + verify(voucherRepository, times(1)).save(any(Voucher.class)); + } + + @Test + @DisplayName("퍼센트 할인 바우처 객체를 생성할 수 있다.") + void createPercentDiscountVoucherSucceed() { + CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(BigDecimal.valueOf(100), VoucherType.PERCENT); + voucherService.createVoucher(createVoucherRequest); + + verify(voucherRepository, times(1)).save(any(Voucher.class)); + } + + @Test + @DisplayName("모든 바우처를 조회할 수 있다.") + void readAllVouchersSucceed() { + voucherService.readAllVouchers(); + + when(voucherRepository.findAll()).thenReturn(new ArrayList<>()); + + verify(voucherRepository, times(1)).findAll(); + } + + @Test + @DisplayName("바우처를 id로 조회할 수 있다.") + void readVoucherByIdSucceed() { + voucherService.readVoucherById(mockId); + + when(voucherRepository.findById(mockId)).thenReturn(Optional.of(mockVoucher)); + + verify(voucherRepository, times(1)).findById(any(UUID.class)); + } + + @Test + @DisplayName("바우처를 id로 삭제할 수 있다.") + void deleteVoucherSucceed() { + voucherService.deleteVoucher(mockId); + + verify(voucherRepository, times(1)).delete(any(UUID.class)); + } + + @Test + @DisplayName("바우처를 업데이트할 수 있다.") + void updateVoucherSucceed() { + voucherService.updateVoucher(new Voucher(UUID.randomUUID(), BigDecimal.valueOf(100), VoucherType.FIXED)); + + verify(voucherRepository, times(1)).update(any(Voucher.class)); + } +} \ No newline at end of file From 1aec87eab82a0f4c660e38bd04875a3f51920914 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 00:03:17 +0900 Subject: [PATCH 138/383] style: rename all repositories --- ...itory.java => CustomerFileRepository.java} | 6 ++-- ...itory.java => CustomerJDBCRepository.java} | 6 ++-- ...sitory.java => VoucherFileRepository.java} | 6 ++-- ...ry.java => VoucherInMemoryRepository.java} | 4 +-- ...sitory.java => VoucherJDBCRepository.java} | 6 ++-- ...t.java => CustomerJDBCRepositoryTest.java} | 12 ++++---- ...ava => VoucherInMemoryRepositoryTest.java} | 18 ++++++------ ...st.java => VoucherJDBCRepositoryTest.java} | 28 +++++++++---------- 8 files changed, 43 insertions(+), 43 deletions(-) rename src/main/java/com/programmers/vouchermanagement/customer/repository/{FileCustomerRepository.java => CustomerFileRepository.java} (92%) rename src/main/java/com/programmers/vouchermanagement/customer/repository/{JDBCCustomerRepository.java => CustomerJDBCRepository.java} (93%) rename src/main/java/com/programmers/vouchermanagement/voucher/repository/{FileVoucherRepository.java => VoucherFileRepository.java} (96%) rename src/main/java/com/programmers/vouchermanagement/voucher/repository/{InMemoryVoucherRepository.java => VoucherInMemoryRepository.java} (91%) rename src/main/java/com/programmers/vouchermanagement/voucher/repository/{JDBCVoucherRepository.java => VoucherJDBCRepository.java} (95%) rename src/test/java/com/programmers/vouchermanagement/customer/repository/{JDBCCustomerRepositoryTest.java => CustomerJDBCRepositoryTest.java} (87%) rename src/test/java/com/programmers/vouchermanagement/voucher/repository/{InMemoryVoucherRepositoryTest.java => VoucherInMemoryRepositoryTest.java} (76%) rename src/test/java/com/programmers/vouchermanagement/voucher/repository/{JDBCVoucherRepositoryTest.java => VoucherJDBCRepositoryTest.java} (85%) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java similarity index 92% rename from src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java rename to src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index fd73461f98..7bf8518c28 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -15,15 +15,15 @@ @Repository @Profile({"dev", "prod"}) -public class FileCustomerRepository implements CustomerRepository { - private static final Logger logger = LoggerFactory.getLogger(FileCustomerRepository.class); +public class CustomerFileRepository implements CustomerRepository { + private static final Logger logger = LoggerFactory.getLogger(CustomerFileRepository.class); private static final String COMMA_SEPARATOR = ", "; private static final String IO_EXCEPTION_LOG_MESSAGE = "Error raised while reading blacklist"; private final String filePath; private final Map customers; - public FileCustomerRepository(AppProperties appProperties) { + public CustomerFileRepository(AppProperties appProperties) { this.filePath = appProperties.resources().path() + appProperties.domains().get("customer").fileName(); this.customers = new HashMap<>(); loadBlacklist(); diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java similarity index 93% rename from src/main/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepository.java rename to src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 5d795f20d1..5ef9a15f58 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -16,8 +16,8 @@ @Repository @Primary -public class JDBCCustomerRepository implements CustomerRepository { - private static final Logger logger = LoggerFactory.getLogger(JDBCCustomerRepository.class); +public class CustomerJDBCRepository implements CustomerRepository { + private static final Logger logger = LoggerFactory.getLogger(CustomerJDBCRepository.class); private static final String FIND_ALL_BLACK_CUSTOMER_QUERY = "SELECT * FROM test.customers WHERE black = TRUE"; private static final String INSERT_QUERY = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; private static final RowMapper customerRowMapper = (resultSet, i) -> { @@ -29,7 +29,7 @@ public class JDBCCustomerRepository implements CustomerRepository { }; private final NamedParameterJdbcTemplate jdbcTemplate; - public JDBCCustomerRepository(NamedParameterJdbcTemplate jdbcTemplate) { + public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java similarity index 96% rename from src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java rename to src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index f1b24cf514..967b51bd9c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -18,8 +18,8 @@ @Repository @Profile("prod") -public class FileVoucherRepository implements VoucherRepository { - private static final Logger logger = LoggerFactory.getLogger(FileVoucherRepository.class); +public class VoucherFileRepository implements VoucherRepository { + private static final Logger logger = LoggerFactory.getLogger(VoucherFileRepository.class); //constants private static final String VOUCHER_ID_KEY = "voucher_id"; @@ -35,7 +35,7 @@ public class FileVoucherRepository implements VoucherRepository { private final String filePath; private final Map vouchers; - public FileVoucherRepository(AppProperties appProperties) { + public VoucherFileRepository(AppProperties appProperties) { this.filePath = appProperties.resources().path() + appProperties.domains().get("voucher").fileName(); this.vouchers = new HashMap<>(); loadFile(); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java similarity index 91% rename from src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java rename to src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index a84b0c5df1..70f1582815 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -8,10 +8,10 @@ @Repository @Profile("dev") -public class InMemoryVoucherRepository implements VoucherRepository { +public class VoucherInMemoryRepository implements VoucherRepository { private final Map vouchers; - public InMemoryVoucherRepository() { + public VoucherInMemoryRepository() { vouchers = new HashMap<>(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java similarity index 95% rename from src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java rename to src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index f6f3b6505f..2519f4604d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -16,8 +16,8 @@ @Repository @Primary -public class JDBCVoucherRepository implements VoucherRepository { - private static final Logger logger = LoggerFactory.getLogger(JDBCVoucherRepository.class); +public class VoucherJDBCRepository implements VoucherRepository { + private static final Logger logger = LoggerFactory.getLogger(VoucherJDBCRepository.class); private static final String INSERT_QUERY = "INSERT INTO test.vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discountValue)"; private static final String FIND_BY_ID_QUERY = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; private static final String FIND_ALL_QUERY = "SELECT * FROM test.vouchers"; @@ -32,7 +32,7 @@ public class JDBCVoucherRepository implements VoucherRepository { }; private final NamedParameterJdbcTemplate jdbcTemplate; - public JDBCVoucherRepository(NamedParameterJdbcTemplate jdbcTemplate) { + public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java similarity index 87% rename from src/test/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepositoryTest.java rename to src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 342beb93d9..58d6bb38aa 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/JDBCCustomerRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -22,19 +22,19 @@ @SpringJUnitConfig @TestInstance(TestInstance.Lifecycle.PER_CLASS) -class JDBCCustomerRepositoryTest { +class CustomerJDBCRepositoryTest { @Autowired - JDBCCustomerRepository jdbcCustomerRepository; + CustomerJDBCRepository customerJDBCRepository; @Autowired DataSource dataSource; @Test @DisplayName("블랙리스트를 조회할 수 있다.") void findAllBlackCustomerSucceed() { - jdbcCustomerRepository.save(new Customer(UUID.randomUUID(), "이세희7", false)); - jdbcCustomerRepository.save(new Customer(UUID.randomUUID(), "이세희8", true)); - jdbcCustomerRepository.save(new Customer(UUID.randomUUID(), "이세희9", false)); - List customers = jdbcCustomerRepository.findAllBlackCustomer(); + customerJDBCRepository.save(new Customer(UUID.randomUUID(), "이세희7", false)); + customerJDBCRepository.save(new Customer(UUID.randomUUID(), "이세희8", true)); + customerJDBCRepository.save(new Customer(UUID.randomUUID(), "이세희9", false)); + List customers = customerJDBCRepository.findAllBlackCustomer(); assertThat(customers.isEmpty()).isFalse(); assertThat(customers.stream().filter(customer -> !customer.isBlack()).toList()).isEmpty(); } diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java similarity index 76% rename from src/test/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepositoryTest.java rename to src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java index b8a4f464a5..da433120ae 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java @@ -14,18 +14,18 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @TestInstance(TestInstance.Lifecycle.PER_CLASS) -class InMemoryVoucherRepositoryTest { - InMemoryVoucherRepository inMemoryVoucherRepository = new InMemoryVoucherRepository(); +class VoucherInMemoryRepositoryTest { + VoucherInMemoryRepository voucherInMemoryRepository = new VoucherInMemoryRepository(); @Test @DisplayName("바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); - inMemoryVoucherRepository.save(voucher); + voucherInMemoryRepository.save(voucher); - inMemoryVoucherRepository.delete(voucher.getVoucherId()); + voucherInMemoryRepository.delete(voucher.getVoucherId()); - assertThat(inMemoryVoucherRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); + assertThat(voucherInMemoryRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); } @Test @@ -34,7 +34,7 @@ void deleteNonExistVoucherFail() { UUID NonExistVoucherId = UUID.randomUUID(); assertThrows(RuntimeException.class, () -> { - inMemoryVoucherRepository.delete(NonExistVoucherId); + voucherInMemoryRepository.delete(NonExistVoucherId); }); } @@ -42,12 +42,12 @@ void deleteNonExistVoucherFail() { @DisplayName("바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); - inMemoryVoucherRepository.save(voucher); + voucherInMemoryRepository.save(voucher); Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), BigDecimal.valueOf(100), VoucherType.PERCENT); - inMemoryVoucherRepository.update(updatedVoucher); + voucherInMemoryRepository.update(updatedVoucher); - Optional retrievedVoucher = inMemoryVoucherRepository.findById(voucher.getVoucherId()); + Optional retrievedVoucher = voucherInMemoryRepository.findById(voucher.getVoucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(updatedVoucher.getVoucherType()); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java similarity index 85% rename from src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java rename to src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index aae4876aab..30d8890353 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JDBCVoucherRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -25,9 +25,9 @@ @SpringJUnitConfig @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) -class JDBCVoucherRepositoryTest { +class VoucherJDBCRepositoryTest { @Autowired - JDBCVoucherRepository jdbcVoucherRepository; + VoucherJDBCRepository voucherJDBCRepository; @Autowired DataSource dataSource; @@ -43,9 +43,9 @@ public void testHikariConnectionPool() { @DisplayName("고정 금액 할인 바우처를 추가할 수 있다.") void saveFixedAmountVoucherSucceed() { Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); - jdbcVoucherRepository.save(newVoucher); + voucherJDBCRepository.save(newVoucher); - Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.getVoucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); @@ -56,9 +56,9 @@ void saveFixedAmountVoucherSucceed() { @DisplayName("퍼센트 할인 바우처를 추가할 수 있다.") void savePercentVoucherSucceed() { Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(50), VoucherType.PERCENT); - jdbcVoucherRepository.save(newVoucher); + voucherJDBCRepository.save(newVoucher); - Optional retrievedVoucher = jdbcVoucherRepository.findById(newVoucher.getVoucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.getVoucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); @@ -68,7 +68,7 @@ void savePercentVoucherSucceed() { @Order(4) @DisplayName("모든 바우처를 조회할 수 있다.") void findAllVoucherSucceed() { - List vouchers = jdbcVoucherRepository.findAll(); + List vouchers = voucherJDBCRepository.findAll(); assertThat(vouchers.isEmpty()).isFalse(); } @@ -78,11 +78,11 @@ void findAllVoucherSucceed() { @DisplayName("바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); - jdbcVoucherRepository.save(voucher); + voucherJDBCRepository.save(voucher); - jdbcVoucherRepository.delete(voucher.getVoucherId()); + voucherJDBCRepository.delete(voucher.getVoucherId()); - assertThat(jdbcVoucherRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); + assertThat(voucherJDBCRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); } @Test @@ -92,7 +92,7 @@ void deleteNonExistVoucherFail() { UUID NonExistVoucherId = UUID.randomUUID(); assertThrows(RuntimeException.class, () -> { - jdbcVoucherRepository.delete(NonExistVoucherId); + voucherJDBCRepository.delete(NonExistVoucherId); }); } @@ -101,12 +101,12 @@ void deleteNonExistVoucherFail() { @DisplayName("바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); - jdbcVoucherRepository.save(voucher); + voucherJDBCRepository.save(voucher); Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), BigDecimal.valueOf(100), VoucherType.PERCENT); - jdbcVoucherRepository.update(updatedVoucher); + voucherJDBCRepository.update(updatedVoucher); - Optional retrievedVoucher = jdbcVoucherRepository.findById(voucher.getVoucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getVoucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(updatedVoucher.getVoucherType()); From 346d6aa5216c78f32138732f26c27b1ec6a48535 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 00:04:29 +0900 Subject: [PATCH 139/383] feat: implement WalletRepository interface --- .../wallet/repository/WalletRepository.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java new file mode 100644 index 0000000000..a31127a5a0 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java @@ -0,0 +1,18 @@ +package com.programmers.vouchermanagement.wallet.repository; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.domain.Voucher; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface WalletRepository { + void save(UUID voucherId, UUID customerId); + + List findAllVoucherByCustomerId(UUID customerId); + + void delete(UUID voucherId, UUID customerId); + + Optional findCustomerByVoucherId(UUID voucherId); +} From 35919e33e3f36fdb60f7c1c67b3aad90e2a2547f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 01:15:49 +0900 Subject: [PATCH 140/383] enhance: set unique value(voucher_id) at wallet table --- src/main/resources/schema.sql | 5 +- .../wallet/WalletJDBCRepositoryTest.java | 74 +++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 572e9fb1b6..352bad2d68 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -14,9 +14,10 @@ CREATE TABLE vouchers created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ); -CREATE TABLE voucher_customer_own_info +CREATE TABLE wallet ( id INT PRIMARY KEY AUTO_INCREMENT, customer_id BINARY(16) NOT NULL REFERENCES customers (id) ON DELETE CASCADE, - voucher_id BINARY(16) NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE + voucher_id BINARY(16) NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE, + CONSTRAINT voucher_id UNIQUE (voucher_id) ); \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java new file mode 100644 index 0000000000..2d329547f2 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java @@ -0,0 +1,74 @@ +package com.programmers.vouchermanagement.wallet; + +import com.programmers.vouchermanagement.wallet.repository.WalletJDBCRepository; +import com.zaxxer.hikari.HikariDataSource; +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import javax.sql.DataSource; + +@SpringJUnitConfig +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class WalletJDBCRepositoryTest { + @Autowired + WalletJDBCRepository walletJDBCRepository; + @Autowired + DataSource dataSource; + + @Test + @DisplayName("고객 id와 바우처 id 정보를 함께 저장할 수 있다.") + void save() { + } + + @Test + @DisplayName("고객 id로 고객이 가진 바우처 id를 가져올 수 있다.") + void findAllVoucherByCustomerId() { + } + + @Test + @DisplayName("함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 있다.") + void delete() { + } + + @Test + @DisplayName("바우처 id로 바우처를 가진 고객 id를 가져올 수 있다.") + void findCustomerByVoucherId() { + } + + @Configuration + @ComponentScan( + basePackages = {"com.programmers.vouchermanagement.wallet.repository"} + ) + static class Config { + @Bean + public DataSource dataSource() { + var dataSource = DataSourceBuilder.create() + .url("jdbc:mysql://localhost:3306/test") + .username("root") + .password("980726") + .type(HikariDataSource.class) + .build(); + dataSource.setMaximumPoolSize(1000); + dataSource.setMinimumIdle(100); + return dataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + return new NamedParameterJdbcTemplate(jdbcTemplate); + } + } +} \ No newline at end of file From 6ee0b35909e139406fc349fa2a0457ec0b6238b3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 01:16:49 +0900 Subject: [PATCH 141/383] Revert "enhance: set unique value(voucher_id) at wallet table" This reverts commit 35919e33e3f36fdb60f7c1c67b3aad90e2a2547f. --- src/main/resources/schema.sql | 5 +- .../wallet/WalletJDBCRepositoryTest.java | 74 ------------------- 2 files changed, 2 insertions(+), 77 deletions(-) delete mode 100644 src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 352bad2d68..572e9fb1b6 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -14,10 +14,9 @@ CREATE TABLE vouchers created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ); -CREATE TABLE wallet +CREATE TABLE voucher_customer_own_info ( id INT PRIMARY KEY AUTO_INCREMENT, customer_id BINARY(16) NOT NULL REFERENCES customers (id) ON DELETE CASCADE, - voucher_id BINARY(16) NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE, - CONSTRAINT voucher_id UNIQUE (voucher_id) + voucher_id BINARY(16) NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE ); \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java deleted file mode 100644 index 2d329547f2..0000000000 --- a/src/test/java/com/programmers/vouchermanagement/wallet/WalletJDBCRepositoryTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.programmers.vouchermanagement.wallet; - -import com.programmers.vouchermanagement.wallet.repository.WalletJDBCRepository; -import com.zaxxer.hikari.HikariDataSource; -import org.junit.jupiter.api.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; - -import javax.sql.DataSource; - -@SpringJUnitConfig -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class WalletJDBCRepositoryTest { - @Autowired - WalletJDBCRepository walletJDBCRepository; - @Autowired - DataSource dataSource; - - @Test - @DisplayName("고객 id와 바우처 id 정보를 함께 저장할 수 있다.") - void save() { - } - - @Test - @DisplayName("고객 id로 고객이 가진 바우처 id를 가져올 수 있다.") - void findAllVoucherByCustomerId() { - } - - @Test - @DisplayName("함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 있다.") - void delete() { - } - - @Test - @DisplayName("바우처 id로 바우처를 가진 고객 id를 가져올 수 있다.") - void findCustomerByVoucherId() { - } - - @Configuration - @ComponentScan( - basePackages = {"com.programmers.vouchermanagement.wallet.repository"} - ) - static class Config { - @Bean - public DataSource dataSource() { - var dataSource = DataSourceBuilder.create() - .url("jdbc:mysql://localhost:3306/test") - .username("root") - .password("980726") - .type(HikariDataSource.class) - .build(); - dataSource.setMaximumPoolSize(1000); - dataSource.setMinimumIdle(100); - return dataSource; - } - - @Bean - public JdbcTemplate jdbcTemplate(DataSource dataSource) { - return new JdbcTemplate(dataSource); - } - - @Bean - public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { - return new NamedParameterJdbcTemplate(jdbcTemplate); - } - } -} \ No newline at end of file From 7853fff5e235d90ca4f696b5605ed1c0d0dbb949 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 01:18:33 +0900 Subject: [PATCH 142/383] enhance: set unique value(voucher_id) at ownership table --- src/main/resources/schema.sql | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 572e9fb1b6..a4da94b1eb 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -14,9 +14,8 @@ CREATE TABLE vouchers created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ); -CREATE TABLE voucher_customer_own_info +CREATE TABLE ownership ( - id INT PRIMARY KEY AUTO_INCREMENT, - customer_id BINARY(16) NOT NULL REFERENCES customers (id) ON DELETE CASCADE, - voucher_id BINARY(16) NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE + voucher_id BINARY(16) PRIMARY KEY NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE, + customer_id BINARY(16) NOT NULL REFERENCES customers (id) ON DELETE CASCADE ); \ No newline at end of file From 59b97e47c51da77595a906234c284b948b3c3a00 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:31:11 +0900 Subject: [PATCH 143/383] feat: implement DomainMapper --- .../repository/CustomerJDBCRepository.java | 25 ++----- .../vouchermanagement/util/DomainMapper.java | 67 +++++++++++++++++++ .../repository/VoucherJDBCRepository.java | 41 ++++-------- 3 files changed, 85 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 5ef9a15f58..2350aec21b 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -1,17 +1,15 @@ package com.programmers.vouchermanagement.customer.repository; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.util.DomainMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Primary; -import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; import java.nio.ByteBuffer; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.UUID; @Repository @@ -20,17 +18,13 @@ public class CustomerJDBCRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerJDBCRepository.class); private static final String FIND_ALL_BLACK_CUSTOMER_QUERY = "SELECT * FROM test.customers WHERE black = TRUE"; private static final String INSERT_QUERY = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; - private static final RowMapper customerRowMapper = (resultSet, i) -> { - UUID id = toUUID(resultSet.getBytes("id")); - String name = resultSet.getString("name"); - boolean isBlack = resultSet.getBoolean("black"); - return new Customer(id, name, isBlack); - }; private final NamedParameterJdbcTemplate jdbcTemplate; + private final DomainMapper domainMapper; - public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { + public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapper domainMapper) { this.jdbcTemplate = jdbcTemplate; + this.domainMapper = domainMapper; } static UUID toUUID(byte[] bytes) { @@ -38,21 +32,14 @@ static UUID toUUID(byte[] bytes) { return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); } - private Map toParamMap(Customer customer) { - Map paramMap = new HashMap<>(); - paramMap.put("id", customer.getCustomerId().toString().getBytes()); - paramMap.put("name", customer.getName()); - paramMap.put("black", customer.isBlack()); - return paramMap; - } @Override public List findAllBlackCustomer() { - return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER_QUERY, customerRowMapper); + return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER_QUERY, domainMapper.customerRowMapper); } public void save(Customer customer) { - int update = jdbcTemplate.update(INSERT_QUERY, toParamMap(customer)); + int update = jdbcTemplate.update(INSERT_QUERY, domainMapper.customerToParamMap(customer)); if (update != 1) { throw new RuntimeException("Noting was inserted"); } diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java new file mode 100644 index 0000000000..296664aba6 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -0,0 +1,67 @@ +package com.programmers.vouchermanagement.util; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.wallet.domain.Ownership; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Component +public class DomainMapper { + public final RowMapper ownershipRowMapper = (resultSet, i) -> { + UUID voucherId = toUUID(resultSet.getBytes("voucher_id")); + UUID customerId = toUUID(resultSet.getBytes("customer_id")); + return new Ownership(voucherId, customerId); + }; + public final RowMapper voucherRowMapper = (resultSet, i) -> { + UUID id = toUUID(resultSet.getBytes("id")); + BigDecimal discountValue = resultSet.getBigDecimal("discount_value"); + String voucherTypeStr = resultSet.getString("type"); + + return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); + }; + public final RowMapper customerRowMapper = (resultSet, i) -> { + UUID id = toUUID(resultSet.getBytes("id")); + String name = resultSet.getString("name"); + boolean isBlack = resultSet.getBoolean("black"); + + return new Customer(id, name, isBlack); + }; + public final RowMapper uuidRowMapper = (resultSet, i) -> + toUUID(resultSet.getBytes("id")); + + private static UUID toUUID(byte[] bytes) { + var byteBuffer = ByteBuffer.wrap(bytes); + return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); + } + + public Map customerToParamMap(Customer customer) { + Map paramMap = new HashMap<>(); + paramMap.put("id", customer.getCustomerId().toString().getBytes()); + paramMap.put("name", customer.getName()); + paramMap.put("black", customer.isBlack()); + return paramMap; + } + + public Map ownershipToParamMap(Ownership ownership) { + Map paramMap = new HashMap<>(); + paramMap.put("voucherId", ownership.voucherId().toString().getBytes()); + paramMap.put("customerId", ownership.customerId().toString().getBytes()); + return paramMap; + } + + public Map voucherToParamMap(Voucher voucher) { + Map paramMap = new HashMap<>(); + paramMap.put("id", voucher.getVoucherId().toString().getBytes()); + paramMap.put("type", voucher.getVoucherType().name()); + paramMap.put("discountValue", voucher.getDiscountValue()); + return paramMap; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 2519f4604d..f46bb786f4 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -1,18 +1,18 @@ package com.programmers.vouchermanagement.voucher.repository; +import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Primary; import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; -import java.math.BigDecimal; -import java.nio.ByteBuffer; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; @Repository @Primary @@ -23,35 +23,18 @@ public class VoucherJDBCRepository implements VoucherRepository { private static final String FIND_ALL_QUERY = "SELECT * FROM test.vouchers"; private static final String DELETE_VOUCHER_QUERY = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; private static final String UPDATE_VOUCHER_QUERY = "UPDATE test.vouchers SET type = :type, discount_value = :discountValue WHERE id = UUID_TO_BIN(:id)"; - private static final RowMapper voucherRowMapper = (resultSet, i) -> { - UUID id = toUUID(resultSet.getBytes("id")); - BigDecimal discountValue = resultSet.getBigDecimal("discount_value"); - String voucherTypeStr = resultSet.getString("type"); - - return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); - }; private final NamedParameterJdbcTemplate jdbcTemplate; + private final DomainMapper domainMapper; - public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { + public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapper domainMapper) { this.jdbcTemplate = jdbcTemplate; + this.domainMapper = domainMapper; } - static UUID toUUID(byte[] bytes) { - var byteBuffer = ByteBuffer.wrap(bytes); - return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); - } - - private Map toParamMap(Voucher voucher) { - Map paramMap = new HashMap<>(); - paramMap.put("id", voucher.getVoucherId().toString().getBytes()); - paramMap.put("type", voucher.getVoucherType().name()); - paramMap.put("discountValue", voucher.getDiscountValue()); - return paramMap; - } @Override public void save(Voucher voucher) { - int update = jdbcTemplate.update(INSERT_QUERY, toParamMap(voucher)); + int update = jdbcTemplate.update(INSERT_QUERY, domainMapper.voucherToParamMap(voucher)); if (update != 1) { throw new RuntimeException("Noting was inserted"); } @@ -59,7 +42,7 @@ public void save(Voucher voucher) { @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL_QUERY, voucherRowMapper); + return jdbcTemplate.query(FIND_ALL_QUERY, domainMapper.voucherRowMapper); } @Override @@ -67,7 +50,7 @@ public Optional findById(UUID id) { try { return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID_QUERY, Collections.singletonMap("id", id.toString().getBytes()), - voucherRowMapper)); + domainMapper.voucherRowMapper)); } catch (EmptyResultDataAccessException e) { logger.error("Got empty result", e); return Optional.empty(); @@ -84,7 +67,7 @@ public void delete(UUID id) { @Override public void update(Voucher voucher) { - int update = jdbcTemplate.update(UPDATE_VOUCHER_QUERY, toParamMap(voucher)); + int update = jdbcTemplate.update(UPDATE_VOUCHER_QUERY, domainMapper.voucherToParamMap(voucher)); if (update != 1) { throw new RuntimeException("Noting was updated"); } From 9d5e45bbf19f4f4da8e763c008769af1ec499b84 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:31:42 +0900 Subject: [PATCH 144/383] feat: implement Ownership --- .../vouchermanagement/wallet/domain/Ownership.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/domain/Ownership.java diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/domain/Ownership.java b/src/main/java/com/programmers/vouchermanagement/wallet/domain/Ownership.java new file mode 100644 index 0000000000..14caf12640 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/domain/Ownership.java @@ -0,0 +1,6 @@ +package com.programmers.vouchermanagement.wallet.domain; + +import java.util.UUID; + +public record Ownership(UUID voucherId, UUID customerId) { +} From 2aac2891b11808d362ebc2250fb5edf87c809be4 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:35:06 +0900 Subject: [PATCH 145/383] enhance: apply Ownership and change return value of WalletRepository's methods --- .../wallet/repository/WalletRepository.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java index a31127a5a0..b57e677564 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java @@ -1,18 +1,19 @@ package com.programmers.vouchermanagement.wallet.repository; -import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.wallet.domain.Ownership; import java.util.List; import java.util.Optional; import java.util.UUID; public interface WalletRepository { - void save(UUID voucherId, UUID customerId); + void save(Ownership ownership); - List findAllVoucherByCustomerId(UUID customerId); + List findAllVoucherByCustomerId(UUID customerId); - void delete(UUID voucherId, UUID customerId); + void delete(Ownership ownership); - Optional findCustomerByVoucherId(UUID voucherId); + Optional findCustomerByVoucherId(UUID voucherId); + + void deleteAll(); } From 16a5495ebf99c84ea865a681b75a44e2cfad097d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:35:22 +0900 Subject: [PATCH 146/383] feat: implement WalletJDBCRepository --- .../repository/WalletJDBCRepository.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java new file mode 100644 index 0000000000..2094083523 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -0,0 +1,71 @@ +package com.programmers.vouchermanagement.wallet.repository; + +import com.programmers.vouchermanagement.util.DomainMapper; +import com.programmers.vouchermanagement.wallet.domain.Ownership; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Repository +public class WalletJDBCRepository implements WalletRepository { + private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepository.class); + private static final String INSERT_QUERY = "INSERT INTO test.ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucherId), UUID_TO_BIN(:customerId))"; + private static final String DELETE_OWNERSHIP_QUERY = "DELETE FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:voucherId) AND customer_id = UUID_TO_BIN(:customerId)"; + private static final String DELETE_ALL_QUERY = "TRUNCATE TABLE test.ownership"; + private static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY = "SELECT voucher_id as id FROM test.ownership WHERE customer_id = UUID_TO_BIN(:id)"; + private static final String FIND_CUSTOMER_BY_VOUCHER_ID_QUERY = "SELECT customer_id as id FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; + private final NamedParameterJdbcTemplate jdbcTemplate; + private final DomainMapper domainMapper; + + public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapper domainMapper) { + this.jdbcTemplate = jdbcTemplate; + this.domainMapper = domainMapper; + } + + @Override + public void save(Ownership ownership) { + int update = jdbcTemplate.update(INSERT_QUERY, domainMapper.ownershipToParamMap(ownership)); + if (update != 1) { + throw new RuntimeException("Noting was inserted"); + } + } + + @Override + public List findAllVoucherByCustomerId(UUID customerId) { + return jdbcTemplate.query(FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY, + Collections.singletonMap("id", customerId.toString().getBytes()), + domainMapper.uuidRowMapper); + } + + @Override + public void delete(Ownership ownership) { + int update = jdbcTemplate.update(DELETE_OWNERSHIP_QUERY, domainMapper.ownershipToParamMap(ownership)); + if (update != 1) { + throw new RuntimeException("Noting was deleted"); + } + } + + @Override + public Optional findCustomerByVoucherId(UUID voucherId) { + try { + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID_QUERY, + Collections.singletonMap("id", voucherId.toString().getBytes()), + domainMapper.uuidRowMapper)); + } catch (EmptyResultDataAccessException e) { + logger.error("Got empty result", e); + return Optional.empty(); + } + } + + @Override + public void deleteAll() { + jdbcTemplate.update(DELETE_ALL_QUERY, Collections.emptyMap()); + } +} From a2737c52c185b8eadb757162d3d0f86f495127f2 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:35:34 +0900 Subject: [PATCH 147/383] test: test WalletJDBCRepository --- .../repository/WalletJDBCRepositoryTest.java | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java new file mode 100644 index 0000000000..f272a952e4 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -0,0 +1,200 @@ +package com.programmers.vouchermanagement.wallet.repository; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.repository.CustomerJDBCRepository; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.repository.VoucherJDBCRepository; +import com.programmers.vouchermanagement.wallet.domain.Ownership; +import com.zaxxer.hikari.HikariDataSource; +import org.junit.jupiter.api.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringJUnitConfig +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class WalletJDBCRepositoryTest { + private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepositoryTest.class); + @Autowired + WalletJDBCRepository walletJDBCRepository; + @Autowired + VoucherJDBCRepository voucherJDBCRepository; + @Autowired + CustomerJDBCRepository customerJDBCRepository; + @Autowired + DataSource dataSource; + + @AfterAll + void cleanTableAfterTest() { + walletJDBCRepository.deleteAll(); + } + + @Test + @Order(1) + @DisplayName("의존성 주입 테스트.") + void injectionTest() { + assertThat(walletJDBCRepository).isNotNull(); + assertThat(voucherJDBCRepository).isNotNull(); + assertThat(customerJDBCRepository).isNotNull(); + } + + @Test + @DisplayName("고객 id와 바우처 id 정보를 함께 저장할 수 있다.") + void saveSucceed() { + Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + voucherJDBCRepository.save(newVoucher); + Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인"); + customerJDBCRepository.save(newCustomer); + + Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), newCustomer.getCustomerId()); + walletJDBCRepository.save(newOwnership); + } + + @Test + @DisplayName("이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") + void saveAllocatedVoucherFail() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + Customer customer = new Customer(UUID.randomUUID(), "바우처 주인12"); + customerJDBCRepository.save(customer); + + Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); + walletJDBCRepository.save(newOwnership); + + Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인212"); + customerJDBCRepository.save(newCustomer); + + Ownership newOwnership2 = new Ownership(voucher.getVoucherId(), newCustomer.getCustomerId()); + RuntimeException exception = assertThrows(RuntimeException.class, () -> { + walletJDBCRepository.save(newOwnership2); + }); + System.err.println(exception.getMessage()); + } + + @Test + @DisplayName("고객 id에 해당하는 고객이 없다면, 고객에게 바우처를 할당할 수 없다.") + void saveNonExistCustomerFail() { + Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + voucherJDBCRepository.save(newVoucher); + UUID nonExistCustomer = UUID.randomUUID(); + + Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), nonExistCustomer); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(newOwnership)); + } + + @Test + @DisplayName("바우처 id에 해당하는 바우처가 없다면, 바우처를 고객에게 할당할 수 없다.") + void saveNonExistVoucherFail() { + UUID nonExistVoucher = UUID.randomUUID(); + Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인3"); + customerJDBCRepository.save(newCustomer); + + Ownership newOwnership = new Ownership(nonExistVoucher, newCustomer.getCustomerId()); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(newOwnership)); + } + + @Test + @DisplayName("고객 id로 고객이 가진 바우처 id를 가져올 수 있다.") + void findAllVoucherByCustomerId() { + Customer customer = new Customer(UUID.randomUUID(), "바우처 주인B"); + customerJDBCRepository.save(customer); + for (int i = 1; i < 6; i++) { + Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(i), VoucherType.FIXED); + voucherJDBCRepository.save(newVoucher); + Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), customer.getCustomerId()); + walletJDBCRepository.save(newOwnership); + } + + assertThat(walletJDBCRepository.findAllVoucherByCustomerId(customer.getCustomerId()).isEmpty()).isFalse(); + } + + @Test + @DisplayName("함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 있다.") + void delete() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + Customer customer = new Customer(UUID.randomUUID(), "바우처 주인1122"); + customerJDBCRepository.save(customer); + + Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); + walletJDBCRepository.save(newOwnership); + + walletJDBCRepository.delete(newOwnership); + } + + @Test + @DisplayName("바우처 id로 바우처를 가진 고객 id를 가져올 수 있다.") + void findCustomerByVoucherId() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + Customer customer = new Customer(UUID.randomUUID(), "r1sdgd2r"); + customerJDBCRepository.save(customer); + Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); + walletJDBCRepository.save(newOwnership); + + Optional customerId = walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()); + assertThat(customerId.isPresent()).isTrue(); + assertThat(customerId.get()).isEqualTo(customer.getCustomerId()); + } + + @Test + @DisplayName("바우처를 지우면 바우처 소유 정보가 사라진다.") + void autoDeleteAfterVoucherDelete() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + Customer customer = new Customer(UUID.randomUUID(), "바우처DFAFsdSD"); + customerJDBCRepository.save(customer); + Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); + walletJDBCRepository.save(newOwnership); + + voucherJDBCRepository.delete(voucher.getVoucherId()); + + assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId())).isEmpty(); + } + + @Configuration + @ComponentScan( + basePackages = {"com.programmers.vouchermanagement"} + ) + static class Config { + @Bean + public DataSource dataSource() { + var dataSource = DataSourceBuilder.create() + .url("jdbc:mysql://localhost:3306/test") + .username("root") + .password("980726") + .type(HikariDataSource.class) + .build(); + dataSource.setMaximumPoolSize(1000); + dataSource.setMinimumIdle(100); + return dataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + return new NamedParameterJdbcTemplate(jdbcTemplate); + } + } +} \ No newline at end of file From d2b6a512f99f7c2cd2e09f1dbbbd63465f190600 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:37:08 +0900 Subject: [PATCH 148/383] feat: add deleteAll at VoucherRepository and its implementation --- .../voucher/repository/VoucherFileRepository.java | 7 +++++++ .../voucher/repository/VoucherInMemoryRepository.java | 6 ++++++ .../voucher/repository/VoucherJDBCRepository.java | 6 ++++++ .../voucher/repository/VoucherRepository.java | 2 ++ 4 files changed, 21 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 967b51bd9c..2589fc3f09 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -63,6 +63,13 @@ public void delete(UUID id) { saveFile(); } + @Override + public void deleteAll() { + if (!vouchers.isEmpty()) + vouchers.clear(); + saveFile(); + } + @Override public void update(Voucher voucher) { Optional.ofNullable(vouchers.get(voucher.getVoucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index 70f1582815..e447d73f9c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -35,6 +35,12 @@ public void delete(UUID id) { Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException("Noting was deleted")); } + @Override + public void deleteAll() { + if (!vouchers.isEmpty()) + vouchers.clear(); + } + @Override public void update(Voucher voucher) { Optional.ofNullable(vouchers.get(voucher.getVoucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index f46bb786f4..5d0c205b6e 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -22,6 +22,7 @@ public class VoucherJDBCRepository implements VoucherRepository { private static final String FIND_BY_ID_QUERY = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; private static final String FIND_ALL_QUERY = "SELECT * FROM test.vouchers"; private static final String DELETE_VOUCHER_QUERY = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; + private static final String DELETE_ALL_QUERY = "TRUNCATE TABLE test.vouchers"; private static final String UPDATE_VOUCHER_QUERY = "UPDATE test.vouchers SET type = :type, discount_value = :discountValue WHERE id = UUID_TO_BIN(:id)"; private final NamedParameterJdbcTemplate jdbcTemplate; private final DomainMapper domainMapper; @@ -65,6 +66,11 @@ public void delete(UUID id) { } } + @Override + public void deleteAll() { + jdbcTemplate.update(DELETE_ALL_QUERY, Collections.emptyMap()); + } + @Override public void update(Voucher voucher) { int update = jdbcTemplate.update(UPDATE_VOUCHER_QUERY, domainMapper.voucherToParamMap(voucher)); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index 90ff74574d..073228c95f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -15,5 +15,7 @@ public interface VoucherRepository { void delete(UUID id); + void deleteAll(); + void update(Voucher voucher); } From 3006d66d5f18e186186f42f9dba47ffcd992c061 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:37:57 +0900 Subject: [PATCH 149/383] enhance: mark foreign key at ownership schema --- src/main/resources/schema.sql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index a4da94b1eb..b315654fb7 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -16,6 +16,8 @@ CREATE TABLE vouchers CREATE TABLE ownership ( - voucher_id BINARY(16) PRIMARY KEY NOT NULL REFERENCES vouchers (id) ON DELETE CASCADE, - customer_id BINARY(16) NOT NULL REFERENCES customers (id) ON DELETE CASCADE + voucher_id BINARY(16) PRIMARY KEY, + customer_id BINARY(16), + FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, + FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE ); \ No newline at end of file From ea76b226b1bfcb83fa4881a8e97379f13c11f0bf Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 14:38:54 +0900 Subject: [PATCH 150/383] test: test a findById method of VoucherJDBCRepository --- .../repository/VoucherJDBCRepositoryTest.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index 30d8890353..cf88df2d9b 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -75,6 +75,21 @@ void findAllVoucherSucceed() { @Test @Order(5) + @DisplayName("바우처를 아이디로 조회할 수 있다.") + void findVoucherByIdSucceed() { + Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(1234), VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getVoucherId()); + + assertThat(retrievedVoucher.isPresent()).isTrue(); + assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(voucher.getVoucherId()); + assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(voucher.getDiscountValue()); + assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(voucher.getVoucherType()); + } + + @Test + @Order(6) @DisplayName("바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); @@ -86,18 +101,16 @@ void deleteVoucherSucceed() { } @Test - @Order(6) + @Order(7) @DisplayName("없는 바우처를 삭제하면 실패한다.") void deleteNonExistVoucherFail() { UUID NonExistVoucherId = UUID.randomUUID(); - assertThrows(RuntimeException.class, () -> { - voucherJDBCRepository.delete(NonExistVoucherId); - }); + assertThrows(RuntimeException.class, () -> voucherJDBCRepository.delete(NonExistVoucherId)); } @Test - @Order(7) + @Order(8) @DisplayName("바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); @@ -114,7 +127,7 @@ void updateVoucherSucceed() { @Configuration @ComponentScan( - basePackages = {"com.programmers.vouchermanagement.voucher.repository"} + basePackages = {"com.programmers.vouchermanagement"} ) static class Config { @Bean From 0253997af1e714233b80848ea754aeaf225965e5 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 15:35:43 +0900 Subject: [PATCH 151/383] refactor: change discountValue type from BigDecimal to long --- .../consoleapp/io/ConsoleManager.java | 27 +++++++++---------- .../vouchermanagement/util/DomainMapper.java | 2 +- .../voucher/domain/Voucher.java | 6 ++--- .../voucher/dto/CreateVoucherRequest.java | 4 +-- .../voucher/dto/VoucherResponse.java | 11 ++++---- .../repository/VoucherFileRepository.java | 5 ++-- 6 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index de9bf91675..95084676c8 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,21 +1,19 @@ package com.programmers.vouchermanagement.consoleapp.io; -import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; - -import java.math.BigDecimal; -import java.util.List; - -import org.beryx.textio.TextIO; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.util.Validator; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import org.beryx.textio.TextIO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; @Component public class ConsoleManager { @@ -73,11 +71,10 @@ public CreateVoucherRequest instructCreate() { return new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE); }); - String discountValueInput = textIO.newStringInputReader() + String discountValueStr = textIO.newStringInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); - BigDecimal discountValue = new BigDecimal(discountValueInput); - Validator.validateDiscountValue(voucherType, discountValue); - return new CreateVoucherRequest(discountValue, voucherType); + Validator.validateDiscountValue(voucherType, discountValueStr); + return new CreateVoucherRequest(Long.parseLong(discountValueStr), voucherType); } public void printCreateResult(VoucherResponse voucherResponse) { @@ -115,7 +112,7 @@ private String formatVoucherDTO(VoucherResponse voucherResponse) { .formatted(voucherResponse.getVoucherId(), voucherResponse.getVoucherTypeName(), voucherResponse.getDiscountValue() + - (voucherResponse.isPercentVoucher() ? PERCENTAGE : EMPTY)); + (voucherResponse.isPercentVoucher() ? PERCENTAGE : EMPTY)); } public void printExit() { diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index 296664aba6..842a369649 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -22,7 +22,7 @@ public class DomainMapper { }; public final RowMapper voucherRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes("id")); - BigDecimal discountValue = resultSet.getBigDecimal("discount_value"); + long discountValue = resultSet.getLong("discount_value"); String voucherTypeStr = resultSet.getString("type"); return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 104eba2138..ca78825049 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -5,10 +5,10 @@ public class Voucher { private final UUID voucherId; - private final BigDecimal discountValue; + private final long discountValue; private final VoucherType voucherType; - public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { + public Voucher(UUID voucherId, long discountValue, VoucherType voucherType) { this.voucherId = voucherId; this.voucherType = voucherType; this.discountValue = discountValue; @@ -18,7 +18,7 @@ public UUID getVoucherId() { return voucherId; } - public BigDecimal getDiscountValue() { + public long getDiscountValue() { return discountValue; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java index 69f62dea49..6868664618 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java @@ -1,8 +1,6 @@ package com.programmers.vouchermanagement.voucher.dto; -import java.math.BigDecimal; - import com.programmers.vouchermanagement.voucher.domain.VoucherType; -public record CreateVoucherRequest(BigDecimal discountValue, VoucherType voucherType) { +public record CreateVoucherRequest(long discountValue, VoucherType voucherType) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java index a8fe420d5d..f9077fcd52 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -1,17 +1,16 @@ package com.programmers.vouchermanagement.voucher.dto; -import java.math.BigDecimal; -import java.util.UUID; - import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import java.util.UUID; + public class VoucherResponse { private final UUID voucherId; - private final BigDecimal discountValue; + private final long discountValue; private final VoucherType voucherType; - private VoucherResponse(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { + private VoucherResponse(UUID voucherId, long discountValue, VoucherType voucherType) { this.voucherId = voucherId; this.discountValue = discountValue; this.voucherType = voucherType; @@ -25,7 +24,7 @@ public UUID getVoucherId() { return voucherId; } - public BigDecimal getDiscountValue() { + public long getDiscountValue() { return discountValue; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 2589fc3f09..a2f41c121b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -13,7 +13,6 @@ import java.io.FileWriter; import java.io.IOException; import java.io.UncheckedIOException; -import java.math.BigDecimal; import java.util.*; @Repository @@ -97,7 +96,7 @@ private void loadVouchers(Map[] voucherObjects) { private Voucher objectToVoucher(Map voucherObject) { UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(VOUCHER_ID_KEY))); - BigDecimal discountValue = new BigDecimal(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); + long discountValue = Long.parseLong(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) .orElseThrow(() -> { @@ -127,7 +126,7 @@ public void saveFile() { private HashMap voucherToObject(Voucher voucher) { HashMap voucherObject = new HashMap<>(); voucherObject.put(VOUCHER_ID_KEY, voucher.getVoucherId().toString()); - voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue().toString()); + voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); voucherObject.put(VOUCHER_TYPE_KEY, voucher.getVoucherType().name()); return voucherObject; } From aa9004187ee13b7dc31c02d52fbdcdb9fe363c94 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 15:36:33 +0900 Subject: [PATCH 152/383] feat: validate if discount value in long type boundary --- .../vouchermanagement/util/Validator.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/Validator.java b/src/main/java/com/programmers/vouchermanagement/util/Validator.java index 83cf951cc1..51454f133e 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/Validator.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Validator.java @@ -1,41 +1,46 @@ package com.programmers.vouchermanagement.util; -import java.math.BigDecimal; - +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; - public class Validator { private static final Logger logger = LoggerFactory.getLogger(Validator.class); - - //constants - private static final int COMPARATOR_FLAG = 0; - private static final BigDecimal MAX_PERCENT = BigDecimal.valueOf(100); + private static final long MAX_LONG_LENGTH = String.valueOf(Long.MAX_VALUE).length(); //messages private static final String INVALID_DISCOUNT_AMOUNT_MESSAGE = "Input should be a number greater than 0"; private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = "Input should be a number greater than 0 and smaller than 100"; + private static final String INVALID_DISCOUNT_VALUE_MESSAGE = + "Input should be a number greater than 0 and smaller than 999999999999999999(length: 18)"; - public static void validateDiscountValue(VoucherType voucherType, BigDecimal discountValue) { + public static void validateDiscountValue(VoucherType voucherType, String discountValueStr) { + validateLongBoundary(discountValueStr); + long discountValue = Long.parseLong(discountValueStr); switch (voucherType) { case FIXED -> validateDiscountAmount(discountValue); case PERCENT -> validateDiscountPercent(discountValue); } } - private static void validateDiscountAmount(BigDecimal discountAmount) { - if (discountAmount.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG) { + private static void validateLongBoundary(String discountAmount) { + if (MAX_LONG_LENGTH <= discountAmount.length()) { + logger.error(INVALID_DISCOUNT_VALUE_MESSAGE); + throw new IllegalArgumentException(INVALID_DISCOUNT_VALUE_MESSAGE); + } + } + + private static void validateDiscountAmount(long discountAmount) { + if (discountAmount <= 0) { logger.error(INVALID_DISCOUNT_AMOUNT_MESSAGE); throw new IllegalArgumentException(INVALID_DISCOUNT_AMOUNT_MESSAGE); } } - private static void validateDiscountPercent(BigDecimal discountPercent) { - if (discountPercent.compareTo(BigDecimal.ZERO) <= COMPARATOR_FLAG || discountPercent.compareTo(MAX_PERCENT) > COMPARATOR_FLAG) { + private static void validateDiscountPercent(long discountPercent) { + if (discountPercent <= 0 || discountPercent > 100) { logger.error(INVALID_DISCOUNT_PERCENT_MESSAGE); throw new IllegalArgumentException(INVALID_DISCOUNT_PERCENT_MESSAGE); } From 85ea58ba600221e7cfc65db30d30a0d10b48132f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 15:38:32 +0900 Subject: [PATCH 153/383] style: fix INVALID_DISCOUNT_VALUE_MESSAGE --- .../java/com/programmers/vouchermanagement/util/Validator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/Validator.java b/src/main/java/com/programmers/vouchermanagement/util/Validator.java index 51454f133e..e91286fae8 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/Validator.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Validator.java @@ -14,7 +14,7 @@ public class Validator { private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = "Input should be a number greater than 0 and smaller than 100"; private static final String INVALID_DISCOUNT_VALUE_MESSAGE = - "Input should be a number greater than 0 and smaller than 999999999999999999(length: 18)"; + "Input should be a number greater than 0 and smaller than 999,999,999,999,999,999(length: 18)"; public static void validateDiscountValue(VoucherType voucherType, String discountValueStr) { validateLongBoundary(discountValueStr); From a751bc9c9964dff160d0a87adf1d3f41e26c5d47 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 15:41:32 +0900 Subject: [PATCH 154/383] refactor: change BigDecimal to long --- .../repository/VoucherInMemoryRepositoryTest.java | 7 +++---- .../repository/VoucherJDBCRepositoryTest.java | 14 ++++++-------- .../voucher/service/VoucherServiceTest.java | 7 +++---- .../repository/WalletJDBCRepositoryTest.java | 15 +++++++-------- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java index da433120ae..fc937c8880 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java @@ -6,7 +6,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; -import java.math.BigDecimal; import java.util.Optional; import java.util.UUID; @@ -20,7 +19,7 @@ class VoucherInMemoryRepositoryTest { @Test @DisplayName("바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherInMemoryRepository.save(voucher); voucherInMemoryRepository.delete(voucher.getVoucherId()); @@ -41,10 +40,10 @@ void deleteNonExistVoucherFail() { @Test @DisplayName("바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherInMemoryRepository.save(voucher); - Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), BigDecimal.valueOf(100), VoucherType.PERCENT); + Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), 100, VoucherType.PERCENT); voucherInMemoryRepository.update(updatedVoucher); Optional retrievedVoucher = voucherInMemoryRepository.findById(voucher.getVoucherId()); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index cf88df2d9b..a36ead0113 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -14,7 +14,6 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import javax.sql.DataSource; -import java.math.BigDecimal; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -42,7 +41,7 @@ public void testHikariConnectionPool() { @Order(2) @DisplayName("고정 금액 할인 바우처를 추가할 수 있다.") void saveFixedAmountVoucherSucceed() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); + Voucher newVoucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(newVoucher); Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.getVoucherId()); @@ -55,7 +54,7 @@ void saveFixedAmountVoucherSucceed() { @Order(3) @DisplayName("퍼센트 할인 바우처를 추가할 수 있다.") void savePercentVoucherSucceed() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(50), VoucherType.PERCENT); + Voucher newVoucher = new Voucher(UUID.randomUUID(), 50, VoucherType.PERCENT); voucherJDBCRepository.save(newVoucher); Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.getVoucherId()); @@ -77,7 +76,7 @@ void findAllVoucherSucceed() { @Order(5) @DisplayName("바우처를 아이디로 조회할 수 있다.") void findVoucherByIdSucceed() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(1234), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 1234, VoucherType.FIXED); voucherJDBCRepository.save(voucher); Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getVoucherId()); @@ -92,7 +91,7 @@ void findVoucherByIdSucceed() { @Order(6) @DisplayName("바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); voucherJDBCRepository.delete(voucher.getVoucherId()); @@ -113,10 +112,10 @@ void deleteNonExistVoucherFail() { @Order(8) @DisplayName("바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(5555), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), BigDecimal.valueOf(100), VoucherType.PERCENT); + Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), 100, VoucherType.PERCENT); voucherJDBCRepository.update(updatedVoucher); Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getVoucherId()); @@ -153,5 +152,4 @@ public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTe return new NamedParameterJdbcTemplate(jdbcTemplate); } } - } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 230456e62c..1d8d6fcecd 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -11,7 +11,6 @@ import org.mockito.Mock; import org.springframework.test.context.junit.jupiter.SpringExtension; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.Optional; import java.util.UUID; @@ -41,7 +40,7 @@ void initTest() { @Test @DisplayName("고정 할인 금액 바우처 객체를 생성할 수 있다.") void createFixedAmountVoucherSucceed() { - CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(BigDecimal.valueOf(1000), VoucherType.FIXED); + CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(1000, VoucherType.FIXED); voucherService.createVoucher(createVoucherRequest); verify(voucherRepository, times(1)).save(any(Voucher.class)); @@ -50,7 +49,7 @@ void createFixedAmountVoucherSucceed() { @Test @DisplayName("퍼센트 할인 바우처 객체를 생성할 수 있다.") void createPercentDiscountVoucherSucceed() { - CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(BigDecimal.valueOf(100), VoucherType.PERCENT); + CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(100, VoucherType.PERCENT); voucherService.createVoucher(createVoucherRequest); verify(voucherRepository, times(1)).save(any(Voucher.class)); @@ -87,7 +86,7 @@ void deleteVoucherSucceed() { @Test @DisplayName("바우처를 업데이트할 수 있다.") void updateVoucherSucceed() { - voucherService.updateVoucher(new Voucher(UUID.randomUUID(), BigDecimal.valueOf(100), VoucherType.FIXED)); + voucherService.updateVoucher(new Voucher(UUID.randomUUID(), 100, VoucherType.FIXED)); verify(voucherRepository, times(1)).update(any(Voucher.class)); } diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index f272a952e4..788922635e 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -20,7 +20,6 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import javax.sql.DataSource; -import java.math.BigDecimal; import java.util.Optional; import java.util.UUID; @@ -58,7 +57,7 @@ void injectionTest() { @Test @DisplayName("고객 id와 바우처 id 정보를 함께 저장할 수 있다.") void saveSucceed() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + Voucher newVoucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(newVoucher); Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인"); customerJDBCRepository.save(newCustomer); @@ -70,7 +69,7 @@ void saveSucceed() { @Test @DisplayName("이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") void saveAllocatedVoucherFail() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처 주인12"); customerJDBCRepository.save(customer); @@ -91,7 +90,7 @@ void saveAllocatedVoucherFail() { @Test @DisplayName("고객 id에 해당하는 고객이 없다면, 고객에게 바우처를 할당할 수 없다.") void saveNonExistCustomerFail() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + Voucher newVoucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(newVoucher); UUID nonExistCustomer = UUID.randomUUID(); @@ -116,7 +115,7 @@ void findAllVoucherByCustomerId() { Customer customer = new Customer(UUID.randomUUID(), "바우처 주인B"); customerJDBCRepository.save(customer); for (int i = 1; i < 6; i++) { - Voucher newVoucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(i), VoucherType.FIXED); + Voucher newVoucher = new Voucher(UUID.randomUUID(), i, VoucherType.FIXED); voucherJDBCRepository.save(newVoucher); Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), customer.getCustomerId()); walletJDBCRepository.save(newOwnership); @@ -128,7 +127,7 @@ void findAllVoucherByCustomerId() { @Test @DisplayName("함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 있다.") void delete() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(333), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처 주인1122"); customerJDBCRepository.save(customer); @@ -142,7 +141,7 @@ void delete() { @Test @DisplayName("바우처 id로 바우처를 가진 고객 id를 가져올 수 있다.") void findCustomerByVoucherId() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); Customer customer = new Customer(UUID.randomUUID(), "r1sdgd2r"); customerJDBCRepository.save(customer); @@ -157,7 +156,7 @@ void findCustomerByVoucherId() { @Test @DisplayName("바우처를 지우면 바우처 소유 정보가 사라진다.") void autoDeleteAfterVoucherDelete() { - Voucher voucher = new Voucher(UUID.randomUUID(), BigDecimal.valueOf(555), VoucherType.FIXED); + Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처DFAFsdSD"); customerJDBCRepository.save(customer); From 29bb09d6b5de16bddf3115d4de0f913117beb801 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 16:26:36 +0900 Subject: [PATCH 155/383] refactor: change parameter ownership to voucher id --- .../vouchermanagement/util/DomainMapper.java | 7 ++++++- .../wallet/repository/WalletJDBCRepository.java | 6 +++--- .../wallet/repository/WalletRepository.java | 2 +- .../repository/WalletJDBCRepositoryTest.java | 14 ++++++++++++-- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index 842a369649..49da228648 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -7,7 +7,6 @@ import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; -import java.math.BigDecimal; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; @@ -57,6 +56,12 @@ public Map ownershipToParamMap(Ownership ownership) { return paramMap; } + public Map uuidToParamMap(UUID id) { + Map paramMap = new HashMap<>(); + paramMap.put("id", id.toString().getBytes()); + return paramMap; + } + public Map voucherToParamMap(Voucher voucher) { Map paramMap = new HashMap<>(); paramMap.put("id", voucher.getVoucherId().toString().getBytes()); diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 2094083523..f77d9b3c10 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -17,7 +17,7 @@ public class WalletJDBCRepository implements WalletRepository { private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepository.class); private static final String INSERT_QUERY = "INSERT INTO test.ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucherId), UUID_TO_BIN(:customerId))"; - private static final String DELETE_OWNERSHIP_QUERY = "DELETE FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:voucherId) AND customer_id = UUID_TO_BIN(:customerId)"; + private static final String DELETE_OWNERSHIP_QUERY = "DELETE FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; private static final String DELETE_ALL_QUERY = "TRUNCATE TABLE test.ownership"; private static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY = "SELECT voucher_id as id FROM test.ownership WHERE customer_id = UUID_TO_BIN(:id)"; private static final String FIND_CUSTOMER_BY_VOUCHER_ID_QUERY = "SELECT customer_id as id FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; @@ -45,8 +45,8 @@ public List findAllVoucherByCustomerId(UUID customerId) { } @Override - public void delete(Ownership ownership) { - int update = jdbcTemplate.update(DELETE_OWNERSHIP_QUERY, domainMapper.ownershipToParamMap(ownership)); + public void delete(UUID voucherId) { + int update = jdbcTemplate.update(DELETE_OWNERSHIP_QUERY, domainMapper.uuidToParamMap(voucherId)); if (update != 1) { throw new RuntimeException("Noting was deleted"); } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java index b57e677564..4d594565c4 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java @@ -11,7 +11,7 @@ public interface WalletRepository { List findAllVoucherByCustomerId(UUID customerId); - void delete(Ownership ownership); + void delete(UUID voucherID); Optional findCustomerByVoucherId(UUID voucherId); diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index 788922635e..a0c66440b7 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -125,7 +125,7 @@ void findAllVoucherByCustomerId() { } @Test - @DisplayName("함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 있다.") + @DisplayName("바우처 id를 통해 할당 정보를 삭제할 수 있다.") void delete() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); @@ -135,7 +135,17 @@ void delete() { Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); walletJDBCRepository.save(newOwnership); - walletJDBCRepository.delete(newOwnership); + walletJDBCRepository.delete(voucher.getVoucherId()); + } + + @Test + @DisplayName("바우처가 할당 정보가 없다면, 함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 없다.") + void deleteNonAllocatedVoucher() { + Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + assertThrows(RuntimeException.class, () -> { + walletJDBCRepository.delete(voucher.getVoucherId()); + }); } @Test From 0067c9929a36ee8c46ca0b846a65cd3fb640befb Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 17:05:30 +0900 Subject: [PATCH 156/383] refactor: change return value at WalletRepository --- .../repository/WalletJDBCRepository.java | 34 ++++++++++--------- .../wallet/repository/WalletRepository.java | 6 ++-- .../repository/WalletJDBCRepositoryTest.java | 18 +++++----- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index f77d9b3c10..2d0adf85d9 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -1,6 +1,8 @@ package com.programmers.vouchermanagement.wallet.repository; +import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.util.DomainMapper; +import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,8 +21,8 @@ public class WalletJDBCRepository implements WalletRepository { private static final String INSERT_QUERY = "INSERT INTO test.ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucherId), UUID_TO_BIN(:customerId))"; private static final String DELETE_OWNERSHIP_QUERY = "DELETE FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; private static final String DELETE_ALL_QUERY = "TRUNCATE TABLE test.ownership"; - private static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY = "SELECT voucher_id as id FROM test.ownership WHERE customer_id = UUID_TO_BIN(:id)"; - private static final String FIND_CUSTOMER_BY_VOUCHER_ID_QUERY = "SELECT customer_id as id FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; + private static final String FIND_CUSTOMER_BY_VOUCHER_ID_QUERY = "SELECT c.* FROM test.ownership as o JOIN test.customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)"; + private static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY = "SELECT v.* FROM test.ownership as o JOIN test.vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)"; private final NamedParameterJdbcTemplate jdbcTemplate; private final DomainMapper domainMapper; @@ -38,10 +40,22 @@ public void save(Ownership ownership) { } @Override - public List findAllVoucherByCustomerId(UUID customerId) { + public Optional findCustomerByVoucherId(UUID voucherId) { + try { + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID_QUERY, + Collections.singletonMap("id", voucherId.toString().getBytes()), + domainMapper.customerRowMapper)); + } catch (EmptyResultDataAccessException e) { + logger.error("Got empty result", e); + return Optional.empty(); + } + } + + @Override + public List findAllVoucherByCustomerId(UUID customerId) { return jdbcTemplate.query(FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY, Collections.singletonMap("id", customerId.toString().getBytes()), - domainMapper.uuidRowMapper); + domainMapper.voucherRowMapper); } @Override @@ -52,18 +66,6 @@ public void delete(UUID voucherId) { } } - @Override - public Optional findCustomerByVoucherId(UUID voucherId) { - try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID_QUERY, - Collections.singletonMap("id", voucherId.toString().getBytes()), - domainMapper.uuidRowMapper)); - } catch (EmptyResultDataAccessException e) { - logger.error("Got empty result", e); - return Optional.empty(); - } - } - @Override public void deleteAll() { jdbcTemplate.update(DELETE_ALL_QUERY, Collections.emptyMap()); diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java index 4d594565c4..1f1b1e0263 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java @@ -1,5 +1,7 @@ package com.programmers.vouchermanagement.wallet.repository; +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.wallet.domain.Ownership; import java.util.List; @@ -9,11 +11,11 @@ public interface WalletRepository { void save(Ownership ownership); - List findAllVoucherByCustomerId(UUID customerId); + List findAllVoucherByCustomerId(UUID customerId); void delete(UUID voucherID); - Optional findCustomerByVoucherId(UUID voucherId); + Optional findCustomerByVoucherId(UUID voucherId); void deleteAll(); } diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index a0c66440b7..5943e38386 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -59,7 +59,7 @@ void injectionTest() { void saveSucceed() { Voucher newVoucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(newVoucher); - Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인"); + Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인12ㅁ3"); customerJDBCRepository.save(newCustomer); Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), newCustomer.getCustomerId()); @@ -110,7 +110,7 @@ void saveNonExistVoucherFail() { } @Test - @DisplayName("고객 id로 고객이 가진 바우처 id를 가져올 수 있다.") + @DisplayName("고객 id로 고객이 가진 바우처들을 가져올 수 있다.") void findAllVoucherByCustomerId() { Customer customer = new Customer(UUID.randomUUID(), "바우처 주인B"); customerJDBCRepository.save(customer); @@ -149,18 +149,18 @@ void deleteNonAllocatedVoucher() { } @Test - @DisplayName("바우처 id로 바우처를 가진 고객 id를 가져올 수 있다.") + @DisplayName("바우처 id로 바우처를 가진 고객 정보를 가져올 수 있다.") void findCustomerByVoucherId() { Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Customer customer = new Customer(UUID.randomUUID(), "r1sdgd2r"); + Customer customer = new Customer(UUID.randomUUID(), "바우처 주인12345"); customerJDBCRepository.save(customer); - Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); - walletJDBCRepository.save(newOwnership); + Ownership ownership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); + walletJDBCRepository.save(ownership); - Optional customerId = walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()); - assertThat(customerId.isPresent()).isTrue(); - assertThat(customerId.get()).isEqualTo(customer.getCustomerId()); + Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()); + assertThat(retrievedCustomer.isPresent()).isTrue(); + assertThat(retrievedCustomer.get().getCustomerId()).isEqualTo(customer.getCustomerId()); } @Test From afca5faddc37009f398ac3f6b31fac82f3cbf27e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 17:06:50 +0900 Subject: [PATCH 157/383] style: format code at VoucherService --- .../vouchermanagement/voucher/service/VoucherService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 4ae2bc778d..f74be230ce 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -38,8 +38,6 @@ public List readAllVouchers() { public void readVoucherById(UUID voucherId) { voucherRepository.findById(voucherId); - - } public void deleteVoucher(UUID voucherId) { From db501477f1d212b562b650542c334ad05a02c732 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 19:09:37 +0900 Subject: [PATCH 158/383] test: test all case at WalletJDBCRepository --- .../repository/WalletJDBCRepositoryTest.java | 154 ++++++++++-------- 1 file changed, 84 insertions(+), 70 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index 5943e38386..237026ef49 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -24,13 +24,16 @@ import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertThrows; @SpringJUnitConfig @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class WalletJDBCRepositoryTest { - private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepositoryTest.class); + private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); + private final static UUID NON_EXISTENT_CUSTOMER_ID = UUID.randomUUID(); + @Autowired WalletJDBCRepository walletJDBCRepository; @Autowired @@ -39,143 +42,154 @@ class WalletJDBCRepositoryTest { CustomerJDBCRepository customerJDBCRepository; @Autowired DataSource dataSource; - - @AfterAll - void cleanTableAfterTest() { - walletJDBCRepository.deleteAll(); - } + @Autowired + NamedParameterJdbcTemplate jdbcTemplate; @Test @Order(1) - @DisplayName("의존성 주입 테스트.") + @DisplayName("🆗 의존성 주입 테스트.") void injectionTest() { - assertThat(walletJDBCRepository).isNotNull(); - assertThat(voucherJDBCRepository).isNotNull(); - assertThat(customerJDBCRepository).isNotNull(); + assertAll( + () -> assertThat(walletJDBCRepository).isNotNull(), + () -> assertThat(voucherJDBCRepository).isNotNull(), + () -> assertThat(customerJDBCRepository).isNotNull() + ); } @Test - @DisplayName("고객 id와 바우처 id 정보를 함께 저장할 수 있다.") - void saveSucceed() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); - voucherJDBCRepository.save(newVoucher); - Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인12ㅁ3"); - customerJDBCRepository.save(newCustomer); - - Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), newCustomer.getCustomerId()); + @DisplayName("🆗 고객에게 바우처를 할당할 수 있다.") + void save() { + Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + Customer customer = new Customer(UUID.randomUUID(), "바우처 주인"); + customerJDBCRepository.save(customer); + + Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); walletJDBCRepository.save(newOwnership); } @Test - @DisplayName("이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") - void saveAllocatedVoucherFail() { + @DisplayName("🚨 이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") + void saveAllocatedVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Customer customer = new Customer(UUID.randomUUID(), "바우처 주인12"); + Customer customer = new Customer(UUID.randomUUID(), "바우처를 가진 고객"); customerJDBCRepository.save(customer); - Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); - walletJDBCRepository.save(newOwnership); + walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); - Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인212"); - customerJDBCRepository.save(newCustomer); + Customer customer2 = new Customer(UUID.randomUUID(), "바우처를 가지지 못하는 고객"); + customerJDBCRepository.save(customer2); - Ownership newOwnership2 = new Ownership(voucher.getVoucherId(), newCustomer.getCustomerId()); - RuntimeException exception = assertThrows(RuntimeException.class, () -> { - walletJDBCRepository.save(newOwnership2); - }); - System.err.println(exception.getMessage()); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer2.getCustomerId()))); } @Test - @DisplayName("고객 id에 해당하는 고객이 없다면, 고객에게 바우처를 할당할 수 없다.") - void saveNonExistCustomerFail() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); - voucherJDBCRepository.save(newVoucher); - UUID nonExistCustomer = UUID.randomUUID(); - - Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), nonExistCustomer); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(newOwnership)); + @DisplayName("🚨 고객 id에 해당하는 고객이 없다면, 고객에게 바우처를 할당할 수 없다.") + void saveNonExistentCustomer() { + Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), NON_EXISTENT_CUSTOMER_ID))); } @Test - @DisplayName("바우처 id에 해당하는 바우처가 없다면, 바우처를 고객에게 할당할 수 없다.") - void saveNonExistVoucherFail() { - UUID nonExistVoucher = UUID.randomUUID(); - Customer newCustomer = new Customer(UUID.randomUUID(), "바우처 주인3"); - customerJDBCRepository.save(newCustomer); - - Ownership newOwnership = new Ownership(nonExistVoucher, newCustomer.getCustomerId()); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(newOwnership)); + @DisplayName("🚨 바우처 id에 해당하는 바우처가 없다면, 바우처를 고객에게 할당할 수 없다.") + void saveNonExistentVoucher() { + Customer customer = new Customer(UUID.randomUUID(), "바우처를 가지지 못한 고객"); + customerJDBCRepository.save(customer); + + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(NON_EXISTENT_VOUCHER_ID, customer.getCustomerId()))); } @Test - @DisplayName("고객 id로 고객이 가진 바우처들을 가져올 수 있다.") + @DisplayName("🚨 id에 해당하는 바우처와 고객이 모두 없다면, 바우처를 고객에게 할당할 수 없다.") + void saveNonExistentBoth() { + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(NON_EXISTENT_VOUCHER_ID, NON_EXISTENT_CUSTOMER_ID))); + } + + @Test + @DisplayName("🆗 고객 id로 고객이 가진 바우처들을 가져올 수 있다.") void findAllVoucherByCustomerId() { - Customer customer = new Customer(UUID.randomUUID(), "바우처 주인B"); + Customer customer = new Customer(UUID.randomUUID(), "조회하려는 바우처들의 주인"); customerJDBCRepository.save(customer); + for (int i = 1; i < 6; i++) { - Voucher newVoucher = new Voucher(UUID.randomUUID(), i, VoucherType.FIXED); - voucherJDBCRepository.save(newVoucher); - Ownership newOwnership = new Ownership(newVoucher.getVoucherId(), customer.getCustomerId()); - walletJDBCRepository.save(newOwnership); + Voucher voucher = new Voucher(UUID.randomUUID(), i, VoucherType.FIXED); + voucherJDBCRepository.save(voucher); + walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); } + // If the customer don't have any voucher, then return empty list. assertThat(walletJDBCRepository.findAllVoucherByCustomerId(customer.getCustomerId()).isEmpty()).isFalse(); } @Test - @DisplayName("바우처 id를 통해 할당 정보를 삭제할 수 있다.") + @DisplayName("🚨 고객에 대한 할당 정보가 없다면, 고객이 가진 바우처들을 가져올 수 없다.") + void findAllVoucherByNonExistentCustomerId() { + assertThat(walletJDBCRepository.findAllVoucherByCustomerId(NON_EXISTENT_CUSTOMER_ID).isEmpty()).isTrue(); + } + + @Test + @DisplayName("🆗 바우처 id를 통해 할당 정보를 삭제할 수 있다. 단, 바우처 자체는 삭제되지 않는다.") void delete() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Customer customer = new Customer(UUID.randomUUID(), "바우처 주인1122"); + Customer customer = new Customer(UUID.randomUUID(), "1개의 삭제될 바우처를 가진 주인"); customerJDBCRepository.save(customer); - Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); - walletJDBCRepository.save(newOwnership); + walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); walletJDBCRepository.delete(voucher.getVoucherId()); + + assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()).isEmpty()).isTrue(); + assertThat(voucherJDBCRepository.findById(voucher.getVoucherId()).isPresent()).isTrue(); } @Test - @DisplayName("바우처가 할당 정보가 없다면, 함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 없다.") + @DisplayName("🚨 바우처에 대한 할당 정보가 없다면, 함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 없다.") void deleteNonAllocatedVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - assertThrows(RuntimeException.class, () -> { - walletJDBCRepository.delete(voucher.getVoucherId()); - }); + + assertThrows(RuntimeException.class, () -> walletJDBCRepository.delete(voucher.getVoucherId())); } @Test - @DisplayName("바우처 id로 바우처를 가진 고객 정보를 가져올 수 있다.") + @DisplayName("🆗 바우처 id로 바우처를 가진 고객 정보를 가져올 수 있다.") void findCustomerByVoucherId() { Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Customer customer = new Customer(UUID.randomUUID(), "바우처 주인12345"); + Customer customer = new Customer(UUID.randomUUID(), "조회될 고객"); customerJDBCRepository.save(customer); - Ownership ownership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); - walletJDBCRepository.save(ownership); + + walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()); + assertThat(retrievedCustomer.isPresent()).isTrue(); assertThat(retrievedCustomer.get().getCustomerId()).isEqualTo(customer.getCustomerId()); } @Test - @DisplayName("바우처를 지우면 바우처 소유 정보가 사라진다.") + @DisplayName("🚨 바우처에 대한 할당 정보가 없다면, 바우처를 가진 고객 정보를 가져올 수 없다.") + void findCustomerByNonExistentVoucherId() { + assertThat(walletJDBCRepository.findCustomerByVoucherId(NON_EXISTENT_VOUCHER_ID).isEmpty()).isTrue(); + } + + @Test + @DisplayName("🆗 바우처 자체를 삭제하면, 바우처 소유 정보가 사라진다.") void autoDeleteAfterVoucherDelete() { Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Customer customer = new Customer(UUID.randomUUID(), "바우처DFAFsdSD"); + Customer customer = new Customer(UUID.randomUUID(), "삭제될 바우처를 가진 고객"); customerJDBCRepository.save(customer); - Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); - walletJDBCRepository.save(newOwnership); + + walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); voucherJDBCRepository.delete(voucher.getVoucherId()); - assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId())).isEmpty(); + assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()).isEmpty()).isTrue(); } @Configuration @@ -206,4 +220,4 @@ public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTe return new NamedParameterJdbcTemplate(jdbcTemplate); } } -} \ No newline at end of file +} From 59cc535fa3e858864af7d6fbf641a082fc42b6a6 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 19:16:08 +0900 Subject: [PATCH 159/383] test: test all case at WalletJDBCRepository --- .../wallet/repository/WalletJDBCRepositoryTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index 237026ef49..6a0af2c6db 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -8,8 +8,6 @@ import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; @@ -40,10 +38,6 @@ class WalletJDBCRepositoryTest { VoucherJDBCRepository voucherJDBCRepository; @Autowired CustomerJDBCRepository customerJDBCRepository; - @Autowired - DataSource dataSource; - @Autowired - NamedParameterJdbcTemplate jdbcTemplate; @Test @Order(1) From 7ef4aad47d264c2b80f4a93cf19f679210eae180 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 19:29:00 +0900 Subject: [PATCH 160/383] test: test all case at VoucherJDBCRepository --- .../repository/VoucherJDBCRepositoryTest.java | 72 ++++++++++--------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index a36ead0113..8d36354088 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -2,8 +2,11 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.zaxxer.hikari.HikariDataSource; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; @@ -22,25 +25,15 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @SpringJUnitConfig -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class VoucherJDBCRepositoryTest { + private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); @Autowired VoucherJDBCRepository voucherJDBCRepository; - @Autowired - DataSource dataSource; - - @Test - @Order(1) - @DisplayName("HikariConnectionPool 연결할 수 있다.") - public void testHikariConnectionPool() { - assertThat(dataSource.getClass().getName()).isEqualTo("com.zaxxer.hikari.HikariDataSource"); - } @Test - @Order(2) - @DisplayName("고정 금액 할인 바우처를 추가할 수 있다.") - void saveFixedAmountVoucherSucceed() { + @DisplayName("🆗 고정 금액 할인 바우처를 추가할 수 있다.") + void saveFixedAmountVoucher() { Voucher newVoucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(newVoucher); @@ -51,9 +44,8 @@ void saveFixedAmountVoucherSucceed() { } @Test - @Order(3) - @DisplayName("퍼센트 할인 바우처를 추가할 수 있다.") - void savePercentVoucherSucceed() { + @DisplayName("🆗 퍼센트 할인 바우처를 추가할 수 있다.") + void savePercentVoucher() { Voucher newVoucher = new Voucher(UUID.randomUUID(), 50, VoucherType.PERCENT); voucherJDBCRepository.save(newVoucher); @@ -64,18 +56,19 @@ void savePercentVoucherSucceed() { } @Test - @Order(4) - @DisplayName("모든 바우처를 조회할 수 있다.") - void findAllVoucherSucceed() { + @DisplayName("🆗 모든 바우처를 조회할 수 있다. 단, 없다면 빈 list를 반환한다.") + void findAllVoucher() { + for (int i = 1; i < 6; i++) + voucherJDBCRepository.save(new Voucher(UUID.randomUUID(), i * 100, VoucherType.PERCENT)); + List vouchers = voucherJDBCRepository.findAll(); assertThat(vouchers.isEmpty()).isFalse(); } @Test - @Order(5) - @DisplayName("바우처를 아이디로 조회할 수 있다.") - void findVoucherByIdSucceed() { + @DisplayName("🆗 바우처를 아이디로 조회할 수 있다.") + void findVoucherById() { Voucher voucher = new Voucher(UUID.randomUUID(), 1234, VoucherType.FIXED); voucherJDBCRepository.save(voucher); @@ -88,9 +81,16 @@ void findVoucherByIdSucceed() { } @Test - @Order(6) - @DisplayName("바우처를 아이디로 삭제할 수 있다.") - void deleteVoucherSucceed() { + @DisplayName("🚨 해당하는 바우처가 없다면, 바우처를 아이디로 조회할 수 없다.") + void findNonExistentVoucherById() { + Optional retrievedVoucher = voucherJDBCRepository.findById(NON_EXISTENT_VOUCHER_ID); + + assertThat(retrievedVoucher.isEmpty()).isTrue(); + } + + @Test + @DisplayName("🆗 바우처를 아이디로 삭제할 수 있다.") + void deleteVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); @@ -100,18 +100,14 @@ void deleteVoucherSucceed() { } @Test - @Order(7) - @DisplayName("없는 바우처를 삭제하면 실패한다.") - void deleteNonExistVoucherFail() { - UUID NonExistVoucherId = UUID.randomUUID(); - - assertThrows(RuntimeException.class, () -> voucherJDBCRepository.delete(NonExistVoucherId)); + @DisplayName("🚨 해당하는 바우처가 없다면, 바우처를 아이디로 삭제할 수 없다.") + void deleteNonExistentVoucher() { + assertThrows(RuntimeException.class, () -> voucherJDBCRepository.delete(NON_EXISTENT_VOUCHER_ID)); } @Test - @Order(8) - @DisplayName("바우처를 업데이트 할 수 있다.") - void updateVoucherSucceed() { + @DisplayName("🆗 바우처를 업데이트 할 수 있다.") + void updateVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); @@ -124,6 +120,12 @@ void updateVoucherSucceed() { assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(updatedVoucher.getVoucherType()); } + @Test + @DisplayName("🚨 해당하는 바우처가 없다면, 바우처를 업데이트 할 수 없다.") + void updateNonExistentVoucher() { + assertThrows(RuntimeException.class, () -> voucherJDBCRepository.update(new Voucher(NON_EXISTENT_VOUCHER_ID, 100, VoucherType.PERCENT))); + } + @Configuration @ComponentScan( basePackages = {"com.programmers.vouchermanagement"} From bbdb81bfc7db484375cff24aca31f9d48d6eae5e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 19:34:36 +0900 Subject: [PATCH 161/383] test: test all case at CustomerJDBCRepository --- .../repository/CustomerJDBCRepositoryTest.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 58d6bb38aa..324d1db945 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -25,23 +25,27 @@ class CustomerJDBCRepositoryTest { @Autowired CustomerJDBCRepository customerJDBCRepository; - @Autowired - DataSource dataSource; @Test - @DisplayName("블랙리스트를 조회할 수 있다.") + @DisplayName("🆗 블랙리스트를 조회할 수 있다. 단, 블랙 고객이 없는 경우 빈 list가 반환된다.") void findAllBlackCustomerSucceed() { - customerJDBCRepository.save(new Customer(UUID.randomUUID(), "이세희7", false)); - customerJDBCRepository.save(new Customer(UUID.randomUUID(), "이세희8", true)); - customerJDBCRepository.save(new Customer(UUID.randomUUID(), "이세희9", false)); + customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객1", false)); + customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객2", true)); + customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객3", false)); List customers = customerJDBCRepository.findAllBlackCustomer(); assertThat(customers.isEmpty()).isFalse(); assertThat(customers.stream().filter(customer -> !customer.isBlack()).toList()).isEmpty(); } + @Test + @DisplayName("🆗 고객 정보를 저장할 수 있다.") + void save() { + customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객4")); + } + @Configuration @ComponentScan( - basePackages = {"com.programmers.vouchermanagement.customer.repository"} + basePackages = {"com.programmers.vouchermanagement"} ) static class Config { @Bean From beb5a35d22a37e38053596987ef89f2161f29c5d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 19:42:48 +0900 Subject: [PATCH 162/383] refactor: remove useless methods, fields --- .../consoleapp/runner/ConsoleAppRunner.java | 3 +- .../controller/CustomerController.java | 7 ++--- .../customer/domain/Customer.java | 18 +++++------ .../repository/CustomerFileRepository.java | 1 - .../repository/CustomerJDBCRepository.java | 9 ------ .../customer/service/CustomerService.java | 1 - .../vouchermanagement/util/DomainMapper.java | 13 ++------ .../voucher/domain/Voucher.java | 24 +-------------- .../voucher/dto/VoucherResponse.java | 2 +- .../repository/VoucherFileRepository.java | 14 ++++----- .../repository/VoucherInMemoryRepository.java | 6 ++-- .../VoucherInMemoryRepositoryTest.java | 12 ++++---- .../repository/VoucherJDBCRepositoryTest.java | 29 +++++++++--------- .../repository/WalletJDBCRepositoryTest.java | 30 +++++++++---------- 14 files changed, 63 insertions(+), 106 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java index 356a8dd074..9f9cb5a221 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java @@ -1,11 +1,10 @@ package com.programmers.vouchermanagement.consoleapp.runner; +import com.programmers.vouchermanagement.consoleapp.menu.MenuHandler; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; -import com.programmers.vouchermanagement.consoleapp.menu.MenuHandler; - @Component public class ConsoleAppRunner implements ApplicationRunner { private final MenuHandler menuHandler; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 559566723a..adb8282945 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -1,11 +1,10 @@ package com.programmers.vouchermanagement.customer.controller; -import java.util.List; - -import org.springframework.stereotype.Controller; - import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.service.CustomerService; +import org.springframework.stereotype.Controller; + +import java.util.List; @Controller public class CustomerController { diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 58e3b6cb51..3f84af229a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -3,26 +3,26 @@ import java.util.UUID; public class Customer { - private final UUID customerId; + private final UUID id; private final String name; - private final boolean isBlack; + private final boolean black; - public Customer(UUID customerId, String name) { - this(customerId, name, false); + public Customer(UUID id, String name) { + this(id, name, false); } - public Customer(UUID customerId, String name, boolean isBlack) { - this.customerId = customerId; + public Customer(UUID id, String name, boolean black) { + this.id = id; this.name = name; - this.isBlack = isBlack; + this.black = black; } public UUID getCustomerId() { - return customerId; + return id; } public boolean isBlack() { - return isBlack; + return black; } public String getName() { diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 7bf8518c28..3064524276 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -19,7 +19,6 @@ public class CustomerFileRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerFileRepository.class); private static final String COMMA_SEPARATOR = ", "; private static final String IO_EXCEPTION_LOG_MESSAGE = "Error raised while reading blacklist"; - private final String filePath; private final Map customers; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 2350aec21b..a43a9ada7a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -8,9 +8,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; -import java.nio.ByteBuffer; import java.util.List; -import java.util.UUID; @Repository @Primary @@ -18,7 +16,6 @@ public class CustomerJDBCRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerJDBCRepository.class); private static final String FIND_ALL_BLACK_CUSTOMER_QUERY = "SELECT * FROM test.customers WHERE black = TRUE"; private static final String INSERT_QUERY = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; - private final NamedParameterJdbcTemplate jdbcTemplate; private final DomainMapper domainMapper; @@ -27,12 +24,6 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMap this.domainMapper = domainMapper; } - static UUID toUUID(byte[] bytes) { - var byteBuffer = ByteBuffer.wrap(bytes); - return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); - } - - @Override public List findAllBlackCustomer() { return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER_QUERY, domainMapper.customerRowMapper); diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 4c2aa2c70c..48576eefda 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -9,7 +9,6 @@ @Service public class CustomerService { - private static final String NO_BLACKLIST = "no blacklist"; private final CustomerRepository customerRepository; public CustomerService(CustomerRepository customerRepository) { diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index 49da228648..baa4288937 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -14,11 +14,6 @@ @Component public class DomainMapper { - public final RowMapper ownershipRowMapper = (resultSet, i) -> { - UUID voucherId = toUUID(resultSet.getBytes("voucher_id")); - UUID customerId = toUUID(resultSet.getBytes("customer_id")); - return new Ownership(voucherId, customerId); - }; public final RowMapper voucherRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes("id")); long discountValue = resultSet.getLong("discount_value"); @@ -33,8 +28,6 @@ public class DomainMapper { return new Customer(id, name, isBlack); }; - public final RowMapper uuidRowMapper = (resultSet, i) -> - toUUID(resultSet.getBytes("id")); private static UUID toUUID(byte[] bytes) { var byteBuffer = ByteBuffer.wrap(bytes); @@ -64,9 +57,9 @@ public Map uuidToParamMap(UUID id) { public Map voucherToParamMap(Voucher voucher) { Map paramMap = new HashMap<>(); - paramMap.put("id", voucher.getVoucherId().toString().getBytes()); - paramMap.put("type", voucher.getVoucherType().name()); - paramMap.put("discountValue", voucher.getDiscountValue()); + paramMap.put("id", voucher.voucherId().toString().getBytes()); + paramMap.put("type", voucher.voucherType().name()); + paramMap.put("discountValue", voucher.discountValue()); return paramMap; } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index ca78825049..bc7adfcaee 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -1,28 +1,6 @@ package com.programmers.vouchermanagement.voucher.domain; -import java.math.BigDecimal; import java.util.UUID; -public class Voucher { - private final UUID voucherId; - private final long discountValue; - private final VoucherType voucherType; - - public Voucher(UUID voucherId, long discountValue, VoucherType voucherType) { - this.voucherId = voucherId; - this.voucherType = voucherType; - this.discountValue = discountValue; - } - - public UUID getVoucherId() { - return voucherId; - } - - public long getDiscountValue() { - return discountValue; - } - - public VoucherType getVoucherType() { - return voucherType; - } +public record Voucher(UUID voucherId, long discountValue, VoucherType voucherType) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java index f9077fcd52..7bdcbd2b66 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -17,7 +17,7 @@ private VoucherResponse(UUID voucherId, long discountValue, VoucherType voucherT } public static VoucherResponse from(Voucher voucher) { - return new VoucherResponse(voucher.getVoucherId(), voucher.getDiscountValue(), voucher.getVoucherType()); + return new VoucherResponse(voucher.voucherId(), voucher.discountValue(), voucher.voucherType()); } public UUID getVoucherId() { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index a2f41c121b..f777fa833b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -42,7 +42,7 @@ public VoucherFileRepository(AppProperties appProperties) { @Override public void save(Voucher voucher) { - vouchers.put(voucher.getVoucherId(), voucher); + vouchers.put(voucher.voucherId(), voucher); saveFile(); } @@ -71,8 +71,8 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - Optional.ofNullable(vouchers.get(voucher.getVoucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); - vouchers.put(voucher.getVoucherId(), voucher); + Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); + vouchers.put(voucher.voucherId(), voucher); saveFile(); } @@ -90,7 +90,7 @@ private void loadFile() { private void loadVouchers(Map[] voucherObjects) { Arrays.stream(voucherObjects).forEach(voucherObject -> { Voucher voucher = objectToVoucher(voucherObject); - vouchers.put(voucher.getVoucherId(), voucher); + vouchers.put(voucher.voucherId(), voucher); }); } @@ -125,9 +125,9 @@ public void saveFile() { private HashMap voucherToObject(Voucher voucher) { HashMap voucherObject = new HashMap<>(); - voucherObject.put(VOUCHER_ID_KEY, voucher.getVoucherId().toString()); - voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); - voucherObject.put(VOUCHER_TYPE_KEY, voucher.getVoucherType().name()); + voucherObject.put(VOUCHER_ID_KEY, voucher.voucherId().toString()); + voucherObject.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); + voucherObject.put(VOUCHER_TYPE_KEY, voucher.voucherType().name()); return voucherObject; } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index e447d73f9c..d06a28cd78 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -17,7 +17,7 @@ public VoucherInMemoryRepository() { @Override public void save(Voucher voucher) { - vouchers.put(voucher.getVoucherId(), voucher); + vouchers.put(voucher.voucherId(), voucher); } @Override @@ -43,7 +43,7 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - Optional.ofNullable(vouchers.get(voucher.getVoucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); - vouchers.put(voucher.getVoucherId(), voucher); + Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); + vouchers.put(voucher.voucherId(), voucher); } } diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java index fc937c8880..a29f5341b2 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java @@ -22,9 +22,9 @@ void deleteVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherInMemoryRepository.save(voucher); - voucherInMemoryRepository.delete(voucher.getVoucherId()); + voucherInMemoryRepository.delete(voucher.voucherId()); - assertThat(voucherInMemoryRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); + assertThat(voucherInMemoryRepository.findById(voucher.voucherId()).isEmpty()).isTrue(); } @Test @@ -43,12 +43,12 @@ void updateVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherInMemoryRepository.save(voucher); - Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), 100, VoucherType.PERCENT); + Voucher updatedVoucher = new Voucher(voucher.voucherId(), 100, VoucherType.PERCENT); voucherInMemoryRepository.update(updatedVoucher); - Optional retrievedVoucher = voucherInMemoryRepository.findById(voucher.getVoucherId()); + Optional retrievedVoucher = voucherInMemoryRepository.findById(voucher.voucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); - assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(updatedVoucher.getVoucherType()); + assertThat(retrievedVoucher.get().discountValue()).isEqualTo(updatedVoucher.discountValue()); + assertThat(retrievedVoucher.get().voucherType()).isEqualTo(updatedVoucher.voucherType()); } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index 8d36354088..d934411de4 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -2,7 +2,6 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -37,10 +36,10 @@ void saveFixedAmountVoucher() { Voucher newVoucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); voucherJDBCRepository.save(newVoucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.getVoucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.voucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.get().voucherId()).isEqualTo(newVoucher.voucherId()); } @Test @@ -49,10 +48,10 @@ void savePercentVoucher() { Voucher newVoucher = new Voucher(UUID.randomUUID(), 50, VoucherType.PERCENT); voucherJDBCRepository.save(newVoucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.getVoucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.voucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(newVoucher.getVoucherId()); + assertThat(retrievedVoucher.get().voucherId()).isEqualTo(newVoucher.voucherId()); } @Test @@ -72,12 +71,12 @@ void findVoucherById() { Voucher voucher = new Voucher(UUID.randomUUID(), 1234, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getVoucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); assertThat(retrievedVoucher.isPresent()).isTrue(); - assertThat(retrievedVoucher.get().getVoucherId()).isEqualTo(voucher.getVoucherId()); - assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(voucher.getDiscountValue()); - assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(voucher.getVoucherType()); + assertThat(retrievedVoucher.get().voucherId()).isEqualTo(voucher.voucherId()); + assertThat(retrievedVoucher.get().discountValue()).isEqualTo(voucher.discountValue()); + assertThat(retrievedVoucher.get().voucherType()).isEqualTo(voucher.voucherType()); } @Test @@ -94,9 +93,9 @@ void deleteVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - voucherJDBCRepository.delete(voucher.getVoucherId()); + voucherJDBCRepository.delete(voucher.voucherId()); - assertThat(voucherJDBCRepository.findById(voucher.getVoucherId()).isEmpty()).isTrue(); + assertThat(voucherJDBCRepository.findById(voucher.voucherId()).isEmpty()).isTrue(); } @Test @@ -111,13 +110,13 @@ void updateVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - Voucher updatedVoucher = new Voucher(voucher.getVoucherId(), 100, VoucherType.PERCENT); + Voucher updatedVoucher = new Voucher(voucher.voucherId(), 100, VoucherType.PERCENT); voucherJDBCRepository.update(updatedVoucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getVoucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); - assertThat(retrievedVoucher.get().getVoucherType()).isEqualTo(updatedVoucher.getVoucherType()); + assertThat(retrievedVoucher.get().discountValue()).isEqualTo(updatedVoucher.discountValue()); + assertThat(retrievedVoucher.get().voucherType()).isEqualTo(updatedVoucher.voucherType()); } @Test diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index 6a0af2c6db..d3f778a51b 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -58,7 +58,7 @@ void save() { Customer customer = new Customer(UUID.randomUUID(), "바우처 주인"); customerJDBCRepository.save(customer); - Ownership newOwnership = new Ownership(voucher.getVoucherId(), customer.getCustomerId()); + Ownership newOwnership = new Ownership(voucher.voucherId(), customer.getCustomerId()); walletJDBCRepository.save(newOwnership); } @@ -70,12 +70,12 @@ void saveAllocatedVoucher() { Customer customer = new Customer(UUID.randomUUID(), "바우처를 가진 고객"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); + walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); Customer customer2 = new Customer(UUID.randomUUID(), "바우처를 가지지 못하는 고객"); customerJDBCRepository.save(customer2); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer2.getCustomerId()))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer2.getCustomerId()))); } @Test @@ -84,7 +84,7 @@ void saveNonExistentCustomer() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), NON_EXISTENT_CUSTOMER_ID))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.voucherId(), NON_EXISTENT_CUSTOMER_ID))); } @Test @@ -111,7 +111,7 @@ void findAllVoucherByCustomerId() { for (int i = 1; i < 6; i++) { Voucher voucher = new Voucher(UUID.randomUUID(), i, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); + walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); } // If the customer don't have any voucher, then return empty list. @@ -132,12 +132,12 @@ void delete() { Customer customer = new Customer(UUID.randomUUID(), "1개의 삭제될 바우처를 가진 주인"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); + walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); - walletJDBCRepository.delete(voucher.getVoucherId()); + walletJDBCRepository.delete(voucher.voucherId()); - assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()).isEmpty()).isTrue(); - assertThat(voucherJDBCRepository.findById(voucher.getVoucherId()).isPresent()).isTrue(); + assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()).isEmpty()).isTrue(); + assertThat(voucherJDBCRepository.findById(voucher.voucherId()).isPresent()).isTrue(); } @Test @@ -146,7 +146,7 @@ void deleteNonAllocatedVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); voucherJDBCRepository.save(voucher); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.delete(voucher.getVoucherId())); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.delete(voucher.voucherId())); } @Test @@ -157,9 +157,9 @@ void findCustomerByVoucherId() { Customer customer = new Customer(UUID.randomUUID(), "조회될 고객"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); + walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); - Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()); + Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()); assertThat(retrievedCustomer.isPresent()).isTrue(); assertThat(retrievedCustomer.get().getCustomerId()).isEqualTo(customer.getCustomerId()); @@ -179,11 +179,11 @@ void autoDeleteAfterVoucherDelete() { Customer customer = new Customer(UUID.randomUUID(), "삭제될 바우처를 가진 고객"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.getVoucherId(), customer.getCustomerId())); + walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); - voucherJDBCRepository.delete(voucher.getVoucherId()); + voucherJDBCRepository.delete(voucher.voucherId()); - assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getVoucherId()).isEmpty()).isTrue(); + assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()).isEmpty()).isTrue(); } @Configuration From 25c78ec32c205629112e740a14c5c4dccec77b69 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 20:41:58 +0900 Subject: [PATCH 163/383] refactor: split messages, queries from WalletJDBCRepository --- .../wallet/WalletMessage.java | 9 +++++ .../repository/WalletJDBCRepository.java | 34 +++++++++++-------- .../wallet/repository/WalletQuery.java | 9 +++++ 3 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java b/src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java new file mode 100644 index 0000000000..7010cab79e --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java @@ -0,0 +1,9 @@ +package com.programmers.vouchermanagement.wallet; + +public class WalletMessage { + public static final String NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION = "There is no voucher allocation information."; + public static final String NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION = "There is no customer allocation information."; + public static final String CAN_NOT_INSERT_OWNERSHIP = "There is no customer allocation information."; + public static final String ALREADY_EMPTY_TABLE = "The table is already empty."; + +} diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 2d0adf85d9..91a3be4571 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -3,6 +3,7 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.wallet.WalletMessage; import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,11 +19,6 @@ @Repository public class WalletJDBCRepository implements WalletRepository { private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepository.class); - private static final String INSERT_QUERY = "INSERT INTO test.ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucherId), UUID_TO_BIN(:customerId))"; - private static final String DELETE_OWNERSHIP_QUERY = "DELETE FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; - private static final String DELETE_ALL_QUERY = "TRUNCATE TABLE test.ownership"; - private static final String FIND_CUSTOMER_BY_VOUCHER_ID_QUERY = "SELECT c.* FROM test.ownership as o JOIN test.customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)"; - private static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY = "SELECT v.* FROM test.ownership as o JOIN test.vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)"; private final NamedParameterJdbcTemplate jdbcTemplate; private final DomainMapper domainMapper; @@ -33,41 +29,49 @@ public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMappe @Override public void save(Ownership ownership) { - int update = jdbcTemplate.update(INSERT_QUERY, domainMapper.ownershipToParamMap(ownership)); + int update = jdbcTemplate.update(WalletQuery.INSERT, domainMapper.ownershipToParamMap(ownership)); if (update != 1) { - throw new RuntimeException("Noting was inserted"); + logger.error(WalletMessage.CAN_NOT_INSERT_OWNERSHIP); + throw new RuntimeException(WalletMessage.CAN_NOT_INSERT_OWNERSHIP); } } @Override public Optional findCustomerByVoucherId(UUID voucherId) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID_QUERY, - Collections.singletonMap("id", voucherId.toString().getBytes()), + return Optional.ofNullable(jdbcTemplate.queryForObject(WalletQuery.FIND_CUSTOMER_BY_VOUCHER_ID, + Collections.singletonMap(DomainMapper.ID_KEY, voucherId.toString().getBytes()), domainMapper.customerRowMapper)); } catch (EmptyResultDataAccessException e) { - logger.error("Got empty result", e); + logger.error(WalletMessage.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION, e); return Optional.empty(); } } @Override public List findAllVoucherByCustomerId(UUID customerId) { - return jdbcTemplate.query(FIND_ALL_VOUCHER_BY_CUSTOMER_ID_QUERY, - Collections.singletonMap("id", customerId.toString().getBytes()), + List vouchers = jdbcTemplate.query(WalletQuery.FIND_ALL_VOUCHER_BY_CUSTOMER_ID, + Collections.singletonMap(DomainMapper.ID_KEY, customerId.toString().getBytes()), domainMapper.voucherRowMapper); + if (vouchers.isEmpty()) + logger.warn(WalletMessage.NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION); + return vouchers; } @Override public void delete(UUID voucherId) { - int update = jdbcTemplate.update(DELETE_OWNERSHIP_QUERY, domainMapper.uuidToParamMap(voucherId)); + int update = jdbcTemplate.update(WalletQuery.DELETE_OWNERSHIP, domainMapper.uuidToParamMap(voucherId)); if (update != 1) { - throw new RuntimeException("Noting was deleted"); + logger.error(WalletMessage.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); + throw new RuntimeException(WalletMessage.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); } } @Override public void deleteAll() { - jdbcTemplate.update(DELETE_ALL_QUERY, Collections.emptyMap()); + int update = jdbcTemplate.update(WalletQuery.DELETE_ALL, Collections.emptyMap()); + if (update == 0) { + logger.warn(WalletMessage.ALREADY_EMPTY_TABLE); + } } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java new file mode 100644 index 0000000000..d04977800a --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java @@ -0,0 +1,9 @@ +package com.programmers.vouchermanagement.wallet.repository; + +public class WalletQuery { + public static final String INSERT = "INSERT INTO test.ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucher_id), UUID_TO_BIN(:customer_id))"; + public static final String DELETE_OWNERSHIP = "DELETE FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; + public static final String DELETE_ALL = "TRUNCATE TABLE test.ownership"; + public static final String FIND_CUSTOMER_BY_VOUCHER_ID = "SELECT c.* FROM test.ownership as o JOIN test.customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)"; + public static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID = "SELECT v.* FROM test.ownership as o JOIN test.vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)"; +} From 650dfd6ca5771802016a45700ede185c5a016dbe Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 20:42:18 +0900 Subject: [PATCH 164/383] refactor: split queries from VoucherJDBCRepository --- .../repository/VoucherJDBCRepository.java | 21 +++++++------------ .../voucher/repository/VoucherQuery.java | 10 +++++++++ 2 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 5d0c205b6e..2a73225d38 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -18,12 +18,6 @@ @Primary public class VoucherJDBCRepository implements VoucherRepository { private static final Logger logger = LoggerFactory.getLogger(VoucherJDBCRepository.class); - private static final String INSERT_QUERY = "INSERT INTO test.vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discountValue)"; - private static final String FIND_BY_ID_QUERY = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; - private static final String FIND_ALL_QUERY = "SELECT * FROM test.vouchers"; - private static final String DELETE_VOUCHER_QUERY = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; - private static final String DELETE_ALL_QUERY = "TRUNCATE TABLE test.vouchers"; - private static final String UPDATE_VOUCHER_QUERY = "UPDATE test.vouchers SET type = :type, discount_value = :discountValue WHERE id = UUID_TO_BIN(:id)"; private final NamedParameterJdbcTemplate jdbcTemplate; private final DomainMapper domainMapper; @@ -32,10 +26,9 @@ public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapp this.domainMapper = domainMapper; } - @Override public void save(Voucher voucher) { - int update = jdbcTemplate.update(INSERT_QUERY, domainMapper.voucherToParamMap(voucher)); + int update = jdbcTemplate.update(VoucherQuery.INSERT, domainMapper.voucherToParamMap(voucher)); if (update != 1) { throw new RuntimeException("Noting was inserted"); } @@ -43,14 +36,14 @@ public void save(Voucher voucher) { @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL_QUERY, domainMapper.voucherRowMapper); + return jdbcTemplate.query(VoucherQuery.FIND_ALL, domainMapper.voucherRowMapper); } @Override public Optional findById(UUID id) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID_QUERY, - Collections.singletonMap("id", id.toString().getBytes()), + return Optional.ofNullable(jdbcTemplate.queryForObject(VoucherQuery.FIND_BY_ID, + Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes()), domainMapper.voucherRowMapper)); } catch (EmptyResultDataAccessException e) { logger.error("Got empty result", e); @@ -60,7 +53,7 @@ public Optional findById(UUID id) { @Override public void delete(UUID id) { - int update = jdbcTemplate.update(DELETE_VOUCHER_QUERY, Collections.singletonMap("id", id.toString().getBytes())); + int update = jdbcTemplate.update(VoucherQuery.DELETE_VOUCHER, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes())); if (update != 1) { throw new RuntimeException("Noting was deleted"); } @@ -68,12 +61,12 @@ public void delete(UUID id) { @Override public void deleteAll() { - jdbcTemplate.update(DELETE_ALL_QUERY, Collections.emptyMap()); + jdbcTemplate.update(VoucherQuery.DELETE_ALL, Collections.emptyMap()); } @Override public void update(Voucher voucher) { - int update = jdbcTemplate.update(UPDATE_VOUCHER_QUERY, domainMapper.voucherToParamMap(voucher)); + int update = jdbcTemplate.update(VoucherQuery.UPDATE_VOUCHER, domainMapper.voucherToParamMap(voucher)); if (update != 1) { throw new RuntimeException("Noting was updated"); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java new file mode 100644 index 0000000000..584315a641 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java @@ -0,0 +1,10 @@ +package com.programmers.vouchermanagement.voucher.repository; + +public class VoucherQuery { + public static final String INSERT = "INSERT INTO test.vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discount_value)"; + public static final String FIND_BY_ID = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; + public static final String FIND_ALL = "SELECT * FROM test.vouchers"; + public static final String DELETE_VOUCHER = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; + public static final String DELETE_ALL = "TRUNCATE TABLE test.vouchers"; + public static final String UPDATE_VOUCHER = "UPDATE test.vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; +} From cf85604af80046a7e1f4d7ac15faf58f3631aa44 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 20:42:28 +0900 Subject: [PATCH 165/383] refactor: split queries from CustomerJDBCRepository --- .../customer/repository/CustomerJDBCRepository.java | 6 ++---- .../customer/repository/CustomerQuery.java | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index a43a9ada7a..44e680d1d1 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -14,8 +14,6 @@ @Primary public class CustomerJDBCRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerJDBCRepository.class); - private static final String FIND_ALL_BLACK_CUSTOMER_QUERY = "SELECT * FROM test.customers WHERE black = TRUE"; - private static final String INSERT_QUERY = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; private final NamedParameterJdbcTemplate jdbcTemplate; private final DomainMapper domainMapper; @@ -26,11 +24,11 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMap @Override public List findAllBlackCustomer() { - return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER_QUERY, domainMapper.customerRowMapper); + return jdbcTemplate.query(CustomerQuery.FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); } public void save(Customer customer) { - int update = jdbcTemplate.update(INSERT_QUERY, domainMapper.customerToParamMap(customer)); + int update = jdbcTemplate.update(CustomerQuery.INSERT, domainMapper.customerToParamMap(customer)); if (update != 1) { throw new RuntimeException("Noting was inserted"); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java new file mode 100644 index 0000000000..af0ad1b86c --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java @@ -0,0 +1,7 @@ +package com.programmers.vouchermanagement.customer.repository; + +public class CustomerQuery { + public static final String FIND_ALL_BLACK_CUSTOMER = "SELECT * FROM test.customers WHERE black = TRUE"; + public static final String INSERT = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; + +} From b33205f068b85b87a40909a0505823ff4681cc14 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 20:42:53 +0900 Subject: [PATCH 166/383] refactor: set Key constant at DomainMapper --- .../vouchermanagement/util/DomainMapper.java | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index baa4288937..658c867ce3 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -14,17 +14,25 @@ @Component public class DomainMapper { + public static final String ID_KEY = "id"; + public static final String VOUCHER_ID_KEY = "voucher_id"; + public static final String CUSTOMER_ID_KEY = "customer_id"; + public static final String BLACK_KEY = "black"; + public static final String NAME_KEY = "name"; + public static final String DISCOUNT_VALUE_KEY = "discount_value"; + public static final String TYPE_KEY = "type"; + public final RowMapper voucherRowMapper = (resultSet, i) -> { - UUID id = toUUID(resultSet.getBytes("id")); - long discountValue = resultSet.getLong("discount_value"); - String voucherTypeStr = resultSet.getString("type"); + UUID id = toUUID(resultSet.getBytes(ID_KEY)); + long discountValue = resultSet.getLong(DISCOUNT_VALUE_KEY); + String voucherTypeStr = resultSet.getString(TYPE_KEY); return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); }; public final RowMapper customerRowMapper = (resultSet, i) -> { - UUID id = toUUID(resultSet.getBytes("id")); - String name = resultSet.getString("name"); - boolean isBlack = resultSet.getBoolean("black"); + UUID id = toUUID(resultSet.getBytes(ID_KEY)); + String name = resultSet.getString(NAME_KEY); + boolean isBlack = resultSet.getBoolean(BLACK_KEY); return new Customer(id, name, isBlack); }; @@ -36,30 +44,30 @@ private static UUID toUUID(byte[] bytes) { public Map customerToParamMap(Customer customer) { Map paramMap = new HashMap<>(); - paramMap.put("id", customer.getCustomerId().toString().getBytes()); - paramMap.put("name", customer.getName()); - paramMap.put("black", customer.isBlack()); + paramMap.put(ID_KEY, customer.getCustomerId().toString().getBytes()); + paramMap.put(NAME_KEY, customer.getName()); + paramMap.put(BLACK_KEY, customer.isBlack()); return paramMap; } public Map ownershipToParamMap(Ownership ownership) { Map paramMap = new HashMap<>(); - paramMap.put("voucherId", ownership.voucherId().toString().getBytes()); - paramMap.put("customerId", ownership.customerId().toString().getBytes()); + paramMap.put(VOUCHER_ID_KEY, ownership.voucherId().toString().getBytes()); + paramMap.put(CUSTOMER_ID_KEY, ownership.customerId().toString().getBytes()); return paramMap; } public Map uuidToParamMap(UUID id) { Map paramMap = new HashMap<>(); - paramMap.put("id", id.toString().getBytes()); + paramMap.put(ID_KEY, id.toString().getBytes()); return paramMap; } public Map voucherToParamMap(Voucher voucher) { Map paramMap = new HashMap<>(); - paramMap.put("id", voucher.voucherId().toString().getBytes()); - paramMap.put("type", voucher.voucherType().name()); - paramMap.put("discountValue", voucher.discountValue()); + paramMap.put(ID_KEY, voucher.voucherId().toString().getBytes()); + paramMap.put(TYPE_KEY, voucher.voucherType().name()); + paramMap.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); return paramMap; } } From 194925ced6c47ca260a568aa333f36836c0cab10 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 21:23:58 +0900 Subject: [PATCH 167/383] refactor: move constants to Constant and apply where they used --- .../vouchermanagement/constant/Constant.java | 3 ++ .../vouchermanagement/constant/Message.java | 15 ++++++++ .../repository/CustomerFileRepository.java | 7 ++-- .../repository/CustomerJDBCRepository.java | 14 +++++-- .../repository/VoucherFileRepository.java | 18 ++++----- .../repository/VoucherInMemoryRepository.java | 7 +++- .../repository/VoucherJDBCRepository.java | 30 ++++++++------- .../wallet/WalletMessage.java | 9 ----- .../repository/WalletJDBCRepository.java | 37 ++++++++++--------- 9 files changed, 80 insertions(+), 60 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/constant/Message.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java diff --git a/src/main/java/com/programmers/vouchermanagement/constant/Constant.java b/src/main/java/com/programmers/vouchermanagement/constant/Constant.java index 2ffa5f8c04..a42a70c56a 100644 --- a/src/main/java/com/programmers/vouchermanagement/constant/Constant.java +++ b/src/main/java/com/programmers/vouchermanagement/constant/Constant.java @@ -2,4 +2,7 @@ public class Constant { public static final String LINE_SEPARATOR = System.lineSeparator(); + public static final String COMMA_SEPARATOR = ", "; + public static final int UPDATE_ONE_FLAG = 1; + public static final int UPDATE_ZERO_FLAG = 0; } diff --git a/src/main/java/com/programmers/vouchermanagement/constant/Message.java b/src/main/java/com/programmers/vouchermanagement/constant/Message.java new file mode 100644 index 0000000000..8e246526fe --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/constant/Message.java @@ -0,0 +1,15 @@ +package com.programmers.vouchermanagement.constant; + +public class Message { + public final static String NOT_INSERTED = "Noting was inserted!"; + public final static String NOT_UPDATED = "Noting was updated!"; + public final static String NOT_DELETED = "Noting was deleted!"; + public final static String EMPTY_RESULT = "Got empty result!"; + public static final String IO_EXCEPTION = "Error raised while reading file!"; + public static final String NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION = "There is no voucher allocation information."; + public static final String NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION = "There is no customer allocation information."; + public static final String CAN_NOT_INSERT_OWNERSHIP = "There is no customer allocation information."; + public static final String ALREADY_EMPTY_TABLE = "The table is already empty."; + public static final String FILE_EXCEPTION = "Error raised while opening the file."; + public static final String INVALID_VOUCHER_TYPE = "Voucher type should be either fixed amount or percent discount voucher."; +} diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 3064524276..64363ec630 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -13,12 +13,13 @@ import java.io.UncheckedIOException; import java.util.*; +import static com.programmers.vouchermanagement.constant.Constant.COMMA_SEPARATOR; +import static com.programmers.vouchermanagement.constant.Message.IO_EXCEPTION; + @Repository @Profile({"dev", "prod"}) public class CustomerFileRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerFileRepository.class); - private static final String COMMA_SEPARATOR = ", "; - private static final String IO_EXCEPTION_LOG_MESSAGE = "Error raised while reading blacklist"; private final String filePath; private final Map customers; @@ -53,7 +54,7 @@ private void loadBlacklist() { blacklist.add(blackCustomer); } } catch (IOException e) { - logger.error(IO_EXCEPTION_LOG_MESSAGE); + logger.error(IO_EXCEPTION); throw new UncheckedIOException(e); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 44e680d1d1..85363f736e 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -10,6 +10,11 @@ import java.util.List; +import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; +import static com.programmers.vouchermanagement.constant.Message.NOT_INSERTED; +import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.FIND_ALL_BLACK_CUSTOMER; +import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.INSERT; + @Repository @Primary public class CustomerJDBCRepository implements CustomerRepository { @@ -24,13 +29,14 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMap @Override public List findAllBlackCustomer() { - return jdbcTemplate.query(CustomerQuery.FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); + return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); } public void save(Customer customer) { - int update = jdbcTemplate.update(CustomerQuery.INSERT, domainMapper.customerToParamMap(customer)); - if (update != 1) { - throw new RuntimeException("Noting was inserted"); + int update = jdbcTemplate.update(INSERT, domainMapper.customerToParamMap(customer)); + if (update != UPDATE_ONE_FLAG) { + logger.error(NOT_INSERTED); + throw new RuntimeException(NOT_INSERTED); } } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index f777fa833b..c4f5e5357c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -15,6 +15,8 @@ import java.io.UncheckedIOException; import java.util.*; +import static com.programmers.vouchermanagement.constant.Message.*; + @Repository @Profile("prod") public class VoucherFileRepository implements VoucherRepository { @@ -24,12 +26,6 @@ public class VoucherFileRepository implements VoucherRepository { private static final String VOUCHER_ID_KEY = "voucher_id"; private static final String DISCOUNT_VALUE_KEY = "discount_value"; private static final String VOUCHER_TYPE_KEY = "voucher_type"; - private static final String FILE_EXCEPTION = "Error raised while opening the file."; - - //messages - private static final String IO_EXCEPTION_LOG_MESSAGE = "Error raised while reading vouchers"; - private static final String INVALID_VOUCHER_TYPE_MESSAGE = "Voucher type should be either fixed amount or percent discount voucher."; - private final ObjectMapper objectMapper = new ObjectMapper(); private final String filePath; private final Map vouchers; @@ -58,7 +54,7 @@ public Optional findById(UUID id) { @Override public void delete(UUID id) { - Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException("Noting was deleted")); + Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); saveFile(); } @@ -71,7 +67,7 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); + Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); vouchers.put(voucher.voucherId(), voucher); saveFile(); } @@ -82,7 +78,7 @@ private void loadFile() { Map[] voucherObjects = objectMapper.readValue(file, Map[].class); loadVouchers(voucherObjects); } catch (IOException e) { - logger.error(IO_EXCEPTION_LOG_MESSAGE); + logger.error(IO_EXCEPTION); throw new UncheckedIOException(e); } } @@ -100,8 +96,8 @@ private Voucher objectToVoucher(Map voucherObject) { String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) .orElseThrow(() -> { - logger.error(INVALID_VOUCHER_TYPE_MESSAGE); - return new NoSuchElementException(INVALID_VOUCHER_TYPE_MESSAGE); + logger.error(INVALID_VOUCHER_TYPE); + return new NoSuchElementException(INVALID_VOUCHER_TYPE); }); return new Voucher(voucherId, discountValue, voucherType); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index d06a28cd78..92ce1b6d07 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -6,6 +6,9 @@ import java.util.*; +import static com.programmers.vouchermanagement.constant.Message.NOT_DELETED; +import static com.programmers.vouchermanagement.constant.Message.NOT_UPDATED; + @Repository @Profile("dev") public class VoucherInMemoryRepository implements VoucherRepository { @@ -32,7 +35,7 @@ public Optional findById(UUID id) { @Override public void delete(UUID id) { - Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException("Noting was deleted")); + Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); } @Override @@ -43,7 +46,7 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException("Noting was updated")); + Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); vouchers.put(voucher.voucherId(), voucher); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 2a73225d38..e8ee644156 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -14,6 +14,10 @@ import java.util.Optional; import java.util.UUID; +import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; +import static com.programmers.vouchermanagement.constant.Message.*; +import static com.programmers.vouchermanagement.voucher.repository.VoucherQuery.*; + @Repository @Primary public class VoucherJDBCRepository implements VoucherRepository { @@ -28,47 +32,47 @@ public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapp @Override public void save(Voucher voucher) { - int update = jdbcTemplate.update(VoucherQuery.INSERT, domainMapper.voucherToParamMap(voucher)); - if (update != 1) { - throw new RuntimeException("Noting was inserted"); + int update = jdbcTemplate.update(INSERT, domainMapper.voucherToParamMap(voucher)); + if (update != UPDATE_ONE_FLAG) { + throw new RuntimeException(NOT_INSERTED); } } @Override public List findAll() { - return jdbcTemplate.query(VoucherQuery.FIND_ALL, domainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL, domainMapper.voucherRowMapper); } @Override public Optional findById(UUID id) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(VoucherQuery.FIND_BY_ID, + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes()), domainMapper.voucherRowMapper)); } catch (EmptyResultDataAccessException e) { - logger.error("Got empty result", e); + logger.error(EMPTY_RESULT, e); return Optional.empty(); } } @Override public void delete(UUID id) { - int update = jdbcTemplate.update(VoucherQuery.DELETE_VOUCHER, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes())); - if (update != 1) { - throw new RuntimeException("Noting was deleted"); + int update = jdbcTemplate.update(DELETE_VOUCHER, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes())); + if (update != UPDATE_ONE_FLAG) { + throw new RuntimeException(NOT_DELETED); } } @Override public void deleteAll() { - jdbcTemplate.update(VoucherQuery.DELETE_ALL, Collections.emptyMap()); + jdbcTemplate.update(DELETE_ALL, Collections.emptyMap()); } @Override public void update(Voucher voucher) { - int update = jdbcTemplate.update(VoucherQuery.UPDATE_VOUCHER, domainMapper.voucherToParamMap(voucher)); - if (update != 1) { - throw new RuntimeException("Noting was updated"); + int update = jdbcTemplate.update(UPDATE_VOUCHER, domainMapper.voucherToParamMap(voucher)); + if (update != UPDATE_ONE_FLAG) { + throw new RuntimeException(NOT_UPDATED); } } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java b/src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java deleted file mode 100644 index 7010cab79e..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/wallet/WalletMessage.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.programmers.vouchermanagement.wallet; - -public class WalletMessage { - public static final String NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION = "There is no voucher allocation information."; - public static final String NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION = "There is no customer allocation information."; - public static final String CAN_NOT_INSERT_OWNERSHIP = "There is no customer allocation information."; - public static final String ALREADY_EMPTY_TABLE = "The table is already empty."; - -} diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 91a3be4571..d0ed8b657b 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -3,7 +3,6 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.wallet.WalletMessage; import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,6 +15,11 @@ import java.util.Optional; import java.util.UUID; +import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; +import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ZERO_FLAG; +import static com.programmers.vouchermanagement.constant.Message.*; +import static com.programmers.vouchermanagement.wallet.repository.WalletQuery.*; + @Repository public class WalletJDBCRepository implements WalletRepository { private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepository.class); @@ -29,49 +33,46 @@ public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMappe @Override public void save(Ownership ownership) { - int update = jdbcTemplate.update(WalletQuery.INSERT, domainMapper.ownershipToParamMap(ownership)); - if (update != 1) { - logger.error(WalletMessage.CAN_NOT_INSERT_OWNERSHIP); - throw new RuntimeException(WalletMessage.CAN_NOT_INSERT_OWNERSHIP); + int update = jdbcTemplate.update(INSERT, domainMapper.ownershipToParamMap(ownership)); + if (update != UPDATE_ONE_FLAG) { + logger.error(CAN_NOT_INSERT_OWNERSHIP); + throw new RuntimeException(CAN_NOT_INSERT_OWNERSHIP); } } @Override public Optional findCustomerByVoucherId(UUID voucherId) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(WalletQuery.FIND_CUSTOMER_BY_VOUCHER_ID, + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID, Collections.singletonMap(DomainMapper.ID_KEY, voucherId.toString().getBytes()), domainMapper.customerRowMapper)); } catch (EmptyResultDataAccessException e) { - logger.error(WalletMessage.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION, e); + logger.error(NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION, e); return Optional.empty(); } } @Override public List findAllVoucherByCustomerId(UUID customerId) { - List vouchers = jdbcTemplate.query(WalletQuery.FIND_ALL_VOUCHER_BY_CUSTOMER_ID, + return jdbcTemplate.query(FIND_ALL_VOUCHER_BY_CUSTOMER_ID, Collections.singletonMap(DomainMapper.ID_KEY, customerId.toString().getBytes()), domainMapper.voucherRowMapper); - if (vouchers.isEmpty()) - logger.warn(WalletMessage.NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION); - return vouchers; } @Override public void delete(UUID voucherId) { - int update = jdbcTemplate.update(WalletQuery.DELETE_OWNERSHIP, domainMapper.uuidToParamMap(voucherId)); - if (update != 1) { - logger.error(WalletMessage.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); - throw new RuntimeException(WalletMessage.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); + int update = jdbcTemplate.update(DELETE_OWNERSHIP, domainMapper.uuidToParamMap(voucherId)); + if (update != UPDATE_ONE_FLAG) { + logger.error(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); + throw new RuntimeException(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); } } @Override public void deleteAll() { - int update = jdbcTemplate.update(WalletQuery.DELETE_ALL, Collections.emptyMap()); - if (update == 0) { - logger.warn(WalletMessage.ALREADY_EMPTY_TABLE); + int update = jdbcTemplate.update(DELETE_ALL, Collections.emptyMap()); + if (update == UPDATE_ZERO_FLAG) { + logger.warn(ALREADY_EMPTY_TABLE); } } } From 47a677e616e76dbfc856f3e073c1c67d425afd9f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 21:54:14 +0900 Subject: [PATCH 168/383] feat: implement WalletService --- .../wallet/service/WalletService.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java new file mode 100644 index 0000000000..1e2ec9c69a --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -0,0 +1,50 @@ +package com.programmers.vouchermanagement.wallet.service; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.wallet.domain.Ownership; +import com.programmers.vouchermanagement.wallet.repository.WalletRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + +import static com.programmers.vouchermanagement.constant.Message.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION; + +@Service +public class WalletService { + private static final Logger logger = LoggerFactory.getLogger(WalletService.class); + private final WalletRepository walletRepository; + + public WalletService(WalletRepository walletRepository) { + this.walletRepository = walletRepository; + } + + public void allocate(Ownership ownership) { + walletRepository.save(ownership); + } + + public Customer readCustomerByVoucherId(UUID voucherId) { + return walletRepository.findCustomerByVoucherId(voucherId).orElseThrow( + () -> { + logger.error(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); + return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); + } + ); + } + + public List readAllVoucherByCustomerId(UUID customerId) { + return walletRepository.findAllVoucherByCustomerId(customerId); + } + + public void deleteVoucherFromCustomer(UUID voucherId) { + walletRepository.delete(voucherId); + } + + public void deleteAllAllocation() { + walletRepository.deleteAll(); + } +} From 3da74ac28fc30d5f7f73e9669101c969442ba6b0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 21:54:21 +0900 Subject: [PATCH 169/383] test: test WalletService --- .../wallet/service/WalletServiceTest.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java new file mode 100644 index 0000000000..5378e42b5c --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java @@ -0,0 +1,90 @@ +package com.programmers.vouchermanagement.wallet.service; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.wallet.domain.Ownership; +import com.programmers.vouchermanagement.wallet.repository.WalletRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(SpringExtension.class) +class WalletServiceTest { + @InjectMocks + WalletService walletService; + @Mock + WalletRepository walletRepository; + @Mock + UUID mockUUID; + @Mock + Customer mockCustomer; + @Mock + Voucher mockVoucher; + @Mock + Ownership ownership; + + @Test + @DisplayName("🆗 단위 테스트를 위해 Service에 Mock 객체(Repository) 주입") + void initTest() { + assertThat(walletRepository).isNotNull(); + assertThat(walletService).isNotNull(); + } + + @Test + @DisplayName("🆗 바우처를 고객에게 할당할 수 있다.") + void allocate() { + walletService.allocate(ownership); + + verify(walletRepository, times(1)).save(ownership); + } + + @Test + @DisplayName("🆗 고객 id로 고객이 가진 바우처를 조회할 수 있다.") + void findAllVoucherByCustomerId() { + List mockVoucherList = mock(List.class); + when(walletRepository.findAllVoucherByCustomerId(mockUUID)).thenReturn(mockVoucherList); + + assertThat(walletService.readAllVoucherByCustomerId(mockUUID)).isEqualTo(mockVoucherList); + + verify(walletRepository, times(1)).findAllVoucherByCustomerId(mockUUID); + } + + @Test + @DisplayName("🆗 고객에게 할당한 바우처를 제거할 수 있다.") + void deleteVoucherFromCustomer() { + walletService.deleteVoucherFromCustomer(mockUUID); + + verify(walletRepository, times(1)).delete(mockUUID); + } + + @Test + @DisplayName("🆗 바우처 id로 바우처가 할당된 고객을 조회할 수 있다.") + void findCustomerByVoucherId() { + Optional customerOptional = Optional.of(mockCustomer); + when(walletRepository.findCustomerByVoucherId(mockUUID)).thenReturn(customerOptional); + + assertThat(walletService.readCustomerByVoucherId(mockUUID)).isEqualTo(customerOptional.get()); + verify(walletRepository, times(1)).findCustomerByVoucherId(mockUUID); + } + + @Test + @DisplayName("🚨 바우처가 없으면, 바우처가 할당된 고객을 조회할 수 없다.") + void findCustomerByNonExistVoucherId() { + when(walletRepository.findCustomerByVoucherId(mockUUID)).thenReturn(Optional.empty()); + + assertThrows(NoSuchElementException.class, () -> walletService.readCustomerByVoucherId(mockUUID)); + verify(walletRepository, times(1)).findCustomerByVoucherId(mockUUID); + } +} \ No newline at end of file From f7802f6fc2cee8bca3d105b7c6ad4e12cd3faba3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 21:55:12 +0900 Subject: [PATCH 170/383] refactor: remove logging NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION --- .../wallet/repository/WalletJDBCRepository.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index d0ed8b657b..df086b4d33 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -47,7 +47,6 @@ public Optional findCustomerByVoucherId(UUID voucherId) { Collections.singletonMap(DomainMapper.ID_KEY, voucherId.toString().getBytes()), domainMapper.customerRowMapper)); } catch (EmptyResultDataAccessException e) { - logger.error(NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION, e); return Optional.empty(); } } From 555719b4961b78263cc7d59cafe8f5a2f22f08bc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 21:55:54 +0900 Subject: [PATCH 171/383] enhance: add icon for readability --- .../repository/VoucherInMemoryRepositoryTest.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java index a29f5341b2..5d42525f73 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java @@ -17,7 +17,7 @@ class VoucherInMemoryRepositoryTest { VoucherInMemoryRepository voucherInMemoryRepository = new VoucherInMemoryRepository(); @Test - @DisplayName("바우처를 아이디로 삭제할 수 있다.") + @DisplayName("🆗 바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherInMemoryRepository.save(voucher); @@ -28,17 +28,15 @@ void deleteVoucherSucceed() { } @Test - @DisplayName("없는 바우처를 삭제하면 실패한다.") + @DisplayName("🚨 없는 바우처를 삭제하면 실패한다.") void deleteNonExistVoucherFail() { UUID NonExistVoucherId = UUID.randomUUID(); - assertThrows(RuntimeException.class, () -> { - voucherInMemoryRepository.delete(NonExistVoucherId); - }); + assertThrows(RuntimeException.class, () -> voucherInMemoryRepository.delete(NonExistVoucherId)); } @Test - @DisplayName("바우처를 업데이트 할 수 있다.") + @DisplayName("🆗 바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); voucherInMemoryRepository.save(voucher); From 64f26c571541c2dc818de416e9e5093fda1a6f13 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 21:58:49 +0900 Subject: [PATCH 172/383] enhance: add initialize database query --- src/main/resources/schema.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index b315654fb7..5b91f93027 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -20,4 +20,6 @@ CREATE TABLE ownership customer_id BINARY(16), FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE -); \ No newline at end of file +) +## for init database +SET FOREIGN_KEY_CHECKS = 0;TRUNCATE TABLE vouchers;TRUNCATE TABLE ownership;TRUNCATE TABLE customers;SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file From 934a69036919965d7e265c68198e21d507f9bfbd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 27 Oct 2023 22:10:09 +0900 Subject: [PATCH 173/383] refactor: implement TestConfig --- .../vouchermanagement/TestConfig.java | 40 +++++++++++++ .../CustomerJDBCRepositoryTest.java | 41 ++----------- .../repository/VoucherJDBCRepositoryTest.java | 57 ++++--------------- .../repository/WalletJDBCRepositoryTest.java | 41 ++----------- 4 files changed, 60 insertions(+), 119 deletions(-) create mode 100644 src/test/java/com/programmers/vouchermanagement/TestConfig.java diff --git a/src/test/java/com/programmers/vouchermanagement/TestConfig.java b/src/test/java/com/programmers/vouchermanagement/TestConfig.java new file mode 100644 index 0000000000..e40dc81eec --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/TestConfig.java @@ -0,0 +1,40 @@ +package com.programmers.vouchermanagement; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; + +import javax.sql.DataSource; + +@Configuration +@ComponentScan( + basePackages = {"com.programmers.vouchermanagement"} +) +public class TestConfig { + @Bean + public DataSource dataSource() { + var dataSource = DataSourceBuilder.create() + .url("jdbc:mysql://localhost:3306/test") + .username("root") + .password("980726") + .type(HikariDataSource.class) + .build(); + dataSource.setMaximumPoolSize(1000); + dataSource.setMinimumIdle(100); + return dataSource; + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + return new NamedParameterJdbcTemplate(jdbcTemplate); + } +} \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 324d1db945..479e7b5848 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -1,20 +1,15 @@ package com.programmers.vouchermanagement.customer.repository; +import com.programmers.vouchermanagement.TestConfig; import com.programmers.vouchermanagement.customer.domain.Customer; -import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.support.AnnotationConfigContextLoader; -import javax.sql.DataSource; import java.util.List; import java.util.UUID; @@ -22,6 +17,7 @@ @SpringJUnitConfig @TestInstance(TestInstance.Lifecycle.PER_CLASS) +@ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class) class CustomerJDBCRepositoryTest { @Autowired CustomerJDBCRepository customerJDBCRepository; @@ -42,33 +38,4 @@ void findAllBlackCustomerSucceed() { void save() { customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객4")); } - - @Configuration - @ComponentScan( - basePackages = {"com.programmers.vouchermanagement"} - ) - static class Config { - @Bean - public DataSource dataSource() { - var dataSource = DataSourceBuilder.create() - .url("jdbc:mysql://localhost:3306/test") - .username("root") - .password("980726") - .type(HikariDataSource.class) - .build(); - dataSource.setMaximumPoolSize(1000); - dataSource.setMinimumIdle(100); - return dataSource; - } - - @Bean - public JdbcTemplate jdbcTemplate(DataSource dataSource) { - return new JdbcTemplate(dataSource); - } - - @Bean - public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { - return new NamedParameterJdbcTemplate(jdbcTemplate); - } - } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index d934411de4..1eed4fa4c5 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -1,21 +1,16 @@ package com.programmers.vouchermanagement.voucher.repository; +import com.programmers.vouchermanagement.TestConfig; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.support.AnnotationConfigContextLoader; -import javax.sql.DataSource; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -25,6 +20,7 @@ @SpringJUnitConfig @TestInstance(TestInstance.Lifecycle.PER_CLASS) +@ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class) class VoucherJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); @Autowired @@ -33,25 +29,25 @@ class VoucherJDBCRepositoryTest { @Test @DisplayName("🆗 고정 금액 할인 바우처를 추가할 수 있다.") void saveFixedAmountVoucher() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); - voucherJDBCRepository.save(newVoucher); + Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); + voucherJDBCRepository.save(voucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.voucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().voucherId()).isEqualTo(newVoucher.voucherId()); + assertThat(retrievedVoucher.get().voucherId()).isEqualTo(voucher.voucherId()); } @Test @DisplayName("🆗 퍼센트 할인 바우처를 추가할 수 있다.") void savePercentVoucher() { - Voucher newVoucher = new Voucher(UUID.randomUUID(), 50, VoucherType.PERCENT); - voucherJDBCRepository.save(newVoucher); + Voucher voucher = new Voucher(UUID.randomUUID(), 50, VoucherType.PERCENT); + voucherJDBCRepository.save(voucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(newVoucher.voucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().voucherId()).isEqualTo(newVoucher.voucherId()); + assertThat(retrievedVoucher.get().voucherId()).isEqualTo(voucher.voucherId()); } @Test @@ -124,33 +120,4 @@ void updateVoucher() { void updateNonExistentVoucher() { assertThrows(RuntimeException.class, () -> voucherJDBCRepository.update(new Voucher(NON_EXISTENT_VOUCHER_ID, 100, VoucherType.PERCENT))); } - - @Configuration - @ComponentScan( - basePackages = {"com.programmers.vouchermanagement"} - ) - static class Config { - @Bean - public DataSource dataSource() { - var dataSource = DataSourceBuilder.create() - .url("jdbc:mysql://localhost:3306/test") - .username("root") - .password("980726") - .type(HikariDataSource.class) - .build(); - dataSource.setMaximumPoolSize(1000); - dataSource.setMinimumIdle(100); - return dataSource; - } - - @Bean - public JdbcTemplate jdbcTemplate(DataSource dataSource) { - return new JdbcTemplate(dataSource); - } - - @Bean - public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { - return new NamedParameterJdbcTemplate(jdbcTemplate); - } - } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index d3f778a51b..1249bc76b2 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -1,23 +1,18 @@ package com.programmers.vouchermanagement.wallet.repository; +import com.programmers.vouchermanagement.TestConfig; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerJDBCRepository; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.repository.VoucherJDBCRepository; import com.programmers.vouchermanagement.wallet.domain.Ownership; -import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.support.AnnotationConfigContextLoader; -import javax.sql.DataSource; import java.util.Optional; import java.util.UUID; @@ -28,6 +23,7 @@ @SpringJUnitConfig @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) +@ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class) class WalletJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); private final static UUID NON_EXISTENT_CUSTOMER_ID = UUID.randomUUID(); @@ -185,33 +181,4 @@ void autoDeleteAfterVoucherDelete() { assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()).isEmpty()).isTrue(); } - - @Configuration - @ComponentScan( - basePackages = {"com.programmers.vouchermanagement"} - ) - static class Config { - @Bean - public DataSource dataSource() { - var dataSource = DataSourceBuilder.create() - .url("jdbc:mysql://localhost:3306/test") - .username("root") - .password("980726") - .type(HikariDataSource.class) - .build(); - dataSource.setMaximumPoolSize(1000); - dataSource.setMinimumIdle(100); - return dataSource; - } - - @Bean - public JdbcTemplate jdbcTemplate(DataSource dataSource) { - return new JdbcTemplate(dataSource); - } - - @Bean - public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { - return new NamedParameterJdbcTemplate(jdbcTemplate); - } - } } From 206360068b8baf871c8cefe02aabcf6b85e706d6 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 29 Oct 2023 17:12:27 +0900 Subject: [PATCH 174/383] refactor: change password --- .../vouchermanagement/configuration/AppConfig.java | 2 +- .../java/com/programmers/vouchermanagement/TestConfig.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java index 129cb840ed..0f65842fe6 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java @@ -23,7 +23,7 @@ public DataSource dataSource() { var dataSource = DataSourceBuilder.create() .url("jdbc:mysql://localhost:3306/test") .username("root") - .password("980726") + .password("20231028") .type(HikariDataSource.class) .build(); dataSource.setMaximumPoolSize(1000); diff --git a/src/test/java/com/programmers/vouchermanagement/TestConfig.java b/src/test/java/com/programmers/vouchermanagement/TestConfig.java index e40dc81eec..b5f321213b 100644 --- a/src/test/java/com/programmers/vouchermanagement/TestConfig.java +++ b/src/test/java/com/programmers/vouchermanagement/TestConfig.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement; import com.zaxxer.hikari.HikariDataSource; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -14,13 +15,14 @@ @ComponentScan( basePackages = {"com.programmers.vouchermanagement"} ) +@ConfigurationPropertiesScan public class TestConfig { @Bean public DataSource dataSource() { var dataSource = DataSourceBuilder.create() .url("jdbc:mysql://localhost:3306/test") .username("root") - .password("980726") + .password("20231028") .type(HikariDataSource.class) .build(); dataSource.setMaximumPoolSize(1000); From eac8c095979c3b551c580662a00963995ded6f84 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 29 Oct 2023 17:16:46 +0900 Subject: [PATCH 175/383] refactor: change sql --- src/main/resources/schema.sql | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 5b91f93027..f6eb346ac4 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,3 +1,5 @@ +CREATE DATABASE test; +use test; CREATE TABLE customers ( id BINARY(16) PRIMARY KEY, @@ -20,6 +22,8 @@ CREATE TABLE ownership customer_id BINARY(16), FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE -) +); + + ## for init database SET FOREIGN_KEY_CHECKS = 0;TRUNCATE TABLE vouchers;TRUNCATE TABLE ownership;TRUNCATE TABLE customers;SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file From 0ee7c970506b2057aa14993613fd8ca643cf39e5 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 29 Oct 2023 17:27:16 +0900 Subject: [PATCH 176/383] refactor: add DB init sql --- .../repository/CustomerJDBCRepositoryTest.java | 12 ++++++++++++ .../repository/VoucherJDBCRepositoryTest.java | 15 ++++++++++++--- .../repository/WalletJDBCRepositoryTest.java | 12 ++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 479e7b5848..63128151d7 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -2,10 +2,12 @@ import com.programmers.vouchermanagement.TestConfig; import com.programmers.vouchermanagement.customer.domain.Customer; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.support.AnnotationConfigContextLoader; @@ -22,6 +24,16 @@ class CustomerJDBCRepositoryTest { @Autowired CustomerJDBCRepository customerJDBCRepository; + @Autowired + JdbcTemplate jdbcTemplate; + + @AfterAll + void init() { + jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 0"); + jdbcTemplate.execute("TRUNCATE TABLE test.customers"); + jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); + } + @Test @DisplayName("🆗 블랙리스트를 조회할 수 있다. 단, 블랙 고객이 없는 경우 빈 list가 반환된다.") void findAllBlackCustomerSucceed() { diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index 1eed4fa4c5..b26955d313 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -3,10 +3,9 @@ import com.programmers.vouchermanagement.TestConfig; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.support.AnnotationConfigContextLoader; @@ -26,6 +25,16 @@ class VoucherJDBCRepositoryTest { @Autowired VoucherJDBCRepository voucherJDBCRepository; + @Autowired + JdbcTemplate jdbcTemplate; + + @AfterAll + void init() { + jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 0"); + jdbcTemplate.execute("TRUNCATE TABLE test.vouchers"); + jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); + } + @Test @DisplayName("🆗 고정 금액 할인 바우처를 추가할 수 있다.") void saveFixedAmountVoucher() { diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index 1249bc76b2..2c69ea35b6 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -9,6 +9,7 @@ import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.support.AnnotationConfigContextLoader; @@ -35,6 +36,17 @@ class WalletJDBCRepositoryTest { @Autowired CustomerJDBCRepository customerJDBCRepository; + @Autowired + JdbcTemplate jdbcTemplate; + + @AfterAll + void init() { + jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 0"); + jdbcTemplate.execute("TRUNCATE TABLE test.vouchers"); + jdbcTemplate.execute("TRUNCATE TABLE test.ownership"); + jdbcTemplate.execute("TRUNCATE TABLE test.customers"); + jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); + } @Test @Order(1) @DisplayName("🆗 의존성 주입 테스트.") From 572123fe7fa21c57d7861d69bec61edf0f2ef510 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 29 Oct 2023 17:27:41 +0900 Subject: [PATCH 177/383] refactor: remove useless sql --- src/main/resources/schema.sql | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index f6eb346ac4..045d5c7efe 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -22,8 +22,4 @@ CREATE TABLE ownership customer_id BINARY(16), FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE -); - - -## for init database -SET FOREIGN_KEY_CHECKS = 0;TRUNCATE TABLE vouchers;TRUNCATE TABLE ownership;TRUNCATE TABLE customers;SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file +); \ No newline at end of file From ec5f94d7d411b2a23c051b2fbc2faf3cbaf328d0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 21:30:09 +0900 Subject: [PATCH 178/383] chore: change gradle repositories to mavenCentral --- build.gradle | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 6d38cbe0d4..e943aed4dd 100644 --- a/build.gradle +++ b/build.gradle @@ -10,9 +10,7 @@ plugins { apply plugin: 'io.spring.dependency-management' repositories { - maven { - url = uri('https://repo.maven.apache.org/maven2/') - } + mavenCentral() } dependencies { From fdc088e60d15ad9e82116c47289c2d9d14b2b627 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 21:33:21 +0900 Subject: [PATCH 179/383] chore: add spring-boot-starter-web dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index e943aed4dd..b90355a8c1 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ dependencies { api 'org.springframework.boot:spring-boot-starter:3.1.4' api 'com.fasterxml.jackson.core:jackson-databind:2.15.2' api 'org.beryx:text-io:3.4.1' + implementation 'org.springframework.boot:spring-boot-starter-web:3.1.5' implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.1.5' runtimeOnly(implementation 'mysql:mysql-connector-java:8.0.33') testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' From 61991434c4521da6eb5a57544f8e570cf30469cb Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 21:33:35 +0900 Subject: [PATCH 180/383] chore: add spring-boot-starter-thymeleaf dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index b90355a8c1..e22fd4c073 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ dependencies { api 'org.beryx:text-io:3.4.1' implementation 'org.springframework.boot:spring-boot-starter-web:3.1.5' implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.1.5' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.5' runtimeOnly(implementation 'mysql:mysql-connector-java:8.0.33') testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' } From 4713b2db7aee510bc634436d9168031695cec864 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 21:33:50 +0900 Subject: [PATCH 181/383] chore: add spring-boot-starter-aop dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index e22fd4c073..c1a6b6b5c0 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:3.1.5' implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.1.5' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.5' + implementation 'org.springframework.boot:spring-boot-starter-aop:3.1.5' runtimeOnly(implementation 'mysql:mysql-connector-java:8.0.33') testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' } From cb37df9191dd2850f645475e3b7b6b33ca2f48c0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 22:44:17 +0900 Subject: [PATCH 182/383] feat: implement MvcConfig and add CorsMappings --- .../vouchermanagement/configuration/MvcConfig.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java new file mode 100644 index 0000000000..ed40b2da77 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java @@ -0,0 +1,14 @@ +package com.programmers.vouchermanagement.configuration; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class MvcConfig implements WebMvcConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/api/*") + .allowedOrigins("*"); + } +} From cdda8de27c393925a456498b4eccf864b75bfbcd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 22:57:44 +0900 Subject: [PATCH 183/383] refactor: change voucjer service method names --- .../voucher/service/VoucherService.java | 16 ++++++++++------ .../voucher/service/VoucherServiceTest.java | 12 ++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index f74be230ce..c24690cc9b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,9 +1,9 @@ package com.programmers.vouchermanagement.voucher.service; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; -import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; import java.util.Collections; @@ -18,13 +18,13 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public VoucherResponse createVoucher(CreateVoucherRequest createVoucherRequest) { + public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType()); voucherRepository.save(voucher); return VoucherResponse.from(voucher); } - public List readAllVouchers() { + public List readAll() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { @@ -36,15 +36,19 @@ public List readAllVouchers() { .toList(); } - public void readVoucherById(UUID voucherId) { + public void readById(UUID voucherId) { voucherRepository.findById(voucherId); } - public void deleteVoucher(UUID voucherId) { + public void delete(UUID voucherId) { voucherRepository.delete(voucherId); } - public void updateVoucher(Voucher voucher) { + public void deleteAll() { + voucherRepository.deleteAll(); + } + + public void update(Voucher voucher) { voucherRepository.update(voucher); } diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 1d8d6fcecd..ee114edd6a 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -41,7 +41,7 @@ void initTest() { @DisplayName("고정 할인 금액 바우처 객체를 생성할 수 있다.") void createFixedAmountVoucherSucceed() { CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(1000, VoucherType.FIXED); - voucherService.createVoucher(createVoucherRequest); + voucherService.create(createVoucherRequest); verify(voucherRepository, times(1)).save(any(Voucher.class)); } @@ -50,7 +50,7 @@ void createFixedAmountVoucherSucceed() { @DisplayName("퍼센트 할인 바우처 객체를 생성할 수 있다.") void createPercentDiscountVoucherSucceed() { CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(100, VoucherType.PERCENT); - voucherService.createVoucher(createVoucherRequest); + voucherService.create(createVoucherRequest); verify(voucherRepository, times(1)).save(any(Voucher.class)); } @@ -58,7 +58,7 @@ void createPercentDiscountVoucherSucceed() { @Test @DisplayName("모든 바우처를 조회할 수 있다.") void readAllVouchersSucceed() { - voucherService.readAllVouchers(); + voucherService.readAll(); when(voucherRepository.findAll()).thenReturn(new ArrayList<>()); @@ -68,7 +68,7 @@ void readAllVouchersSucceed() { @Test @DisplayName("바우처를 id로 조회할 수 있다.") void readVoucherByIdSucceed() { - voucherService.readVoucherById(mockId); + voucherService.readById(mockId); when(voucherRepository.findById(mockId)).thenReturn(Optional.of(mockVoucher)); @@ -78,7 +78,7 @@ void readVoucherByIdSucceed() { @Test @DisplayName("바우처를 id로 삭제할 수 있다.") void deleteVoucherSucceed() { - voucherService.deleteVoucher(mockId); + voucherService.delete(mockId); verify(voucherRepository, times(1)).delete(any(UUID.class)); } @@ -86,7 +86,7 @@ void deleteVoucherSucceed() { @Test @DisplayName("바우처를 업데이트할 수 있다.") void updateVoucherSucceed() { - voucherService.updateVoucher(new Voucher(UUID.randomUUID(), 100, VoucherType.FIXED)); + voucherService.update(new Voucher(UUID.randomUUID(), 100, VoucherType.FIXED)); verify(voucherRepository, times(1)).update(any(Voucher.class)); } From ec6cbdde72956b6ca648906a28ac39ab01f06cce Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 22:58:09 +0900 Subject: [PATCH 184/383] refactor: change voucher controller method names --- .../consoleapp/menu/MenuHandler.java | 4 +- .../voucher/controller/VoucherController.java | 41 +++++++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index c03a078baa..3cc3e4215f 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -65,11 +65,11 @@ private void executeMenu(Menu menu) { case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { CreateVoucherRequest createVoucherRequest = consoleManager.instructCreate(); - VoucherResponse voucherResponse = voucherController.createVoucher(createVoucherRequest); + VoucherResponse voucherResponse = voucherController.create(createVoucherRequest); consoleManager.printCreateResult(voucherResponse); } case LIST -> { - List voucherResponses = voucherController.readAllVouchers(); + List voucherResponses = voucherController.readAll(); consoleManager.printReadAllVouchers(voucherResponses); } //TODO: customerDTO diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 9bffef4238..01cea6896f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,12 +1,16 @@ package com.programmers.vouchermanagement.voucher.controller; +import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.UUID; +@RequestMapping("/api/v1/vouchers") @Controller public class VoucherController { private final VoucherService voucherService; @@ -15,11 +19,40 @@ public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } - public VoucherResponse createVoucher(CreateVoucherRequest createVoucherRequest) { - return voucherService.createVoucher(createVoucherRequest); + @PostMapping + @ResponseBody + public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + return voucherService.create(createVoucherRequest); } - public List readAllVouchers() { - return voucherService.readAllVouchers(); + @GetMapping + @ResponseBody + public List readAll() { + return voucherService.readAll(); } + + @GetMapping("/{voucherId}") + @ResponseBody + public void readById(@PathVariable("voucherId") UUID voucherId) { + voucherService.readById(voucherId); + } + + @DeleteMapping("/{voucherId}") + @ResponseBody + public void delete(@PathVariable("voucherId") UUID voucherId) { + voucherService.delete(voucherId); + } + + @DeleteMapping + @ResponseBody + public void deleteAll() { + voucherService.deleteAll(); + } + + @PutMapping + @ResponseBody + public void update(Voucher voucher) { + voucherService.update(voucher); + } + } From 444008910eed982dfb44e72a741f98604f197a07 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 23:54:48 +0900 Subject: [PATCH 185/383] refactor: refactor readById in VoucherService --- .../voucher/service/VoucherService.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index c24690cc9b..db4e7ad68b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,15 +1,18 @@ package com.programmers.vouchermanagement.voucher.service; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; +import java.util.NoSuchElementException; import java.util.UUID; +import static com.programmers.vouchermanagement.constant.Message.NOT_FOUND_VOUCHER; + @Service public class VoucherService { private final VoucherRepository voucherRepository; @@ -36,8 +39,11 @@ public List readAll() { .toList(); } - public void readById(UUID voucherId) { - voucherRepository.findById(voucherId); + public VoucherResponse readById(UUID voucherId) { + Voucher voucher = voucherRepository + .findById(voucherId) + .orElseThrow(() -> new NoSuchElementException(NOT_FOUND_VOUCHER)); + return VoucherResponse.from(voucher); } public void delete(UUID voucherId) { From 276345ec286c14356c598d718689da4e6b45a476 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 23:55:12 +0900 Subject: [PATCH 186/383] feat: implement VoucherMVCController --- .../controller/VoucherMVCController.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java new file mode 100644 index 0000000000..87350d8395 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java @@ -0,0 +1,66 @@ +package com.programmers.vouchermanagement.voucher.controller; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.service.VoucherService; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@Profile("mvc") +@RequestMapping("/vouchers") +@Controller +public class VoucherMVCController { + private final VoucherService voucherService; + + public VoucherMVCController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + @PostMapping + public String create(CreateVoucherRequest createVoucherRequest) { + voucherService.create(createVoucherRequest); + return "redirect:/customers"; + } + + @GetMapping + public String viewVouchersPage(Model model) { + List vouchers = voucherService.readAll(); + model.addAttribute("vouchers", vouchers); + return "view/customers"; + } + + @GetMapping("/{voucherId}") + public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { + try { + VoucherResponse voucher = voucherService.readById(voucherId); + model.addAttribute("vouchers", List.of(voucher)); + return "view/customers"; + } catch (RuntimeException e) { + return "view/404"; + } + } + + @DeleteMapping("/{voucherId}") + public String delete(@PathVariable("voucherId") UUID voucherId) { + voucherService.delete(voucherId); + return "redirect:/customers"; + } + + @DeleteMapping + public String deleteAll() { + voucherService.deleteAll(); + return "redirect:/customers"; + } + + @PutMapping + public String update(Voucher voucher) { + voucherService.update(voucher); + return "redirect:/customers"; + } +} From 7715a574d56648833ac7b7d507685f2c501edc73 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 23:55:51 +0900 Subject: [PATCH 187/383] enhance: add api, console Profile at VoucherController --- .../vouchermanagement/voucher/controller/VoucherController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 01cea6896f..248ff38c5e 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -4,12 +4,14 @@ import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.UUID; +@Profile({"api", "console"}) @RequestMapping("/api/v1/vouchers") @Controller public class VoucherController { From 6601d289c33f8e7d5ee3f8891f7bae2a832ad3d1 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 23:56:14 +0900 Subject: [PATCH 188/383] enhance: add not found messages --- .../com/programmers/vouchermanagement/constant/Message.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/constant/Message.java b/src/main/java/com/programmers/vouchermanagement/constant/Message.java index 8e246526fe..9c9fc1bbca 100644 --- a/src/main/java/com/programmers/vouchermanagement/constant/Message.java +++ b/src/main/java/com/programmers/vouchermanagement/constant/Message.java @@ -6,8 +6,10 @@ public class Message { public final static String NOT_DELETED = "Noting was deleted!"; public final static String EMPTY_RESULT = "Got empty result!"; public static final String IO_EXCEPTION = "Error raised while reading file!"; - public static final String NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION = "There is no voucher allocation information."; - public static final String NOT_FOUND_CUSTOMER_ALLOCATION_INFORMATION = "There is no customer allocation information."; + public static final String NOT_FOUND_VOUCHER = "There is no such voucher."; + public static final String NOT_FOUND_CUSTOMER = "There is no such customer."; + public static final String NOT_FOUND_VOUCHER_ALLOCATION = "There is no voucher allocation information."; + public static final String NOT_FOUND_CUSTOMER_ALLOCATION = "There is no customer allocation information."; public static final String CAN_NOT_INSERT_OWNERSHIP = "There is no customer allocation information."; public static final String ALREADY_EMPTY_TABLE = "The table is already empty."; public static final String FILE_EXCEPTION = "Error raised while opening the file."; From 82006b97a9b4144b0a9f326a204abb7c1b59744c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 1 Nov 2023 23:56:38 +0900 Subject: [PATCH 189/383] refactor: change message name --- .../wallet/repository/WalletJDBCRepository.java | 4 ++-- .../vouchermanagement/wallet/service/WalletService.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index df086b4d33..35f26ac5a5 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -62,8 +62,8 @@ public List findAllVoucherByCustomerId(UUID customerId) { public void delete(UUID voucherId) { int update = jdbcTemplate.update(DELETE_OWNERSHIP, domainMapper.uuidToParamMap(voucherId)); if (update != UPDATE_ONE_FLAG) { - logger.error(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); - throw new RuntimeException(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); + logger.error(NOT_FOUND_VOUCHER_ALLOCATION); + throw new RuntimeException(NOT_FOUND_VOUCHER_ALLOCATION); } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index 1e2ec9c69a..df0f168281 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -12,7 +12,7 @@ import java.util.NoSuchElementException; import java.util.UUID; -import static com.programmers.vouchermanagement.constant.Message.NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION; +import static com.programmers.vouchermanagement.constant.Message.NOT_FOUND_VOUCHER_ALLOCATION; @Service public class WalletService { @@ -30,8 +30,8 @@ public void allocate(Ownership ownership) { public Customer readCustomerByVoucherId(UUID voucherId) { return walletRepository.findCustomerByVoucherId(voucherId).orElseThrow( () -> { - logger.error(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); - return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION_INFORMATION); + logger.error(NOT_FOUND_VOUCHER_ALLOCATION); + return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); } ); } From fc9759200b9482088742275285134f4f19bbfd70 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 00:46:13 +0900 Subject: [PATCH 190/383] refactor: change properties files --- src/main/resources/application-dev.yaml | 9 --------- src/main/resources/application-mvc.yaml | 4 ++++ .../{application-prod.yaml => application.yaml} | 7 ++++++- 3 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 src/main/resources/application-dev.yaml create mode 100644 src/main/resources/application-mvc.yaml rename src/main/resources/{application-prod.yaml => application.yaml} (59%) diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml deleted file mode 100644 index d79aa9c10f..0000000000 --- a/src/main/resources/application-dev.yaml +++ /dev/null @@ -1,9 +0,0 @@ -file: - resources: - path: src/main/resources/ - build-path: build/resources/main/ - - domains: - customer: - file-name: blacklist.csv - diff --git a/src/main/resources/application-mvc.yaml b/src/main/resources/application-mvc.yaml new file mode 100644 index 0000000000..0507533d87 --- /dev/null +++ b/src/main/resources/application-mvc.yaml @@ -0,0 +1,4 @@ +spring: + thymeleaf: + excluded-view-names: "views/*" + prefix: "/WEB-INF/" \ No newline at end of file diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application.yaml similarity index 59% rename from src/main/resources/application-prod.yaml rename to src/main/resources/application.yaml index c21b2d66c5..7c417a9045 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application.yaml @@ -1,7 +1,12 @@ +spring: + datasource: + url: jdbc:mysql://localhost:3306/ + username: root + password: 20231028 + file: resources: path: src/main/resources/ - build-path: build/resources/main/ domains: customer: From 57a79e268ee38bd3dad3dd1b06ae4f3d15eb72a9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 00:46:33 +0900 Subject: [PATCH 191/383] refactor: change VoucherResponse to record --- .../voucher/dto/VoucherResponse.java | 31 ++----------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java index 7bdcbd2b66..219de0d4a0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -5,34 +5,9 @@ import java.util.UUID; -public class VoucherResponse { - private final UUID voucherId; - private final long discountValue; - private final VoucherType voucherType; - - private VoucherResponse(UUID voucherId, long discountValue, VoucherType voucherType) { - this.voucherId = voucherId; - this.discountValue = discountValue; - this.voucherType = voucherType; - } - +public record VoucherResponse(UUID voucherId, long discountValue, String voucherTypeName, boolean isPercent) { public static VoucherResponse from(Voucher voucher) { - return new VoucherResponse(voucher.voucherId(), voucher.discountValue(), voucher.voucherType()); - } - - public UUID getVoucherId() { - return voucherId; - } - - public long getDiscountValue() { - return discountValue; - } - - public boolean isPercentVoucher() { - return voucherType.isPercent(); - } - - public String getVoucherTypeName() { - return voucherType.displayTypeName(); + VoucherType voucherType = voucher.voucherType(); + return new VoucherResponse(voucher.voucherId(), voucher.discountValue(), voucherType.displayTypeName(), voucherType.isPercent()); } } From 07aa3b1cb03ac066ce3c20200f868bffe70ebe31 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 00:47:28 +0900 Subject: [PATCH 192/383] refactor: delete datasource from AppConfig --- .../configuration/AppConfig.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java index 0f65842fe6..3b56d18753 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java @@ -1,9 +1,7 @@ package com.programmers.vouchermanagement.configuration; -import com.zaxxer.hikari.HikariDataSource; import org.beryx.textio.TextIO; import org.beryx.textio.TextIoFactory; -import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; @@ -18,19 +16,6 @@ public TextIO textIO() { return TextIoFactory.getTextIO(); } - @Bean - public DataSource dataSource() { - var dataSource = DataSourceBuilder.create() - .url("jdbc:mysql://localhost:3306/test") - .username("root") - .password("20231028") - .type(HikariDataSource.class) - .build(); - dataSource.setMaximumPoolSize(1000); - dataSource.setMinimumIdle(100); - return dataSource; - } - @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); From 992acc99c61d301479d6c9c4fd73d17545f06c56 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 00:49:08 +0900 Subject: [PATCH 193/383] refactor: check empty result readAllVoucherByCustomerId at WalletService --- .../wallet/service/WalletService.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index df0f168281..f118516a42 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -2,12 +2,14 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.repository.WalletRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; import java.util.UUID; @@ -28,16 +30,16 @@ public void allocate(Ownership ownership) { } public Customer readCustomerByVoucherId(UUID voucherId) { - return walletRepository.findCustomerByVoucherId(voucherId).orElseThrow( - () -> { - logger.error(NOT_FOUND_VOUCHER_ALLOCATION); - return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); - } - ); + return walletRepository.findCustomerByVoucherId(voucherId).orElseThrow(() -> { + logger.error(NOT_FOUND_VOUCHER_ALLOCATION); + return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); + }); } - public List readAllVoucherByCustomerId(UUID customerId) { - return walletRepository.findAllVoucherByCustomerId(customerId); + public List readAllVoucherByCustomerId(UUID customerId) { + List vouchers = walletRepository.findAllVoucherByCustomerId(customerId); + if (vouchers.isEmpty()) return Collections.emptyList(); + return vouchers.stream().map(VoucherResponse::from).toList(); } public void deleteVoucherFromCustomer(UUID voucherId) { From 0b6cdc7981a96d685616bfc1c01b7189eb38b519 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 00:51:55 +0900 Subject: [PATCH 194/383] fix: fix return url value --- .../voucher/controller/VoucherMVCController.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java index 87350d8395..c7cc80d2ec 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java @@ -25,14 +25,14 @@ public VoucherMVCController(VoucherService voucherService) { @PostMapping public String create(CreateVoucherRequest createVoucherRequest) { voucherService.create(createVoucherRequest); - return "redirect:/customers"; + return "redirect:/vouchers"; } @GetMapping public String viewVouchersPage(Model model) { List vouchers = voucherService.readAll(); model.addAttribute("vouchers", vouchers); - return "view/customers"; + return "views/vouchers"; } @GetMapping("/{voucherId}") @@ -40,27 +40,27 @@ public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { try { VoucherResponse voucher = voucherService.readById(voucherId); model.addAttribute("vouchers", List.of(voucher)); - return "view/customers"; + return "views/vouchers"; } catch (RuntimeException e) { - return "view/404"; + return "views/404"; } } @DeleteMapping("/{voucherId}") public String delete(@PathVariable("voucherId") UUID voucherId) { voucherService.delete(voucherId); - return "redirect:/customers"; + return "redirect:/vouchers"; } @DeleteMapping public String deleteAll() { voucherService.deleteAll(); - return "redirect:/customers"; + return "redirect:/vouchers"; } @PutMapping public String update(Voucher voucher) { voucherService.update(voucher); - return "redirect:/customers"; + return "redirect:/vouchers"; } } From 7187d5af124c04c35e040a660dd6c74668cc9acc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 01:44:31 +0900 Subject: [PATCH 195/383] refactor: change log level to debug --- src/main/resources/logback-spring.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 2a17a4b164..0b3435e715 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -18,7 +18,7 @@ - + From ba02841866eb8ed9e6665a68cdc8c9cefeed92dd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:17:46 +0900 Subject: [PATCH 196/383] refactor: remove excluded view names --- src/main/resources/application-mvc.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/application-mvc.yaml b/src/main/resources/application-mvc.yaml index 0507533d87..c5cdcd8b4c 100644 --- a/src/main/resources/application-mvc.yaml +++ b/src/main/resources/application-mvc.yaml @@ -1,4 +1,3 @@ spring: thymeleaf: - excluded-view-names: "views/*" prefix: "/WEB-INF/" \ No newline at end of file From dc58b5a6cafbcf9be70feaec1b9601f441b8d403 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:18:46 +0900 Subject: [PATCH 197/383] refactor: modify voucherResponse to record at ConsoleManager --- .../consoleapp/io/ConsoleManager.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 95084676c8..99553068ce 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -78,7 +78,7 @@ public CreateVoucherRequest instructCreate() { } public void printCreateResult(VoucherResponse voucherResponse) { - textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.getVoucherId())); + textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.voucherId())); } public void printReadAllVouchers(List voucherResponses) { @@ -109,10 +109,10 @@ private String formatVoucherDTO(VoucherResponse voucherResponse) { Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------""" - .formatted(voucherResponse.getVoucherId(), - voucherResponse.getVoucherTypeName(), - voucherResponse.getDiscountValue() + - (voucherResponse.isPercentVoucher() ? PERCENTAGE : EMPTY)); + .formatted(voucherResponse.voucherId(), + voucherResponse.voucherTypeName(), + voucherResponse.discountValue() + + (voucherResponse.isPercent() ? PERCENTAGE : EMPTY)); } public void printExit() { From 91d23afd02494e164fe12ddd4cc9623f747d39d5 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:19:15 +0900 Subject: [PATCH 198/383] refactor: change VoucherFileRepository profile name to "file" --- .../voucher/repository/VoucherFileRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index c4f5e5357c..75f8735922 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -18,7 +18,7 @@ import static com.programmers.vouchermanagement.constant.Message.*; @Repository -@Profile("prod") +@Profile("file") public class VoucherFileRepository implements VoucherRepository { private static final Logger logger = LoggerFactory.getLogger(VoucherFileRepository.class); From ac897260059d7de06db5fa0e4ffdae62ca114f07 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:19:26 +0900 Subject: [PATCH 199/383] refactor: change VoucherInMemoryRepository profile name to "memory" --- .../voucher/repository/VoucherInMemoryRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index 92ce1b6d07..04d02239b2 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -10,7 +10,7 @@ import static com.programmers.vouchermanagement.constant.Message.NOT_UPDATED; @Repository -@Profile("dev") +@Profile("memory") public class VoucherInMemoryRepository implements VoucherRepository { private final Map vouchers; From 889ed83f9322247016f1994ef31e12999ac6612e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:20:02 +0900 Subject: [PATCH 200/383] refactor: change VoucherJDBCRepository profile name to "jdbc" --- .../voucher/repository/VoucherJDBCRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index e8ee644156..c4d4e7b0e9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -17,9 +18,8 @@ import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.constant.Message.*; import static com.programmers.vouchermanagement.voucher.repository.VoucherQuery.*; - +@Profile("jdbc") @Repository -@Primary public class VoucherJDBCRepository implements VoucherRepository { private static final Logger logger = LoggerFactory.getLogger(VoucherJDBCRepository.class); private final NamedParameterJdbcTemplate jdbcTemplate; From 7cba91380a100ed70b65f4ab1ab8659f8ddd50e8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:20:35 +0900 Subject: [PATCH 201/383] refactor:remove default profile --- .../vouchermanagement/VoucherManagementApplication.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java index dde3bdb2ad..4da2f2d990 100644 --- a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java +++ b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java @@ -10,7 +10,6 @@ public class VoucherManagementApplication { public static void main(String[] args) { var application = new SpringApplication(VoucherManagementApplication.class); - application.setAdditionalProfiles("prod"); application.run(args); } From f958b5244171e5b702a88282a45b57ad50c7b475 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:29:38 +0900 Subject: [PATCH 202/383] refactor:rename from VoucherResponse to VoucherDto --- .../consoleapp/io/ConsoleManager.java | 22 +++++++++---------- .../consoleapp/menu/MenuHandler.java | 10 ++++----- .../voucher/controller/VoucherController.java | 6 ++--- .../controller/VoucherMVCController.java | 6 ++--- .../voucher/dto/VoucherDto.java | 13 +++++++++++ .../voucher/dto/VoucherResponse.java | 13 ----------- .../voucher/service/VoucherService.java | 14 ++++++------ .../wallet/service/WalletService.java | 6 ++--- 8 files changed, 45 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 99553068ce..ad62813a58 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -5,7 +5,7 @@ import com.programmers.vouchermanagement.util.Validator; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -77,15 +77,15 @@ public CreateVoucherRequest instructCreate() { return new CreateVoucherRequest(Long.parseLong(discountValueStr), voucherType); } - public void printCreateResult(VoucherResponse voucherResponse) { - textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucherResponse.voucherId())); + public void printCreateResult(VoucherDto voucher) { + textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucher.voucherId())); } - public void printReadAllVouchers(List voucherResponses) { - if (voucherResponses.isEmpty()) { + public void printReadAllVouchers(List vouchers) { + if (vouchers.isEmpty()) { textIO.getTextTerminal().println(NO_CONTENT.formatted("voucher")); } - voucherResponses.forEach(voucherResponse -> textIO.getTextTerminal().println(formatVoucherDTO(voucherResponse))); + vouchers.forEach(voucher -> textIO.getTextTerminal().println(formatVoucherDTO(voucher))); } public void printReadBlacklist(List customerResponses) { @@ -103,16 +103,16 @@ private String formatCustomer(Customer customer) { .formatted(customer.getCustomerId(), customer.getName()); } - private String formatVoucherDTO(VoucherResponse voucherResponse) { + private String formatVoucherDTO(VoucherDto voucher) { return """ Voucher ID : %s Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------""" - .formatted(voucherResponse.voucherId(), - voucherResponse.voucherTypeName(), - voucherResponse.discountValue() + - (voucherResponse.isPercent() ? PERCENTAGE : EMPTY)); + .formatted(voucher.voucherId(), + voucher.voucherTypeName(), + voucher.discountValue() + + (voucher.isPercent() ? PERCENTAGE : EMPTY)); } public void printExit() { diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 3cc3e4215f..5aaedc778c 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -5,7 +5,7 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.controller.VoucherController; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -65,12 +65,12 @@ private void executeMenu(Menu menu) { case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { CreateVoucherRequest createVoucherRequest = consoleManager.instructCreate(); - VoucherResponse voucherResponse = voucherController.create(createVoucherRequest); - consoleManager.printCreateResult(voucherResponse); + VoucherDto voucher = voucherController.create(createVoucherRequest); + consoleManager.printCreateResult(voucher); } case LIST -> { - List voucherResponses = voucherController.readAll(); - consoleManager.printReadAllVouchers(voucherResponses); + List voucher = voucherController.readAll(); + consoleManager.printReadAllVouchers(voucher); } //TODO: customerDTO case BLACKLIST -> { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 248ff38c5e..7d115a064c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.voucher.service.VoucherService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; @@ -23,13 +23,13 @@ public VoucherController(VoucherService voucherService) { @PostMapping @ResponseBody - public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + public VoucherDto create(CreateVoucherRequest createVoucherRequest) { return voucherService.create(createVoucherRequest); } @GetMapping @ResponseBody - public List readAll() { + public List readAll() { return voucherService.readAll(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java index c7cc80d2ec..cb59f5d736 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.voucher.service.VoucherService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; @@ -30,7 +30,7 @@ public String create(CreateVoucherRequest createVoucherRequest) { @GetMapping public String viewVouchersPage(Model model) { - List vouchers = voucherService.readAll(); + List vouchers = voucherService.readAll(); model.addAttribute("vouchers", vouchers); return "views/vouchers"; } @@ -38,7 +38,7 @@ public String viewVouchersPage(Model model) { @GetMapping("/{voucherId}") public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { try { - VoucherResponse voucher = voucherService.readById(voucherId); + VoucherDto voucher = voucherService.readById(voucherId); model.addAttribute("vouchers", List.of(voucher)); return "views/vouchers"; } catch (RuntimeException e) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java new file mode 100644 index 0000000000..085240187a --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java @@ -0,0 +1,13 @@ +package com.programmers.vouchermanagement.voucher.dto; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; + +import java.util.UUID; + +public record VoucherDto(UUID voucherId, long discountValue, String voucherTypeName, boolean isPercent) { + public static VoucherDto from(Voucher voucher) { + VoucherType voucherType = voucher.voucherType(); + return new VoucherDto(voucher.voucherId(), voucher.discountValue(), voucherType.displayTypeName(), voucherType.isPercent()); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java deleted file mode 100644 index 219de0d4a0..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.programmers.vouchermanagement.voucher.dto; - -import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; - -import java.util.UUID; - -public record VoucherResponse(UUID voucherId, long discountValue, String voucherTypeName, boolean isPercent) { - public static VoucherResponse from(Voucher voucher) { - VoucherType voucherType = voucher.voucherType(); - return new VoucherResponse(voucher.voucherId(), voucher.discountValue(), voucherType.displayTypeName(), voucherType.isPercent()); - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index db4e7ad68b..5e7c60cbbc 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; @@ -21,13 +21,13 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + public VoucherDto create(CreateVoucherRequest createVoucherRequest) { Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType()); voucherRepository.save(voucher); - return VoucherResponse.from(voucher); + return VoucherDto.from(voucher); } - public List readAll() { + public List readAll() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { @@ -35,15 +35,15 @@ public List readAll() { } return vouchers.stream() - .map(VoucherResponse::from) + .map(VoucherDto::from) .toList(); } - public VoucherResponse readById(UUID voucherId) { + public VoucherDto readById(UUID voucherId) { Voucher voucher = voucherRepository .findById(voucherId) .orElseThrow(() -> new NoSuchElementException(NOT_FOUND_VOUCHER)); - return VoucherResponse.from(voucher); + return VoucherDto.from(voucher); } public void delete(UUID voucherId) { diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index f118516a42..322568a44b 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.repository.WalletRepository; import org.slf4j.Logger; @@ -36,10 +36,10 @@ public Customer readCustomerByVoucherId(UUID voucherId) { }); } - public List readAllVoucherByCustomerId(UUID customerId) { + public List readAllVoucherByCustomerId(UUID customerId) { List vouchers = walletRepository.findAllVoucherByCustomerId(customerId); if (vouchers.isEmpty()) return Collections.emptyList(); - return vouchers.stream().map(VoucherResponse::from).toList(); + return vouchers.stream().map(VoucherDto::from).toList(); } public void deleteVoucherFromCustomer(UUID voucherId) { From 8ec081c3e4978819f6f4ad23dd27a5ff2fde83cc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:33:39 +0900 Subject: [PATCH 203/383] feat:apply CustomerDto --- .../consoleapp/io/ConsoleManager.java | 16 ++++++++-------- .../consoleapp/menu/MenuHandler.java | 10 +++++----- .../customer/controller/CustomerController.java | 4 ++-- .../customer/dto/CustomerDto.java | 10 ++++++++++ .../customer/service/CustomerService.java | 5 +++-- 5 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index ad62813a58..d4c4844df7 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.consoleapp.io; import com.programmers.vouchermanagement.consoleapp.menu.Menu; -import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.util.Validator; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; @@ -78,7 +78,7 @@ public CreateVoucherRequest instructCreate() { } public void printCreateResult(VoucherDto voucher) { - textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucher.voucherId())); + textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucher.id())); } public void printReadAllVouchers(List vouchers) { @@ -88,19 +88,19 @@ public void printReadAllVouchers(List vouchers) { vouchers.forEach(voucher -> textIO.getTextTerminal().println(formatVoucherDTO(voucher))); } - public void printReadBlacklist(List customerResponses) { - if (customerResponses.isEmpty()) { + public void printReadBlacklist(List customers) { + if (customers.isEmpty()) { textIO.getTextTerminal().println(NO_CONTENT.formatted("black customer")); } - customerResponses.forEach(customerResponse -> textIO.getTextTerminal().println(formatCustomer(customerResponse))); + customers.forEach(customer -> textIO.getTextTerminal().println(formatCustomer(customer))); } - private String formatCustomer(Customer customer) { + private String formatCustomer(CustomerDto customer) { return """ Customer ID : %s Customer Name : %s -------------------------""" - .formatted(customer.getCustomerId(), customer.getName()); + .formatted(customer.id(), customer.name()); } private String formatVoucherDTO(VoucherDto voucher) { @@ -109,7 +109,7 @@ private String formatVoucherDTO(VoucherDto voucher) { Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------""" - .formatted(voucher.voucherId(), + .formatted(voucher.id(), voucher.voucherTypeName(), voucher.discountValue() + (voucher.isPercent() ? PERCENTAGE : EMPTY)); diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 5aaedc778c..76fc059518 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; import com.programmers.vouchermanagement.customer.controller.CustomerController; -import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.voucher.controller.VoucherController; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherDto; @@ -69,13 +69,13 @@ private void executeMenu(Menu menu) { consoleManager.printCreateResult(voucher); } case LIST -> { - List voucher = voucherController.readAll(); - consoleManager.printReadAllVouchers(voucher); + List vouchers = voucherController.readAll(); + consoleManager.printReadAllVouchers(vouchers); } //TODO: customerDTO case BLACKLIST -> { - List customerResponses = customerController.readAllBlackCustomer(); - consoleManager.printReadBlacklist(customerResponses); + List blackCustomers = customerController.readAllBlackCustomer(); + consoleManager.printReadBlacklist(blackCustomers); } } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index adb8282945..67e23bfd70 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -1,6 +1,6 @@ package com.programmers.vouchermanagement.customer.controller; -import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.customer.service.CustomerService; import org.springframework.stereotype.Controller; @@ -14,7 +14,7 @@ public CustomerController(CustomerService customerService) { this.customerService = customerService; } - public List readAllBlackCustomer() { + public List readAllBlackCustomer() { return customerService.readAllBlackCustomer(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java b/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java new file mode 100644 index 0000000000..9a821e1560 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java @@ -0,0 +1,10 @@ +package com.programmers.vouchermanagement.customer.dto; +import com.programmers.vouchermanagement.customer.domain.Customer; + +import java.util.UUID; + +public record CustomerDto(UUID id, String name, boolean isBlack) { + public static CustomerDto from(Customer customer) { + return new CustomerDto(customer.getCustomerId(), customer.getName(), customer.isBlack()); + } +} \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 48576eefda..49c9a167bd 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.customer.service; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import org.springframework.stereotype.Service; @@ -15,11 +16,11 @@ public CustomerService(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } - public List readAllBlackCustomer() { + public List readAllBlackCustomer() { List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { return Collections.emptyList(); } - return blacklist; + return blacklist.stream().map(CustomerDto::from).toList(); } } From fd65a36de73600fd57071e3bed9a351472a1c861 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:39:43 +0900 Subject: [PATCH 204/383] feat:rename field name form voucherId to id at VoucherDto --- .../programmers/vouchermanagement/voucher/dto/VoucherDto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java index 085240187a..a547773bb7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java @@ -5,7 +5,7 @@ import java.util.UUID; -public record VoucherDto(UUID voucherId, long discountValue, String voucherTypeName, boolean isPercent) { +public record VoucherDto(UUID id, long discountValue, String voucherTypeName, boolean isPercent) { public static VoucherDto from(Voucher voucher) { VoucherType voucherType = voucher.voucherType(); return new VoucherDto(voucher.voucherId(), voucher.discountValue(), voucherType.displayTypeName(), voucherType.isPercent()); From 99574c63a721640c15f69f6ffeed9ce806afb177 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:41:46 +0900 Subject: [PATCH 205/383] feat:implement cusotomers page --- src/main/webapp/WEB-INF/views/customers.html | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/webapp/WEB-INF/views/customers.html diff --git a/src/main/webapp/WEB-INF/views/customers.html b/src/main/webapp/WEB-INF/views/customers.html new file mode 100644 index 0000000000..ea720e679f --- /dev/null +++ b/src/main/webapp/WEB-INF/views/customers.html @@ -0,0 +1,31 @@ + + + + + + + + Home + + +

Customers

+ + + + + + + + + + + + + + + +
IDNameIs Black?
+ + \ No newline at end of file From 8894b4bbf6c365043dab2652cd9d37b0c7e786dc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 09:42:13 +0900 Subject: [PATCH 206/383] feat:implement vouchers page --- src/main/webapp/WEB-INF/views/vouchers.html | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/webapp/WEB-INF/views/vouchers.html diff --git a/src/main/webapp/WEB-INF/views/vouchers.html b/src/main/webapp/WEB-INF/views/vouchers.html new file mode 100644 index 0000000000..52c072c6ed --- /dev/null +++ b/src/main/webapp/WEB-INF/views/vouchers.html @@ -0,0 +1,31 @@ + + + + + + + + Home + + +

Vouchers

+ + + + + + + + + + + + + + + +
IDDiscount Valuevoucher Type
+ + \ No newline at end of file From 6437dfe24b3e45b0436058996c8a51f8b78f1c5d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 11:27:25 +0900 Subject: [PATCH 207/383] feat:implement CustomerFileManager --- .../repository/CustomerFileManager.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java new file mode 100644 index 0000000000..7f3b45cf32 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java @@ -0,0 +1,67 @@ +package com.programmers.vouchermanagement.customer.repository; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.properties.AppProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static com.programmers.vouchermanagement.constant.Constant.COMMA_SEPARATOR; +import static com.programmers.vouchermanagement.constant.Message.FILE_EXCEPTION; +import static com.programmers.vouchermanagement.constant.Message.IO_EXCEPTION; + +@Component +public class CustomerFileManager { + private static final Logger logger = LoggerFactory.getLogger(CustomerFileManager.class); + public final Map customers; + private final String filePath; + + public CustomerFileManager(AppProperties appProperties) { + this.filePath = appProperties.resources().path() + appProperties.domains().get("customer").fileName(); + this.customers = new HashMap<>(); + loadFile(); + } + + private void loadFile() { + try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { + br.readLine(); // skip the first line + String str; + while ((str = br.readLine()) != null) { + Customer customer = stringToCustomer(str); + customers.put(customer.getCustomerId(), customer); + } + } catch (IOException e) { + logger.warn(IO_EXCEPTION); + throw new UncheckedIOException(e); + } + } + + private Customer stringToCustomer(String line) { + String[] customerInfo = line.split(COMMA_SEPARATOR); + UUID customerId = UUID.fromString(customerInfo[0]); + String name = customerInfo[1]; + boolean isBlack = Boolean.parseBoolean(customerInfo[2]); + return new Customer(customerId, name, isBlack); + } + + public void saveFile() { + File csvOutputFile = new File(filePath); + try (PrintWriter pw = new PrintWriter(csvOutputFile)) { + customers.values().forEach((customer) -> pw.println(customerToString(customer))); + } catch (FileNotFoundException e) { + logger.warn(FILE_EXCEPTION); + throw new RuntimeException(e); + } + } + + private String customerToString(Customer customer) { + return customer.getCustomerId().toString() + COMMA_SEPARATOR + + customer.getName() + COMMA_SEPARATOR + + customer.isBlack(); + } +} From 381760c78120d262a1d0bf4e9516a7bd7412105e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 11:27:36 +0900 Subject: [PATCH 208/383] feat:implement VoucherFileManager --- .../repository/VoucherFileManager.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java new file mode 100644 index 0000000000..d242bdfa42 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java @@ -0,0 +1,89 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.programmers.vouchermanagement.properties.AppProperties; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.*; + +import static com.programmers.vouchermanagement.constant.Message.*; + +@Component +public class VoucherFileManager { + static final String VOUCHER_TYPE_KEY = "voucher_type"; + private static final Logger logger = LoggerFactory.getLogger(VoucherFileManager.class); + private static final String VOUCHER_ID_KEY = "voucher_id"; + private static final String DISCOUNT_VALUE_KEY = "discount_value"; + public final Map vouchers; + private final ObjectMapper objectMapper = new ObjectMapper(); + private final String filePath; + + public VoucherFileManager(AppProperties appProperties) { + this.filePath = appProperties.resources().path() + appProperties.domains().get("voucher").fileName(); + vouchers = new HashMap<>(); + loadFile(); + } + + public void loadFile() { + try { + File file = new File(filePath); + Map[] voucherObjects = objectMapper.readValue(file, Map[].class); + loadVouchers(voucherObjects); + } catch (IOException e) { + logger.error(IO_EXCEPTION); + throw new UncheckedIOException(e); + } + } + + public void loadVouchers(Map[] voucherObjects) { + Arrays.stream(voucherObjects).forEach(voucherObject -> { + Voucher voucher = objectToVoucher(voucherObject); + vouchers.put(voucher.voucherId(), voucher); + }); + } + + private Voucher objectToVoucher(Map voucherObject) { + UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(VOUCHER_ID_KEY))); + long discountValue = Long.parseLong(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); + String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); + VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) + .orElseThrow(() -> { + logger.error(INVALID_VOUCHER_TYPE); + return new NoSuchElementException(INVALID_VOUCHER_TYPE); + }); + return new Voucher(voucherId, discountValue, voucherType); + } + + public void saveFile() { + try (FileWriter fileWriter = new FileWriter(filePath)) { + List> voucherObjects = new ArrayList<>(); + if (!vouchers.isEmpty()) { + vouchers.values().forEach(voucher -> { + HashMap voucherObject = voucherToObject(voucher); + voucherObjects.add(voucherObject); + }); + } + String jsonStr = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(voucherObjects); + fileWriter.write(jsonStr); + fileWriter.flush(); + } catch (Exception e) { + throw new RuntimeException(FILE_EXCEPTION); + } + } + + private HashMap voucherToObject(Voucher voucher) { + HashMap voucherObject = new HashMap<>(); + voucherObject.put(VOUCHER_ID_KEY, voucher.voucherId().toString()); + voucherObject.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); + voucherObject.put(VOUCHER_TYPE_KEY, voucher.voucherType().name()); + return voucherObject; + } +} From 4f6472daa0bc4279ac26774bc36fb874a23fea72 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 11:28:12 +0900 Subject: [PATCH 209/383] feat:apply CustomerFileManager and implement save method --- .../repository/CustomerFileRepository.java | 55 +++++-------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 64363ec630..4a97ece04b 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -1,63 +1,34 @@ package com.programmers.vouchermanagement.customer.repository; import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.properties.AppProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.*; - -import static com.programmers.vouchermanagement.constant.Constant.COMMA_SEPARATOR; -import static com.programmers.vouchermanagement.constant.Message.IO_EXCEPTION; +import java.util.List; @Repository -@Profile({"dev", "prod"}) +@Profile({"file"}) public class CustomerFileRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerFileRepository.class); - private final String filePath; - private final Map customers; + private final CustomerFileManager customerFileManager; + + public CustomerFileRepository(CustomerFileManager customerFileManager) { + this.customerFileManager = customerFileManager; + } - public CustomerFileRepository(AppProperties appProperties) { - this.filePath = appProperties.resources().path() + appProperties.domains().get("customer").fileName(); - this.customers = new HashMap<>(); - loadBlacklist(); + @Override + public void save(Customer customer) { + customerFileManager.customers.put(customer.getCustomerId(), customer); + customerFileManager.saveFile(); } @Override public List findAllBlackCustomer() { - return customers.values() + return customerFileManager.customers.values() .stream() .filter(Customer::isBlack) .toList(); } - - private void loadBlacklist() { - List blacklist = new ArrayList<>(); - - try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { - br.readLine(); // skip the first line - String str; - while ((str = br.readLine()) != null) { - String[] line = str.split(COMMA_SEPARATOR); - - UUID blackCustomerId = UUID.fromString(line[0]); - String name = line[1]; - - Customer blackCustomer = new Customer(blackCustomerId, name, true); - - blacklist.add(blackCustomer); - } - } catch (IOException e) { - logger.error(IO_EXCEPTION); - throw new UncheckedIOException(e); - } - - blacklist.forEach(blackCustomer -> customers.put(blackCustomer.getCustomerId(), blackCustomer)); - } -} +} \ No newline at end of file From 5057fae32c67e3a6213f4c7d26bf4dd0fb3171b7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 11:28:34 +0900 Subject: [PATCH 210/383] feat: save method at CustomerRepository interface --- .../customer/repository/CustomerRepository.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java index a06f236bc9..e72b4def6e 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -1,9 +1,10 @@ package com.programmers.vouchermanagement.customer.repository; -import java.util.List; - import com.programmers.vouchermanagement.customer.domain.Customer; +import java.util.List; + public interface CustomerRepository { + void save(Customer customer); List findAllBlackCustomer(); } From 6f4b839ff2bab6719493896405ed3fd1978f85c7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 11:28:48 +0900 Subject: [PATCH 211/383] feat: implement CreateCustomerRequest --- .../vouchermanagement/customer/dto/CreateCustomerRequest.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/dto/CreateCustomerRequest.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/dto/CreateCustomerRequest.java b/src/main/java/com/programmers/vouchermanagement/customer/dto/CreateCustomerRequest.java new file mode 100644 index 0000000000..3b7ace0569 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/dto/CreateCustomerRequest.java @@ -0,0 +1,4 @@ +package com.programmers.vouchermanagement.customer.dto; + +public record CreateCustomerRequest(String name, boolean isBlack) { +} \ No newline at end of file From 392a3bc5bde2b15692409e44b9261c844774df5c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 11:29:05 +0900 Subject: [PATCH 212/383] refactor: change csv format --- src/main/resources/blacklist.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/blacklist.csv b/src/main/resources/blacklist.csv index e2efc7ccaa..195a4a730a 100644 --- a/src/main/resources/blacklist.csv +++ b/src/main/resources/blacklist.csv @@ -1,3 +1,3 @@ id,name -e8d88c24-668c-4b65-a658-44303bfbb805, 송인재 -9b46f523-03d4-41b2-a68e-0666f21c6f7d, 익명 +e8d88c24-668c-4b65-a658-44303bfbb805, 송인재, false +9b46f523-03d4-41b2-a68e-0666f21c6f7d, 익명, true From 4f590eb2970b84ccfc61f64421981a1ab9101cd7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 11:29:22 +0900 Subject: [PATCH 213/383] refactor: apply voucherFileManager at VoucherFileRepository --- .../repository/VoucherFileRepository.java | 107 ++++-------------- 1 file changed, 20 insertions(+), 87 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 75f8735922..2f3004e65e 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -1,129 +1,62 @@ package com.programmers.vouchermanagement.voucher.repository; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.programmers.vouchermanagement.properties.AppProperties; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.*; +import java.util.List; +import java.util.Optional; +import java.util.UUID; -import static com.programmers.vouchermanagement.constant.Message.*; +import static com.programmers.vouchermanagement.constant.Message.NOT_DELETED; +import static com.programmers.vouchermanagement.constant.Message.NOT_UPDATED; @Repository @Profile("file") public class VoucherFileRepository implements VoucherRepository { private static final Logger logger = LoggerFactory.getLogger(VoucherFileRepository.class); - //constants - private static final String VOUCHER_ID_KEY = "voucher_id"; - private static final String DISCOUNT_VALUE_KEY = "discount_value"; - private static final String VOUCHER_TYPE_KEY = "voucher_type"; - private final ObjectMapper objectMapper = new ObjectMapper(); - private final String filePath; - private final Map vouchers; + private final VoucherFileManager voucherFileManager; - public VoucherFileRepository(AppProperties appProperties) { - this.filePath = appProperties.resources().path() + appProperties.domains().get("voucher").fileName(); - this.vouchers = new HashMap<>(); - loadFile(); + public VoucherFileRepository(VoucherFileManager voucherFileManager) { + this.voucherFileManager = voucherFileManager; } @Override public void save(Voucher voucher) { - vouchers.put(voucher.voucherId(), voucher); - saveFile(); + voucherFileManager.vouchers.put(voucher.voucherId(), voucher); + voucherFileManager.saveFile(); } @Override public List findAll() { - return vouchers.values().stream().toList(); + return voucherFileManager.vouchers.values().stream().toList(); } @Override public Optional findById(UUID id) { - return Optional.ofNullable(vouchers.get(id)); + return Optional.ofNullable(voucherFileManager.vouchers.get(id)); } @Override public void delete(UUID id) { - Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); - saveFile(); + Optional.ofNullable(voucherFileManager.vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); + voucherFileManager.saveFile(); } @Override public void deleteAll() { - if (!vouchers.isEmpty()) - vouchers.clear(); - saveFile(); + if (!voucherFileManager.vouchers.isEmpty()) + voucherFileManager.vouchers.clear(); + voucherFileManager.saveFile(); } @Override public void update(Voucher voucher) { - Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); - vouchers.put(voucher.voucherId(), voucher); - saveFile(); - } - - private void loadFile() { - try { - File file = new File(filePath); - Map[] voucherObjects = objectMapper.readValue(file, Map[].class); - loadVouchers(voucherObjects); - } catch (IOException e) { - logger.error(IO_EXCEPTION); - throw new UncheckedIOException(e); - } - } - - private void loadVouchers(Map[] voucherObjects) { - Arrays.stream(voucherObjects).forEach(voucherObject -> { - Voucher voucher = objectToVoucher(voucherObject); - vouchers.put(voucher.voucherId(), voucher); - }); - } - - private Voucher objectToVoucher(Map voucherObject) { - UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(VOUCHER_ID_KEY))); - long discountValue = Long.parseLong(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); - String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); - VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) - .orElseThrow(() -> { - logger.error(INVALID_VOUCHER_TYPE); - return new NoSuchElementException(INVALID_VOUCHER_TYPE); - }); - return new Voucher(voucherId, discountValue, voucherType); - } - - public void saveFile() { - try (FileWriter fileWriter = new FileWriter(filePath)) { - List> voucherObjects = new ArrayList<>(); - if (!vouchers.isEmpty()) { - vouchers.values().forEach(voucher -> { - HashMap voucherObject = voucherToObject(voucher); - voucherObjects.add(voucherObject); - }); - } - String jsonStr = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(voucherObjects); - fileWriter.write(jsonStr); - fileWriter.flush(); - } catch (Exception e) { - throw new RuntimeException(FILE_EXCEPTION); - } - } - - private HashMap voucherToObject(Voucher voucher) { - HashMap voucherObject = new HashMap<>(); - voucherObject.put(VOUCHER_ID_KEY, voucher.voucherId().toString()); - voucherObject.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); - voucherObject.put(VOUCHER_TYPE_KEY, voucher.voucherType().name()); - return voucherObject; + Optional.ofNullable(voucherFileManager.vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); + voucherFileManager.vouchers.put(voucher.voucherId(), voucher); + voucherFileManager.saveFile(); } } From 3c70b49a9834c046501b5602eda436fe68fc9e71 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 13:49:29 +0900 Subject: [PATCH 214/383] feat: implement CustomerInMemoryRepository for test mode --- .../CustomerInMemoryRepository.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java new file mode 100644 index 0000000000..d0391a5a7b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java @@ -0,0 +1,36 @@ +package com.programmers.vouchermanagement.customer.repository; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Repository +@Profile("memory") +public class CustomerInMemoryRepository implements CustomerRepository { + private static final Logger logger = LoggerFactory.getLogger(CustomerInMemoryRepository.class); + private final Map customers; + + public CustomerInMemoryRepository() { + customers = new HashMap<>(); + } + + @Override + public void save(Customer customer) { + customers.put(customer.getCustomerId(), customer); + } + + @Override + public List findAllBlackCustomer() { + return customers.values() + .stream() + .filter(Customer::isBlack) + .toList(); + } +} \ No newline at end of file From 19d57631b97152650a8191daa576cd7da863678b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 13:50:12 +0900 Subject: [PATCH 215/383] refactor: add jdbc profile at CustomerJDBCRepository --- .../customer/repository/CustomerJDBCRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 85363f736e..21f2e29dd8 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -16,7 +16,7 @@ import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.INSERT; @Repository -@Primary +@Profile("jdbc") public class CustomerJDBCRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerJDBCRepository.class); private final NamedParameterJdbcTemplate jdbcTemplate; From a28cbef0020b0059cf76f3ce882f88c5018f7d26 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 13:50:28 +0900 Subject: [PATCH 216/383] refactor: modify jdbc profile at CustomerFileRepository --- .../customer/repository/CustomerFileRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 4a97ece04b..b14d0a7fbd 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -9,7 +9,7 @@ import java.util.List; @Repository -@Profile({"file"}) +@Profile("file") public class CustomerFileRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerFileRepository.class); private final CustomerFileManager customerFileManager; From d091ce05e7c3bceaacb974dacbb195669a913b6c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:05:00 +0900 Subject: [PATCH 217/383] refactor: import Profile at CustomerJDBCRepository --- .../customer/repository/CustomerJDBCRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 21f2e29dd8..84f0505738 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -4,7 +4,7 @@ import com.programmers.vouchermanagement.util.DomainMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; From 6eac4201ad58b16bc870e4df0fff0f9f1bcf8c94 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:05:18 +0900 Subject: [PATCH 218/383] style: format code style --- .../customer/repository/CustomerRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java index e72b4def6e..b3b0271830 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -6,5 +6,6 @@ public interface CustomerRepository { void save(Customer customer); + List findAllBlackCustomer(); } From c282a95aa0fff25596d9c20d4b42a78fabae2c0a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:18:56 +0900 Subject: [PATCH 219/383] refactor: change method name from getCustomerId to getId --- .../programmers/vouchermanagement/customer/domain/Customer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 3f84af229a..5aefd771e3 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -17,7 +17,7 @@ public Customer(UUID id, String name, boolean black) { this.black = black; } - public UUID getCustomerId() { + public UUID getId() { return id; } From 855d18e45ea0a9ff47826c487032767c10605bfa Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:19:52 +0900 Subject: [PATCH 220/383] refactor: apply customer.getId method name --- .../vouchermanagement/customer/dto/CustomerDto.java | 3 ++- .../customer/repository/CustomerFileManager.java | 4 ++-- .../customer/repository/CustomerFileRepository.java | 2 +- .../customer/repository/CustomerInMemoryRepository.java | 2 +- .../com/programmers/vouchermanagement/util/DomainMapper.java | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java b/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java index 9a821e1560..c9a10eef42 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java @@ -1,10 +1,11 @@ package com.programmers.vouchermanagement.customer.dto; + import com.programmers.vouchermanagement.customer.domain.Customer; import java.util.UUID; public record CustomerDto(UUID id, String name, boolean isBlack) { public static CustomerDto from(Customer customer) { - return new CustomerDto(customer.getCustomerId(), customer.getName(), customer.isBlack()); + return new CustomerDto(customer.getId(), customer.getName(), customer.isBlack()); } } \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java index 7f3b45cf32..b641098dc5 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java @@ -33,7 +33,7 @@ private void loadFile() { String str; while ((str = br.readLine()) != null) { Customer customer = stringToCustomer(str); - customers.put(customer.getCustomerId(), customer); + customers.put(customer.getId(), customer); } } catch (IOException e) { logger.warn(IO_EXCEPTION); @@ -60,7 +60,7 @@ public void saveFile() { } private String customerToString(Customer customer) { - return customer.getCustomerId().toString() + COMMA_SEPARATOR + return customer.getId().toString() + COMMA_SEPARATOR + customer.getName() + COMMA_SEPARATOR + customer.isBlack(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index b14d0a7fbd..7bf34795be 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -20,7 +20,7 @@ public CustomerFileRepository(CustomerFileManager customerFileManager) { @Override public void save(Customer customer) { - customerFileManager.customers.put(customer.getCustomerId(), customer); + customerFileManager.customers.put(customer.getId(), customer); customerFileManager.saveFile(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java index d0391a5a7b..04c1c7af0a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java @@ -23,7 +23,7 @@ public CustomerInMemoryRepository() { @Override public void save(Customer customer) { - customers.put(customer.getCustomerId(), customer); + customers.put(customer.getId(), customer); } @Override diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index 658c867ce3..5d681bf728 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -44,7 +44,7 @@ private static UUID toUUID(byte[] bytes) { public Map customerToParamMap(Customer customer) { Map paramMap = new HashMap<>(); - paramMap.put(ID_KEY, customer.getCustomerId().toString().getBytes()); + paramMap.put(ID_KEY, customer.getId().toString().getBytes()); paramMap.put(NAME_KEY, customer.getName()); paramMap.put(BLACK_KEY, customer.isBlack()); return paramMap; From 4b332e617828dd92995a44f27d39a72df8b00b0f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:41:24 +0900 Subject: [PATCH 221/383] enhance: add findAll method at CustomerRepository interface --- .../customer/repository/CustomerRepository.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java index b3b0271830..651486907f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -7,5 +7,7 @@ public interface CustomerRepository { void save(Customer customer); + List findAll(); + List findAllBlackCustomer(); } From 2965d4f2af6ebb334f8446bc35798c3a942fe9c1 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:41:38 +0900 Subject: [PATCH 222/383] enhance: implement findAll method at CustomerInMemoryRepository --- .../customer/repository/CustomerInMemoryRepository.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java index 04c1c7af0a..31e5c4f0f1 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java @@ -26,6 +26,11 @@ public void save(Customer customer) { customers.put(customer.getId(), customer); } + @Override + public List findAll() { + return customers.values().stream().toList(); + } + @Override public List findAllBlackCustomer() { return customers.values() From 11c6bc20227d9240acba4e18c9d4e3fe8f6737dc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:41:53 +0900 Subject: [PATCH 223/383] enhance: implement findAll method at CustomerFileRepository --- .../customer/repository/CustomerFileRepository.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 7bf34795be..39168499ac 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -24,11 +24,13 @@ public void save(Customer customer) { customerFileManager.saveFile(); } + @Override + public List findAll() { + return customerFileManager.customers.values().stream().toList(); + } + @Override public List findAllBlackCustomer() { - return customerFileManager.customers.values() - .stream() - .filter(Customer::isBlack) - .toList(); + return customerFileManager.customers.values().stream().filter(Customer::isBlack).toList(); } } \ No newline at end of file From 936c599670a59bdc0f248e89c62dba279de38fc3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:42:05 +0900 Subject: [PATCH 224/383] enhance: implement findAll method at CustomerJDBCRepository --- .../customer/repository/CustomerJDBCRepository.java | 8 ++++++-- .../customer/repository/CustomerQuery.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 84f0505738..876eb7f0e1 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -12,8 +12,7 @@ import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.constant.Message.NOT_INSERTED; -import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.FIND_ALL_BLACK_CUSTOMER; -import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.INSERT; +import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.*; @Repository @Profile("jdbc") @@ -39,4 +38,9 @@ public void save(Customer customer) { throw new RuntimeException(NOT_INSERTED); } } + + @Override + public List findAll() { + return jdbcTemplate.query(FIND_ALL, domainMapper.customerRowMapper); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java index af0ad1b86c..97d9d3f996 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java @@ -3,5 +3,5 @@ public class CustomerQuery { public static final String FIND_ALL_BLACK_CUSTOMER = "SELECT * FROM test.customers WHERE black = TRUE"; public static final String INSERT = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; - + public static final String FIND_ALL = "SELECT * FROM test.customers"; } From c18fa5f77e77d2badc5ff2b561e4cf86b3d06177 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:42:23 +0900 Subject: [PATCH 225/383] feat: implement CustomerMVCController --- .../controller/CustomerMVCController.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java new file mode 100644 index 0000000000..8b82d47c90 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java @@ -0,0 +1,33 @@ +package com.programmers.vouchermanagement.customer.controller; + +import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; +import com.programmers.vouchermanagement.customer.service.CustomerService; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Profile("mvc") +@RequestMapping("/customers") +@Controller +public class CustomerMVCController { + private final CustomerService customerService; + + public CustomerMVCController(CustomerService customerService) { + this.customerService = customerService; + } + + @PostMapping + public String create(CreateCustomerRequest createCustomerRequest) { + customerService.create(createCustomerRequest); + return "redirect:/customers/blacklist"; + } + + @GetMapping("/blacklist") + public String readAllBlackCustomer(Model model) { + model.addAttribute("customers", customerService.readAllBlackCustomer()); + return "views/customers"; + } +} From fd762fcdbd7d01093efeb5526f29a60b6ca7a5d8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:43:41 +0900 Subject: [PATCH 226/383] feat: add "api", "console" profile and apply url mapping at CustomerController --- .../customer/controller/CustomerController.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 67e23bfd70..23d706a0cb 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -1,11 +1,19 @@ package com.programmers.vouchermanagement.customer.controller; +import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.customer.service.CustomerService; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; import java.util.List; +@Profile({"api", "console"}) +@RequestMapping("/api/v1/customers") @Controller public class CustomerController { private final CustomerService customerService; @@ -14,6 +22,14 @@ public CustomerController(CustomerService customerService) { this.customerService = customerService; } + @PostMapping + @ResponseBody + public void create(CreateCustomerRequest createCustomerRequest) { + customerService.create(createCustomerRequest); + } + + @GetMapping("/blacklist") + @ResponseBody public List readAllBlackCustomer() { return customerService.readAllBlackCustomer(); } From 07c6ff623d3419e78e11fe84596a1a6267725794 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:44:24 +0900 Subject: [PATCH 227/383] feat: implement create customer method at CustomerService --- .../customer/service/CustomerService.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 49c9a167bd..ec26d30d3b 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -1,12 +1,14 @@ package com.programmers.vouchermanagement.customer.service; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; +import java.util.UUID; @Service public class CustomerService { @@ -16,6 +18,11 @@ public CustomerService(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } + public void create(CreateCustomerRequest createCustomerRequest) { + Customer customer = new Customer(UUID.randomUUID(), createCustomerRequest.name(), createCustomerRequest.isBlack()); + customerRepository.save(customer); + } + public List readAllBlackCustomer() { List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { From f26cc615be858ad58b1e1884f34e8fbc8a2bba57 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:48:51 +0900 Subject: [PATCH 228/383] feat: implement readAll customer method at CustomerService --- .../customer/service/CustomerService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index ec26d30d3b..ec6bb66329 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -23,6 +23,14 @@ public void create(CreateCustomerRequest createCustomerRequest) { customerRepository.save(customer); } + public List readAll() { + List customers = customerRepository.findAll(); + if (customers.isEmpty()) { + return Collections.emptyList(); + } + return customers.stream().map(CustomerDto::from).toList(); + } + public List readAllBlackCustomer() { List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { From 3a2e7cbb5844dfecbd465222d464589c432d9f1a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:49:03 +0900 Subject: [PATCH 229/383] feat: implement readAll customer method at CustomerMVCController --- .../customer/controller/CustomerMVCController.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java index 8b82d47c90..8a3c2d4fe2 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java @@ -25,8 +25,16 @@ public String create(CreateCustomerRequest createCustomerRequest) { return "redirect:/customers/blacklist"; } + @GetMapping + public String readAll(Model model) { + model.addAttribute("list-title", "all"); + model.addAttribute("customers", customerService.readAll()); + return "views/customers"; + } + @GetMapping("/blacklist") public String readAllBlackCustomer(Model model) { + model.addAttribute("list-title", "blacklist"); model.addAttribute("customers", customerService.readAllBlackCustomer()); return "views/customers"; } From 067407cb6917fee40608df4eda0aa3132f87cfe4 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 14:49:13 +0900 Subject: [PATCH 230/383] feat: implement readAll customer method at CustomerController --- .../customer/controller/CustomerController.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 23d706a0cb..6a853d264a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -28,6 +28,12 @@ public void create(CreateCustomerRequest createCustomerRequest) { customerService.create(createCustomerRequest); } + @GetMapping + @ResponseBody + public List readAll() { + return customerService.readAll(); + } + @GetMapping("/blacklist") @ResponseBody public List readAllBlackCustomer() { From 8577178d55be1d1b5701ebaed13a9591e932718f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 15:05:10 +0900 Subject: [PATCH 231/383] feat: implement WalletController for console --- .../wallet/controller/WalletController.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java new file mode 100644 index 0000000000..b9fb4df28b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java @@ -0,0 +1,38 @@ +package com.programmers.vouchermanagement.wallet.controller; + +import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.wallet.domain.Ownership; +import com.programmers.vouchermanagement.wallet.service.WalletService; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; + +import java.util.List; +import java.util.UUID; + +@Profile("console") +@Controller +public class WalletController { + private final WalletService walletService; + + public WalletController(WalletService walletService) { + this.walletService = walletService; + } + + public void allocate(Ownership ownership) { + walletService.allocate(ownership); + } + + public CustomerDto readCustomerByVoucherId(UUID voucherId, Model model) { + return walletService.readCustomerByVoucherId(voucherId); + } + + public List readAllVoucherByCustomerId(UUID customerId, Model model) { + return walletService.readAllVoucherByCustomerId(customerId); + } + + public void deleteAllAllocation() { + walletService.deleteAllAllocation(); + } +} From 69b6a8583a9d72f13dea342bebe81f4fcf875f37 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 15:05:23 +0900 Subject: [PATCH 232/383] feat: implement wallets page --- src/main/webapp/WEB-INF/views/wallets.html | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/webapp/WEB-INF/views/wallets.html diff --git a/src/main/webapp/WEB-INF/views/wallets.html b/src/main/webapp/WEB-INF/views/wallets.html new file mode 100644 index 0000000000..85d31aad41 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/wallets.html @@ -0,0 +1,29 @@ + + + + + + + + Home + + +

wallets

+ + + + + + + + + + + + + +
voucher idcustomer id
+ + \ No newline at end of file From c5c06fb622740b44eb43ecb7c56c752df0ddda96 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 15:06:15 +0900 Subject: [PATCH 233/383] refactor: change return value of readCustomerByVoucherId method --- .../vouchermanagement/wallet/service/WalletService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index 322568a44b..db6c39ae8e 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.wallet.service; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.wallet.domain.Ownership; @@ -29,11 +30,12 @@ public void allocate(Ownership ownership) { walletRepository.save(ownership); } - public Customer readCustomerByVoucherId(UUID voucherId) { - return walletRepository.findCustomerByVoucherId(voucherId).orElseThrow(() -> { + public CustomerDto readCustomerByVoucherId(UUID voucherId) { + Customer customer = walletRepository.findCustomerByVoucherId(voucherId).orElseThrow(() -> { logger.error(NOT_FOUND_VOUCHER_ALLOCATION); return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); }); + return CustomerDto.from(customer); } public List readAllVoucherByCustomerId(UUID customerId) { From fbb7065036dac0aa18aecc238423bcf9ebb88e9b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 15:06:32 +0900 Subject: [PATCH 234/383] feat: implement WalletMVCController for mvc mode --- .../controller/WalletMVCController.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletMVCController.java diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletMVCController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletMVCController.java new file mode 100644 index 0000000000..9e54af075c --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletMVCController.java @@ -0,0 +1,49 @@ +package com.programmers.vouchermanagement.wallet.controller; + +import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.wallet.domain.Ownership; +import com.programmers.vouchermanagement.wallet.service.WalletService; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@Profile("mvc") +@RequestMapping("/wallets") +@Controller +public class WalletMVCController { + private final WalletService walletService; + + public WalletMVCController(WalletService walletService) { + this.walletService = walletService; + } + + @PostMapping + public void allocate(Ownership ownership) { + walletService.allocate(ownership); + } + + @GetMapping("/vouchers/{voucherId}") + public String readCustomerByVoucherId(@PathVariable("voucherId") UUID voucherId, Model model) { + CustomerDto customer = walletService.readCustomerByVoucherId(voucherId); + model.addAttribute("customers", List.of(customer)); + return "views/customers"; + } + + @GetMapping("/customers/{customerId}") + public String readAllVoucherByCustomerId(@PathVariable("customerId") UUID customerId, Model model) { + List vouchers = walletService.readAllVoucherByCustomerId(customerId); + model.addAttribute("vouchers", List.of(vouchers)); + return "views/vouchers"; + } + + @DeleteMapping + public String deleteAllAllocation() { + walletService.deleteAllAllocation(); + return "redirect:/wallets"; + } +} From 7977cfa13158d519448d195ec8aca658a168b8aa Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 21:43:32 +0900 Subject: [PATCH 235/383] feat: implement ownweship post form --- src/main/webapp/WEB-INF/views/wallets.html | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/webapp/WEB-INF/views/wallets.html b/src/main/webapp/WEB-INF/views/wallets.html index 85d31aad41..6acc476bef 100644 --- a/src/main/webapp/WEB-INF/views/wallets.html +++ b/src/main/webapp/WEB-INF/views/wallets.html @@ -11,6 +11,29 @@

wallets

+

Voucher Allocation

+
+
Customer
+
+ +
+
Voucher
+
+ +
+ +
+

Voucher Ownership

From 73af02f25c043abdd118f98b09ea63892884adf0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 21:43:42 +0900 Subject: [PATCH 236/383] feat: implement voucher post form --- src/main/webapp/WEB-INF/views/vouchers.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/webapp/WEB-INF/views/vouchers.html b/src/main/webapp/WEB-INF/views/vouchers.html index 52c072c6ed..f47b93924a 100644 --- a/src/main/webapp/WEB-INF/views/vouchers.html +++ b/src/main/webapp/WEB-INF/views/vouchers.html @@ -11,6 +11,21 @@

Vouchers

+

New Voucher

+
+
+ + +
+ + + +

Voucher List

From 2f7a835911e8d03889474bcd490a64e5fc70e561 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 2 Nov 2023 21:44:40 +0900 Subject: [PATCH 237/383] feat: implement customer post form --- src/main/webapp/WEB-INF/views/customers.html | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/WEB-INF/views/customers.html b/src/main/webapp/WEB-INF/views/customers.html index ea720e679f..b94e2eaf56 100644 --- a/src/main/webapp/WEB-INF/views/customers.html +++ b/src/main/webapp/WEB-INF/views/customers.html @@ -11,12 +11,25 @@

Customers

+

New Customer

+
+
+ + +
+
+ + +
+ + +

Customer List

- + From 1cd61064445d5d2eaf93c4986921c4e078b7943c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 10:45:59 +0900 Subject: [PATCH 238/383] enhance: implement all require at voucher list page --- src/main/webapp/WEB-INF/views/vouchers.html | 31 ++++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/main/webapp/WEB-INF/views/vouchers.html b/src/main/webapp/WEB-INF/views/vouchers.html index f47b93924a..84807a6916 100644 --- a/src/main/webapp/WEB-INF/views/vouchers.html +++ b/src/main/webapp/WEB-INF/views/vouchers.html @@ -11,34 +11,31 @@

Vouchers

-

New Voucher

-
-
- - -
- - -

Voucher List

-
ID NameIs Black?Bad Customer
- +
+ Create +
+
+ + - + +
ID Discount Value voucher Type
+ Detail + Update +
+ +
+
From 70618366ece2f79d7d0d0b93145702f7c7aebd72 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 10:46:21 +0900 Subject: [PATCH 239/383] feat: implement voucher detail page --- .../webapp/WEB-INF/views/voucher-detail.html | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/webapp/WEB-INF/views/voucher-detail.html diff --git a/src/main/webapp/WEB-INF/views/voucher-detail.html b/src/main/webapp/WEB-INF/views/voucher-detail.html new file mode 100644 index 0000000000..66966cec7d --- /dev/null +++ b/src/main/webapp/WEB-INF/views/voucher-detail.html @@ -0,0 +1,29 @@ + + + + + + + + Home + + +

Vouchers

+

Voucher Id

+
+ + +
+Ok +Update +
+ +
+ + \ No newline at end of file From 89dc5487d852a3959ffe5a28affbd98f0f862d6b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 10:46:27 +0900 Subject: [PATCH 240/383] feat: implement voucher register page --- .../webapp/WEB-INF/views/voucher-new.html | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/webapp/WEB-INF/views/voucher-new.html diff --git a/src/main/webapp/WEB-INF/views/voucher-new.html b/src/main/webapp/WEB-INF/views/voucher-new.html new file mode 100644 index 0000000000..e8a7e17ad8 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/voucher-new.html @@ -0,0 +1,27 @@ + + + + + + + + Home + + +

Vouchers

+

New Voucher

+
+
+ + +
+ +
+ + \ No newline at end of file From 0b1ff22d0e631f100cac1db7c528022ac6d6e06c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 10:46:36 +0900 Subject: [PATCH 241/383] feat: implement voucher update page --- .../webapp/WEB-INF/views/voucher-update.html | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/webapp/WEB-INF/views/voucher-update.html diff --git a/src/main/webapp/WEB-INF/views/voucher-update.html b/src/main/webapp/WEB-INF/views/voucher-update.html new file mode 100644 index 0000000000..01dd59e861 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/voucher-update.html @@ -0,0 +1,28 @@ + + + + + + + + Home + + +

Vouchers

+

New Voucher

+
+
+ + +
+ + Cancel +
+ + \ No newline at end of file From a98ca0aca611a514c659ec9c6182d572aa028265 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:00:45 +0900 Subject: [PATCH 242/383] enhance: apply new page and implement all requires at voucher feature --- .../controller/VoucherMVCController.java | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java index cb59f5d736..ce3778dea8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java @@ -1,6 +1,5 @@ package com.programmers.vouchermanagement.voucher.controller; -import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.voucher.service.VoucherService; @@ -22,12 +21,17 @@ public VoucherMVCController(VoucherService voucherService) { this.voucherService = voucherService; } - @PostMapping + @PostMapping("/new") public String create(CreateVoucherRequest createVoucherRequest) { voucherService.create(createVoucherRequest); return "redirect:/vouchers"; } + @GetMapping("/new") + public String ViewCreatePage(Model model) { + return "views/voucher-new"; + } + @GetMapping public String viewVouchersPage(Model model) { List vouchers = voucherService.readAll(); @@ -39,8 +43,8 @@ public String viewVouchersPage(Model model) { public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { try { VoucherDto voucher = voucherService.readById(voucherId); - model.addAttribute("vouchers", List.of(voucher)); - return "views/vouchers"; + model.addAttribute("voucher", voucher); + return "views/voucher-detail"; } catch (RuntimeException e) { return "views/404"; } @@ -58,9 +62,21 @@ public String deleteAll() { return "redirect:/vouchers"; } - @PutMapping - public String update(Voucher voucher) { - voucherService.update(voucher); + @PutMapping("/update/{voucherId}") + public String update(@PathVariable("voucherId") UUID voucherId, CreateVoucherRequest createVoucherRequest) { + voucherService.update(voucherId, createVoucherRequest); return "redirect:/vouchers"; } + //TODO: check id + + @GetMapping("/update/{voucherId}") + public String viewUpdatePage(@PathVariable("voucherId") UUID voucherId, Model model) { + try { + VoucherDto voucher = voucherService.readById(voucherId); + model.addAttribute("voucher", voucher); + return "views/voucher-update"; + } catch (RuntimeException e) { + return "views/404"; + } + } } From 3d8ba79d8f7e34d3340334498512d4a3b00d45a9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:01:09 +0900 Subject: [PATCH 243/383] refactor: change update voucher parameter --- .../vouchermanagement/voucher/service/VoucherService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 5e7c60cbbc..e15b0f6d4f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -54,7 +54,8 @@ public void deleteAll() { voucherRepository.deleteAll(); } - public void update(Voucher voucher) { + public void update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { + Voucher voucher = new Voucher(voucherId, createVoucherRequest.discountValue(), createVoucherRequest.voucherType()); voucherRepository.update(voucher); } From f631492dc5fd0fc43fed1584a36e49407bc5366d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:01:23 +0900 Subject: [PATCH 244/383] refactor: change update voucher parameter at VoucherController --- .../voucher/controller/VoucherController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 7d115a064c..c488c63e39 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,6 +1,5 @@ package com.programmers.vouchermanagement.voucher.controller; -import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.voucher.service.VoucherService; @@ -51,10 +50,10 @@ public void deleteAll() { voucherService.deleteAll(); } - @PutMapping + @PutMapping("/{voucherId}") @ResponseBody - public void update(Voucher voucher) { - voucherService.update(voucher); + public void update(@PathVariable("voucherId") UUID voucherId, CreateVoucherRequest createVoucherRequest) { + voucherService.update(voucherId, createVoucherRequest); } } From eae798e6a808ea21e43cbbcea11a0e8a18d37d6c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:01:58 +0900 Subject: [PATCH 245/383] chore: add hidden-method property --- src/main/resources/application.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7c417a9045..31042c6c8c 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -4,6 +4,10 @@ spring: username: root password: 20231028 + mvc: + hidden-method: + filter: + enabled: true file: resources: path: src/main/resources/ From 2ad9a64fe7df69162ce3068c36dbd69b11c7d696 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:11:02 +0900 Subject: [PATCH 246/383] refactor: move html file to templates directory --- .../views => resources/templates/customer}/customers.html | 2 +- .../views => resources/templates/voucher}/voucher-detail.html | 0 .../views => resources/templates/voucher}/voucher-new.html | 0 .../views => resources/templates/voucher}/voucher-update.html | 0 .../WEB-INF/views => resources/templates/voucher}/vouchers.html | 0 .../WEB-INF/views => resources/templates/wallet}/wallets.html | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename src/main/{webapp/WEB-INF/views => resources/templates/customer}/customers.html (97%) rename src/main/{webapp/WEB-INF/views => resources/templates/voucher}/voucher-detail.html (100%) rename src/main/{webapp/WEB-INF/views => resources/templates/voucher}/voucher-new.html (100%) rename src/main/{webapp/WEB-INF/views => resources/templates/voucher}/voucher-update.html (100%) rename src/main/{webapp/WEB-INF/views => resources/templates/voucher}/vouchers.html (100%) rename src/main/{webapp/WEB-INF/views => resources/templates/wallet}/wallets.html (100%) diff --git a/src/main/webapp/WEB-INF/views/customers.html b/src/main/resources/templates/customer/customers.html similarity index 97% rename from src/main/webapp/WEB-INF/views/customers.html rename to src/main/resources/templates/customer/customers.html index b94e2eaf56..640f49ebf6 100644 --- a/src/main/webapp/WEB-INF/views/customers.html +++ b/src/main/resources/templates/customer/customers.html @@ -18,7 +18,7 @@

New Customer

- +
diff --git a/src/main/webapp/WEB-INF/views/voucher-detail.html b/src/main/resources/templates/voucher/voucher-detail.html similarity index 100% rename from src/main/webapp/WEB-INF/views/voucher-detail.html rename to src/main/resources/templates/voucher/voucher-detail.html diff --git a/src/main/webapp/WEB-INF/views/voucher-new.html b/src/main/resources/templates/voucher/voucher-new.html similarity index 100% rename from src/main/webapp/WEB-INF/views/voucher-new.html rename to src/main/resources/templates/voucher/voucher-new.html diff --git a/src/main/webapp/WEB-INF/views/voucher-update.html b/src/main/resources/templates/voucher/voucher-update.html similarity index 100% rename from src/main/webapp/WEB-INF/views/voucher-update.html rename to src/main/resources/templates/voucher/voucher-update.html diff --git a/src/main/webapp/WEB-INF/views/vouchers.html b/src/main/resources/templates/voucher/vouchers.html similarity index 100% rename from src/main/webapp/WEB-INF/views/vouchers.html rename to src/main/resources/templates/voucher/vouchers.html diff --git a/src/main/webapp/WEB-INF/views/wallets.html b/src/main/resources/templates/wallet/wallets.html similarity index 100% rename from src/main/webapp/WEB-INF/views/wallets.html rename to src/main/resources/templates/wallet/wallets.html From d6148933ad37cde6b65c15e5232b3b665579bfed Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:11:20 +0900 Subject: [PATCH 247/383] refactor: apply html path --- .../voucher/controller/VoucherMVCController.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java index ce3778dea8..8830670e36 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java @@ -24,19 +24,19 @@ public VoucherMVCController(VoucherService voucherService) { @PostMapping("/new") public String create(CreateVoucherRequest createVoucherRequest) { voucherService.create(createVoucherRequest); - return "redirect:/vouchers"; + return "redirect:voucher/vouchers"; } @GetMapping("/new") public String ViewCreatePage(Model model) { - return "views/voucher-new"; + return "voucher/voucher-new"; } @GetMapping public String viewVouchersPage(Model model) { List vouchers = voucherService.readAll(); model.addAttribute("vouchers", vouchers); - return "views/vouchers"; + return "voucher/vouchers"; } @GetMapping("/{voucherId}") @@ -44,7 +44,7 @@ public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { try { VoucherDto voucher = voucherService.readById(voucherId); model.addAttribute("voucher", voucher); - return "views/voucher-detail"; + return "voucher/voucher-detail"; } catch (RuntimeException e) { return "views/404"; } @@ -53,19 +53,19 @@ public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { @DeleteMapping("/{voucherId}") public String delete(@PathVariable("voucherId") UUID voucherId) { voucherService.delete(voucherId); - return "redirect:/vouchers"; + return "redirect:voucher/vouchers"; } @DeleteMapping public String deleteAll() { voucherService.deleteAll(); - return "redirect:/vouchers"; + return "redirect:voucher/vouchers"; } @PutMapping("/update/{voucherId}") public String update(@PathVariable("voucherId") UUID voucherId, CreateVoucherRequest createVoucherRequest) { voucherService.update(voucherId, createVoucherRequest); - return "redirect:/vouchers"; + return "redirect:voucher/vouchers"; } //TODO: check id @@ -74,7 +74,7 @@ public String viewUpdatePage(@PathVariable("voucherId") UUID voucherId, Model mo try { VoucherDto voucher = voucherService.readById(voucherId); model.addAttribute("voucher", voucher); - return "views/voucher-update"; + return "voucher/voucher-update"; } catch (RuntimeException e) { return "views/404"; } From ac591e8130b0a63d7c7b78453de460d1bec48d75 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:11:51 +0900 Subject: [PATCH 248/383] refactor: remove thymeleaf path setting --- src/main/resources/application-mvc.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/resources/application-mvc.yaml b/src/main/resources/application-mvc.yaml index c5cdcd8b4c..e69de29bb2 100644 --- a/src/main/resources/application-mvc.yaml +++ b/src/main/resources/application-mvc.yaml @@ -1,3 +0,0 @@ -spring: - thymeleaf: - prefix: "/WEB-INF/" \ No newline at end of file From e4643794c5a1a46d6fade8e7bdb259603f4f558e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:13:31 +0900 Subject: [PATCH 249/383] fix: fix redirect path at VoucherMVCController --- .../voucher/controller/VoucherMVCController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java index 8830670e36..cfa29dadf5 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java @@ -24,7 +24,7 @@ public VoucherMVCController(VoucherService voucherService) { @PostMapping("/new") public String create(CreateVoucherRequest createVoucherRequest) { voucherService.create(createVoucherRequest); - return "redirect:voucher/vouchers"; + return "redirect:/vouchers"; } @GetMapping("/new") @@ -53,19 +53,19 @@ public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { @DeleteMapping("/{voucherId}") public String delete(@PathVariable("voucherId") UUID voucherId) { voucherService.delete(voucherId); - return "redirect:voucher/vouchers"; + return "redirect:/vouchers"; } @DeleteMapping public String deleteAll() { voucherService.deleteAll(); - return "redirect:voucher/vouchers"; + return "redirect:/vouchers"; } @PutMapping("/update/{voucherId}") public String update(@PathVariable("voucherId") UUID voucherId, CreateVoucherRequest createVoucherRequest) { voucherService.update(voucherId, createVoucherRequest); - return "redirect:voucher/vouchers"; + return "redirect:/vouchers"; } //TODO: check id From 7ef6477054ea6ed333822459a7fb5223abac01e7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 11:29:10 +0900 Subject: [PATCH 250/383] refactor: change blacklist to blocklist --- .../vouchermanagement/consoleapp/menu/MenuHandler.java | 2 +- .../customer/controller/CustomerController.java | 6 +++--- .../customer/controller/CustomerMVCController.java | 10 +++++----- .../customer/repository/CustomerFileRepository.java | 2 +- .../repository/CustomerInMemoryRepository.java | 2 +- .../customer/repository/CustomerJDBCRepository.java | 2 +- .../customer/repository/CustomerRepository.java | 2 +- .../customer/service/CustomerService.java | 4 ++-- .../repository/CustomerJDBCRepositoryTest.java | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 76fc059518..54b79dad73 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -74,7 +74,7 @@ private void executeMenu(Menu menu) { } //TODO: customerDTO case BLACKLIST -> { - List blackCustomers = customerController.readAllBlackCustomer(); + List blackCustomers = customerController.readBlocklist(); consoleManager.printReadBlacklist(blackCustomers); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 6a853d264a..8b242b4fd8 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -34,9 +34,9 @@ public List readAll() { return customerService.readAll(); } - @GetMapping("/blacklist") + @GetMapping("/blocklist") @ResponseBody - public List readAllBlackCustomer() { - return customerService.readAllBlackCustomer(); + public List readBlocklist() { + return customerService.readBlocklist(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java index 8a3c2d4fe2..5015f21942 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java @@ -32,10 +32,10 @@ public String readAll(Model model) { return "views/customers"; } - @GetMapping("/blacklist") - public String readAllBlackCustomer(Model model) { - model.addAttribute("list-title", "blacklist"); - model.addAttribute("customers", customerService.readAllBlackCustomer()); - return "views/customers"; + @GetMapping("/blocklist") + public String readBlocklist(Model model) { + model.addAttribute("list-title", "blocklist"); + model.addAttribute("customers", customerService.readBlocklist()); + return "customer/customers"; } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 39168499ac..8cebea326d 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -30,7 +30,7 @@ public List findAll() { } @Override - public List findAllBlackCustomer() { + public List findBlocklist() { return customerFileManager.customers.values().stream().filter(Customer::isBlack).toList(); } } \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java index 31e5c4f0f1..86cf1be7a7 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java @@ -32,7 +32,7 @@ public List findAll() { } @Override - public List findAllBlackCustomer() { + public List findBlocklist() { return customers.values() .stream() .filter(Customer::isBlack) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 876eb7f0e1..38c0cd69ed 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -27,7 +27,7 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMap } @Override - public List findAllBlackCustomer() { + public List findBlocklist() { return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java index 651486907f..1a23608b63 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -9,5 +9,5 @@ public interface CustomerRepository { List findAll(); - List findAllBlackCustomer(); + List findBlocklist(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index ec6bb66329..11da507a34 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -31,8 +31,8 @@ public List readAll() { return customers.stream().map(CustomerDto::from).toList(); } - public List readAllBlackCustomer() { - List blacklist = customerRepository.findAllBlackCustomer(); + public List readBlocklist() { + List blacklist = customerRepository.findBlocklist(); if (blacklist.isEmpty()) { return Collections.emptyList(); } diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 63128151d7..8cba50929a 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -40,7 +40,7 @@ void findAllBlackCustomerSucceed() { customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객1", false)); customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객2", true)); customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객3", false)); - List customers = customerJDBCRepository.findAllBlackCustomer(); + List customers = customerJDBCRepository.findBlocklist(); assertThat(customers.isEmpty()).isFalse(); assertThat(customers.stream().filter(customer -> !customer.isBlack()).toList()).isEmpty(); } From 9405ccdcf82cc3e494c414941e98cb42ee4c7fdd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 13:22:13 +0900 Subject: [PATCH 251/383] Revert "refactor: change blacklist to blocklist" This reverts commit 7ef6477054ea6ed333822459a7fb5223abac01e7. --- .../vouchermanagement/consoleapp/menu/MenuHandler.java | 2 +- .../customer/controller/CustomerController.java | 6 +++--- .../customer/controller/CustomerMVCController.java | 10 +++++----- .../customer/repository/CustomerFileRepository.java | 2 +- .../repository/CustomerInMemoryRepository.java | 2 +- .../customer/repository/CustomerJDBCRepository.java | 2 +- .../customer/repository/CustomerRepository.java | 2 +- .../customer/service/CustomerService.java | 4 ++-- .../repository/CustomerJDBCRepositoryTest.java | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 54b79dad73..76fc059518 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -74,7 +74,7 @@ private void executeMenu(Menu menu) { } //TODO: customerDTO case BLACKLIST -> { - List blackCustomers = customerController.readBlocklist(); + List blackCustomers = customerController.readAllBlackCustomer(); consoleManager.printReadBlacklist(blackCustomers); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 8b242b4fd8..6a853d264a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -34,9 +34,9 @@ public List readAll() { return customerService.readAll(); } - @GetMapping("/blocklist") + @GetMapping("/blacklist") @ResponseBody - public List readBlocklist() { - return customerService.readBlocklist(); + public List readAllBlackCustomer() { + return customerService.readAllBlackCustomer(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java index 5015f21942..8a3c2d4fe2 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java @@ -32,10 +32,10 @@ public String readAll(Model model) { return "views/customers"; } - @GetMapping("/blocklist") - public String readBlocklist(Model model) { - model.addAttribute("list-title", "blocklist"); - model.addAttribute("customers", customerService.readBlocklist()); - return "customer/customers"; + @GetMapping("/blacklist") + public String readAllBlackCustomer(Model model) { + model.addAttribute("list-title", "blacklist"); + model.addAttribute("customers", customerService.readAllBlackCustomer()); + return "views/customers"; } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 8cebea326d..39168499ac 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -30,7 +30,7 @@ public List findAll() { } @Override - public List findBlocklist() { + public List findAllBlackCustomer() { return customerFileManager.customers.values().stream().filter(Customer::isBlack).toList(); } } \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java index 86cf1be7a7..31e5c4f0f1 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java @@ -32,7 +32,7 @@ public List findAll() { } @Override - public List findBlocklist() { + public List findAllBlackCustomer() { return customers.values() .stream() .filter(Customer::isBlack) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 38c0cd69ed..876eb7f0e1 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -27,7 +27,7 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMap } @Override - public List findBlocklist() { + public List findAllBlackCustomer() { return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java index 1a23608b63..651486907f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -9,5 +9,5 @@ public interface CustomerRepository { List findAll(); - List findBlocklist(); + List findAllBlackCustomer(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 11da507a34..ec6bb66329 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -31,8 +31,8 @@ public List readAll() { return customers.stream().map(CustomerDto::from).toList(); } - public List readBlocklist() { - List blacklist = customerRepository.findBlocklist(); + public List readAllBlackCustomer() { + List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { return Collections.emptyList(); } diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 8cba50929a..63128151d7 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -40,7 +40,7 @@ void findAllBlackCustomerSucceed() { customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객1", false)); customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객2", true)); customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객3", false)); - List customers = customerJDBCRepository.findBlocklist(); + List customers = customerJDBCRepository.findAllBlackCustomer(); assertThat(customers.isEmpty()).isFalse(); assertThat(customers.stream().filter(customer -> !customer.isBlack()).toList()).isEmpty(); } From d7b3e11f178a9a7db664194ba54a568aa22cd084 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 15:39:58 +0900 Subject: [PATCH 252/383] feat: implement customer register page --- .../templates/customer/customer-new.html | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/main/resources/templates/customer/customer-new.html diff --git a/src/main/resources/templates/customer/customer-new.html b/src/main/resources/templates/customer/customer-new.html new file mode 100644 index 0000000000..f70f76ad7e --- /dev/null +++ b/src/main/resources/templates/customer/customer-new.html @@ -0,0 +1,35 @@ + + + + + + + + + Home + + +

Customers

+

New Customer

+
+
+ + +
+
+ + +
+ + +
+ + \ No newline at end of file From af91853e52d709eb8f7515f8f1eadba9d925c9f0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 16:28:31 +0900 Subject: [PATCH 253/383] enhance: separate customer register form from customers and add blacklist button --- .../templates/customer/customers.html | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/resources/templates/customer/customers.html b/src/main/resources/templates/customer/customers.html index 640f49ebf6..29360b00ad 100644 --- a/src/main/resources/templates/customer/customers.html +++ b/src/main/resources/templates/customer/customers.html @@ -11,19 +11,14 @@

Customers

-

New Customer

-
-
- - -
-
- - -
- -
-

Customer List

+ +

Customer List

+

Customer Blacklist

From 778dab974a99868a726f37abd86efe31e5d63eed Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 16:29:21 +0900 Subject: [PATCH 254/383] refactor: add bad customer check script --- .../resources/templates/customer/customer-new.html | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/resources/templates/customer/customer-new.html b/src/main/resources/templates/customer/customer-new.html index f70f76ad7e..d1819050e0 100644 --- a/src/main/resources/templates/customer/customer-new.html +++ b/src/main/resources/templates/customer/customer-new.html @@ -7,13 +7,6 @@ - Home @@ -28,8 +21,13 @@

New Customer

- + + \ No newline at end of file From 62c9e9c0e841d6d721a13cbae996f6b68dd580b2 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 16:30:03 +0900 Subject: [PATCH 255/383] refactor: add mode before return view and change mapping url at CustomerMVCController --- .../controller/CustomerMVCController.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java index 8a3c2d4fe2..6915e0a039 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java @@ -19,23 +19,28 @@ public CustomerMVCController(CustomerService customerService) { this.customerService = customerService; } - @PostMapping + @PostMapping("/new") public String create(CreateCustomerRequest createCustomerRequest) { customerService.create(createCustomerRequest); - return "redirect:/customers/blacklist"; + return "redirect:/customers"; + } + + @GetMapping("/new") + public String viewCreatePage() { + return "customer/customer-new"; } @GetMapping public String readAll(Model model) { - model.addAttribute("list-title", "all"); + model.addAttribute("mode", "all"); model.addAttribute("customers", customerService.readAll()); - return "views/customers"; + return "customer/customers"; } @GetMapping("/blacklist") public String readAllBlackCustomer(Model model) { - model.addAttribute("list-title", "blacklist"); + model.addAttribute("mode", "blacklist"); model.addAttribute("customers", customerService.readAllBlackCustomer()); - return "views/customers"; + return "customer/customers"; } } From 673e5c8bf49db38b3f601ef847bd77f35998a5ce Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 3 Nov 2023 17:37:22 +0900 Subject: [PATCH 256/383] fix: fix delete all query at voucher --- .../vouchermanagement/voucher/repository/VoucherQuery.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java index 584315a641..b2a09aaff7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java @@ -5,6 +5,6 @@ public class VoucherQuery { public static final String FIND_BY_ID = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; public static final String FIND_ALL = "SELECT * FROM test.vouchers"; public static final String DELETE_VOUCHER = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; - public static final String DELETE_ALL = "TRUNCATE TABLE test.vouchers"; + public static final String DELETE_ALL = "DELETE FROM test.vouchers"; public static final String UPDATE_VOUCHER = "UPDATE test.vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; } From ffb35f4ee469926e879f2bd64025d7212dcd92ec Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 18:23:01 +0900 Subject: [PATCH 257/383] refactor: add "file" profile at VoucherFileManager --- .../voucher/repository/VoucherFileManager.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java index d242bdfa42..55513cd088 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java @@ -6,19 +6,23 @@ import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.UncheckedIOException; +import java.time.LocalDateTime; import java.util.*; import static com.programmers.vouchermanagement.constant.Message.*; @Component +@Profile("file") public class VoucherFileManager { static final String VOUCHER_TYPE_KEY = "voucher_type"; + static final String CREATED_AT_KEY = "created_at"; private static final Logger logger = LoggerFactory.getLogger(VoucherFileManager.class); private static final String VOUCHER_ID_KEY = "voucher_id"; private static final String DISCOUNT_VALUE_KEY = "discount_value"; @@ -59,7 +63,9 @@ private Voucher objectToVoucher(Map voucherObject) { logger.error(INVALID_VOUCHER_TYPE); return new NoSuchElementException(INVALID_VOUCHER_TYPE); }); - return new Voucher(voucherId, discountValue, voucherType); + //TODO: check save format + LocalDateTime createdAt = (LocalDateTime) voucherObject.get(CREATED_AT_KEY); + return new Voucher(voucherId, discountValue, voucherType, createdAt); } public void saveFile() { @@ -84,6 +90,7 @@ private HashMap voucherToObject(Voucher voucher) { voucherObject.put(VOUCHER_ID_KEY, voucher.voucherId().toString()); voucherObject.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); voucherObject.put(VOUCHER_TYPE_KEY, voucher.voucherType().name()); + voucherObject.put(CREATED_AT_KEY, voucher.createdAt().toString()); return voucherObject; } } From a3a126364ce78f2c429957d91f72e547063245e7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 18:23:41 +0900 Subject: [PATCH 258/383] refactor: add voucher create time field at Voucher --- .../programmers/vouchermanagement/voucher/domain/Voucher.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index bc7adfcaee..5bf734ee6c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.voucher.domain; +import java.time.LocalDateTime; import java.util.UUID; -public record Voucher(UUID voucherId, long discountValue, VoucherType voucherType) { +public record Voucher(UUID voucherId, long discountValue, VoucherType voucherType, LocalDateTime createdAt) { } From dafa627c02fb19404ec6e9c86e8fd9dc73b151c2 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 18:24:07 +0900 Subject: [PATCH 259/383] refactor: add voucher create time field at VoucherDto --- .../vouchermanagement/voucher/dto/VoucherDto.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java index a547773bb7..ad213fd280 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java @@ -3,11 +3,13 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import java.time.LocalDateTime; import java.util.UUID; -public record VoucherDto(UUID id, long discountValue, String voucherTypeName, boolean isPercent) { +public record VoucherDto(UUID id, long discountValue, String voucherTypeName, boolean isPercent, + LocalDateTime createdAt) { public static VoucherDto from(Voucher voucher) { VoucherType voucherType = voucher.voucherType(); - return new VoucherDto(voucher.voucherId(), voucher.discountValue(), voucherType.displayTypeName(), voucherType.isPercent()); + return new VoucherDto(voucher.voucherId(), voucher.discountValue(), voucherType.displayTypeName(), voucherType.isPercent(), voucher.createdAt()); } } From 0fde8861a3d1e3612a48ec3d40a9527d552241fb Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 18:24:28 +0900 Subject: [PATCH 260/383] refactor: apply voucher create time at DomainMapper --- .../programmers/vouchermanagement/util/DomainMapper.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index 5d681bf728..b2c3b15db0 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -8,12 +8,15 @@ import org.springframework.stereotype.Component; import java.nio.ByteBuffer; +import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; import java.util.UUID; @Component public class DomainMapper { + //TODO: split public static final String ID_KEY = "id"; public static final String VOUCHER_ID_KEY = "voucher_id"; public static final String CUSTOMER_ID_KEY = "customer_id"; @@ -21,13 +24,15 @@ public class DomainMapper { public static final String NAME_KEY = "name"; public static final String DISCOUNT_VALUE_KEY = "discount_value"; public static final String TYPE_KEY = "type"; + public static final String CREATED_AT_KEY = "created_at"; public final RowMapper voucherRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes(ID_KEY)); long discountValue = resultSet.getLong(DISCOUNT_VALUE_KEY); String voucherTypeStr = resultSet.getString(TYPE_KEY); + LocalDateTime createdAt = resultSet.getTimestamp(CREATED_AT_KEY).toLocalDateTime(); - return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr)); + return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr), createdAt); }; public final RowMapper customerRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes(ID_KEY)); @@ -68,6 +73,7 @@ public Map voucherToParamMap(Voucher voucher) { paramMap.put(ID_KEY, voucher.voucherId().toString().getBytes()); paramMap.put(TYPE_KEY, voucher.voucherType().name()); paramMap.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); + paramMap.put(CREATED_AT_KEY, Timestamp.valueOf(voucher.createdAt())); return paramMap; } } From 9cb477f1718fb7d0e0aba7cd7ae52282dd36e527 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 18:24:41 +0900 Subject: [PATCH 261/383] refactor: apply voucher create time at VoucherService --- .../vouchermanagement/voucher/service/VoucherService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index e15b0f6d4f..bd34d35e0d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -6,6 +6,7 @@ import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; @@ -22,7 +23,8 @@ public VoucherService(VoucherRepository voucherRepository) { } public VoucherDto create(CreateVoucherRequest createVoucherRequest) { - Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType()); + //TODO: now? DB vs Application + Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType(), LocalDateTime.now()); voucherRepository.save(voucher); return VoucherDto.from(voucher); } @@ -55,7 +57,9 @@ public void deleteAll() { } public void update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { - Voucher voucher = new Voucher(voucherId, createVoucherRequest.discountValue(), createVoucherRequest.voucherType()); + // TODO: modify code format + VoucherDto voucherDto = readById(voucherId); + Voucher voucher = new Voucher(voucherId, createVoucherRequest.discountValue(), createVoucherRequest.voucherType(), voucherDto.createdAt()); voucherRepository.update(voucher); } From 829a017c2d166b6fe948b077c7adb60958abf234 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:44:43 +0900 Subject: [PATCH 262/383] feat: implement findAllByCreatedAt at VoucherRepository --- .../voucher/repository/VoucherRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index 073228c95f..eab22793c9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -2,6 +2,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -13,6 +14,8 @@ public interface VoucherRepository { Optional findById(UUID id); + List findAllByCreatedAt(LocalDateTime from, LocalDateTime to); + void delete(UUID id); void deleteAll(); From 74a6a6e39718ed2944653a9473b09b6aaead64de Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:44:55 +0900 Subject: [PATCH 263/383] feat: implement findAllByCreatedAt at VoucherJDBCRepository --- .../voucher/repository/VoucherJDBCRepository.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index c4d4e7b0e9..04c5081fdd 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -4,20 +4,18 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.time.LocalDateTime; +import java.util.*; import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.constant.Message.*; import static com.programmers.vouchermanagement.voucher.repository.VoucherQuery.*; + @Profile("jdbc") @Repository public class VoucherJDBCRepository implements VoucherRepository { @@ -54,6 +52,12 @@ public Optional findById(UUID id) { return Optional.empty(); } } + @Override + public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { + return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, + Map.of(DomainMapper.FROM_KEY, from.toString(), DomainMapper.TO_KEY, to.toString()), + domainMapper.voucherRowMapper); + } @Override public void delete(UUID id) { From 3d5536e1095b687a7edded821f9ca3291365d662 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:45:02 +0900 Subject: [PATCH 264/383] feat: implement findAllByCreatedAt at VoucherInMemoryRepository --- .../voucher/repository/VoucherInMemoryRepository.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index 04d02239b2..d259df0704 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -4,6 +4,7 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; import java.util.*; import static com.programmers.vouchermanagement.constant.Message.NOT_DELETED; @@ -33,6 +34,14 @@ public Optional findById(UUID id) { return Optional.ofNullable(vouchers.get(id)); } + @Override + public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { + return vouchers.values().stream().filter(voucher -> { + LocalDateTime createdAt = voucher.createdAt(); + return createdAt.isAfter(from) && createdAt.isBefore(to); + }).toList(); + } + @Override public void delete(UUID id) { Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); From cf03b744b2a815de5224607d12879531fdd20e46 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:45:10 +0900 Subject: [PATCH 265/383] feat: implement findAllByCreatedAt at VoucherFileRepository --- .../voucher/repository/VoucherFileRepository.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 2f3004e65e..0ad570fc43 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -6,6 +6,7 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -40,6 +41,14 @@ public Optional findById(UUID id) { return Optional.ofNullable(voucherFileManager.vouchers.get(id)); } + @Override + public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { + return voucherFileManager.vouchers.values().stream().filter(voucher -> { + LocalDateTime createdAt = voucher.createdAt(); + return createdAt.isAfter(from) && createdAt.isBefore(to); + }).toList(); + } + @Override public void delete(UUID id) { Optional.ofNullable(voucherFileManager.vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); From 44fa438f784dd8ab0637f457ec6dc7075bb882c6 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:45:45 +0900 Subject: [PATCH 266/383] feat: implement readAllByCreatedAt at VoucherService --- .../voucher/service/VoucherService.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index bd34d35e0d..5f95ecb981 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -41,6 +41,18 @@ public List readAll() { .toList(); } + public List readAllByCreatedAt(LocalDateTime from, LocalDateTime to) { + List vouchers = voucherRepository.findAllByCreatedAt(from, to); + + if (vouchers.isEmpty()) { + return Collections.emptyList(); + } + + return vouchers.stream() + .map(VoucherDto::from) + .toList(); + } + public VoucherDto readById(UUID voucherId) { Voucher voucher = voucherRepository .findById(voucherId) From 0b527129eee94c1b37daa12b0c257df655299524 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:46:54 +0900 Subject: [PATCH 267/383] feat: implement readAllByCreatedAt at VoucherController --- .../voucher/controller/VoucherController.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index c488c63e39..1a12450098 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -7,6 +7,9 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; import java.util.UUID; @@ -56,4 +59,11 @@ public void update(@PathVariable("voucherId") UUID voucherId, CreateVoucherReque voucherService.update(voucherId, createVoucherRequest); } + @GetMapping("/datetime") + @ResponseBody + public List readAllByCreatedAt(@RequestParam(name = "from") LocalDate from, @RequestParam(name = "to") LocalDate to) { + LocalDateTime fromDateTime = LocalDateTime.of(from, LocalTime.of(0, 0, 0)); + LocalDateTime toDateTime = LocalDateTime.of(to, LocalTime.of(23, 59, 59)); + return voucherService.readAllByCreatedAt(fromDateTime, toDateTime); + } } From 6b95f0b5ae48d90084cae2159688bec3129234b7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:47:12 +0900 Subject: [PATCH 268/383] feat: implement FIND_ALL_BY_CREATED_AT query --- .../vouchermanagement/voucher/repository/VoucherQuery.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java index b2a09aaff7..6987c87721 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java @@ -4,6 +4,7 @@ public class VoucherQuery { public static final String INSERT = "INSERT INTO test.vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discount_value)"; public static final String FIND_BY_ID = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; public static final String FIND_ALL = "SELECT * FROM test.vouchers"; + public static final String FIND_ALL_BY_CREATED_AT = "SELECT * FROM test.vouchers WHERE created_at BETWEEN DATE(:from) AND DATE(:to)"; public static final String DELETE_VOUCHER = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; public static final String DELETE_ALL = "DELETE FROM test.vouchers"; public static final String UPDATE_VOUCHER = "UPDATE test.vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; From a75a95e2ca23b07bd50ab2121120bfed32fa85c0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:47:44 +0900 Subject: [PATCH 269/383] feat: implement FROM_KEY, TO_KEY at DomainMapper --- .../com/programmers/vouchermanagement/util/DomainMapper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index b2c3b15db0..1976daf641 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -25,6 +25,8 @@ public class DomainMapper { public static final String DISCOUNT_VALUE_KEY = "discount_value"; public static final String TYPE_KEY = "type"; public static final String CREATED_AT_KEY = "created_at"; + public static final String FROM_KEY = "from"; + public static final String TO_KEY = "to"; public final RowMapper voucherRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes(ID_KEY)); From 15afade252aec0bf1e98247f9542915e75dd75fa Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 19:56:59 +0900 Subject: [PATCH 270/383] refactor: change url name of readAllByCreatedAt method --- .../vouchermanagement/voucher/controller/VoucherController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 1a12450098..4d19e872b7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -59,7 +59,7 @@ public void update(@PathVariable("voucherId") UUID voucherId, CreateVoucherReque voucherService.update(voucherId, createVoucherRequest); } - @GetMapping("/datetime") + @GetMapping("/created-at") @ResponseBody public List readAllByCreatedAt(@RequestParam(name = "from") LocalDate from, @RequestParam(name = "to") LocalDate to) { LocalDateTime fromDateTime = LocalDateTime.of(from, LocalTime.of(0, 0, 0)); From 54cb574d5cefb4bcb9dc212c47809294d3ae2da9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:31:30 +0900 Subject: [PATCH 271/383] feat: FIND_ALL_BY_TYPE query at VoucherQuery --- .../vouchermanagement/voucher/repository/VoucherQuery.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java index 6987c87721..6a4ed06dc5 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java @@ -5,6 +5,7 @@ public class VoucherQuery { public static final String FIND_BY_ID = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; public static final String FIND_ALL = "SELECT * FROM test.vouchers"; public static final String FIND_ALL_BY_CREATED_AT = "SELECT * FROM test.vouchers WHERE created_at BETWEEN DATE(:from) AND DATE(:to)"; + public static final String FIND_ALL_BY_TYPE = "SELECT * FROM test.vouchers WHERE type = :type"; public static final String DELETE_VOUCHER = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; public static final String DELETE_ALL = "DELETE FROM test.vouchers"; public static final String UPDATE_VOUCHER = "UPDATE test.vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; From 0b707b0375bb9e5417168518da08652db5853465 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:31:55 +0900 Subject: [PATCH 272/383] feat: implement findAllByType at VoucherRepository interface --- .../voucher/repository/VoucherRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index eab22793c9..286b5b3d4c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import java.time.LocalDateTime; import java.util.List; @@ -21,4 +22,6 @@ public interface VoucherRepository { void deleteAll(); void update(Voucher voucher); + + List findAllByType(VoucherType voucherType); } From 4849019cdabd8abf619a58928e5a959c02cc1491 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:32:11 +0900 Subject: [PATCH 273/383] feat: implement findAllByType at VoucherJDBCRepository --- .../voucher/repository/VoucherJDBCRepository.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 04c5081fdd..86af70728f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -2,6 +2,7 @@ import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -52,6 +53,7 @@ public Optional findById(UUID id) { return Optional.empty(); } } + @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, @@ -79,4 +81,11 @@ public void update(Voucher voucher) { throw new RuntimeException(NOT_UPDATED); } } + + @Override + public List findAllByType(VoucherType type) { + return jdbcTemplate.query(FIND_ALL_BY_TYPE, + Map.of(DomainMapper.TYPE_KEY, type.name()), + domainMapper.voucherRowMapper); + } } From b5ea953f4bc4503840d29078b586246f594a36c8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:32:17 +0900 Subject: [PATCH 274/383] feat: implement findAllByType at VoucherInMemoryRepository --- .../voucher/repository/VoucherInMemoryRepository.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index d259df0704..9499a339fd 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; @@ -58,4 +59,9 @@ public void update(Voucher voucher) { Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); vouchers.put(voucher.voucherId(), voucher); } + + @Override + public List findAllByType(VoucherType voucherType) { + return vouchers.values().stream().filter(voucher -> voucher.voucherType().equals(voucherType)).toList(); + } } From 9160dfc70bede5f76e850068a395923cf8da0ac4 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:32:26 +0900 Subject: [PATCH 275/383] feat: implement findAllByType at VoucherFileRepository --- .../voucher/repository/VoucherFileRepository.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 0ad570fc43..15a0d3f268 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -57,8 +58,7 @@ public void delete(UUID id) { @Override public void deleteAll() { - if (!voucherFileManager.vouchers.isEmpty()) - voucherFileManager.vouchers.clear(); + if (!voucherFileManager.vouchers.isEmpty()) voucherFileManager.vouchers.clear(); voucherFileManager.saveFile(); } @@ -68,4 +68,9 @@ public void update(Voucher voucher) { voucherFileManager.vouchers.put(voucher.voucherId(), voucher); voucherFileManager.saveFile(); } + + @Override + public List findAllByType(VoucherType voucherType) { + return voucherFileManager.vouchers.values().stream().filter(voucher -> voucher.voucherType().equals(voucherType)).toList(); + } } From 2517aacc06fd7116de2e958ae25cac780f320e24 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:32:40 +0900 Subject: [PATCH 276/383] feat: implement readAllByType at VoucherService --- .../vouchermanagement/voucher/service/VoucherService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 5f95ecb981..a94d5ad0d1 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.voucher.service; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; @@ -75,4 +76,7 @@ public void update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { voucherRepository.update(voucher); } + public List readAllByType(VoucherType type) { + return voucherRepository.findAllByType(type).stream().map(VoucherDto::from).toList(); + } } From 1f40ebdebce52ef92735acbaa7c6fadd03c33297 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:32:59 +0900 Subject: [PATCH 277/383] feat: implement readAllByType at VoucherController --- .../voucher/controller/VoucherController.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 4d19e872b7..2d434bc13f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher.controller; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import com.programmers.vouchermanagement.voucher.service.VoucherService; @@ -66,4 +67,10 @@ public List readAllByCreatedAt(@RequestParam(name = "from") LocalDat LocalDateTime toDateTime = LocalDateTime.of(to, LocalTime.of(23, 59, 59)); return voucherService.readAllByCreatedAt(fromDateTime, toDateTime); } + + @GetMapping("type/{type}") + @ResponseBody + public List readAllByType(@PathVariable("type") VoucherType type) { + return voucherService.readAllByType(type); + } } From 3072a7f1334f5361bef93f2f4c0faa8e5c05cf5a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sat, 4 Nov 2023 20:33:35 +0900 Subject: [PATCH 278/383] refactor: apply @RequestBody for api version --- .../voucher/controller/VoucherController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 2d434bc13f..95ab2f92a7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -26,7 +26,7 @@ public VoucherController(VoucherService voucherService) { @PostMapping @ResponseBody - public VoucherDto create(CreateVoucherRequest createVoucherRequest) { + public VoucherDto create(@RequestBody CreateVoucherRequest createVoucherRequest) { return voucherService.create(createVoucherRequest); } @@ -56,7 +56,7 @@ public void deleteAll() { @PutMapping("/{voucherId}") @ResponseBody - public void update(@PathVariable("voucherId") UUID voucherId, CreateVoucherRequest createVoucherRequest) { + public void update(@PathVariable("voucherId") UUID voucherId, @RequestBody CreateVoucherRequest createVoucherRequest) { voucherService.update(voucherId, createVoucherRequest); } From 3e644ae69ebab3e414a2a207598c1de93d1d194c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 02:16:42 +0900 Subject: [PATCH 279/383] chore: add dependencies for (un)marshalling xml at rest api --- build.gradle | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index c1a6b6b5c0..bb64bc5e5f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,7 @@ -/* - * This file was generated by the Gradle 'init' task. - */ - plugins { id 'java-library' id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' } apply plugin: 'io.spring.dependency-management' @@ -14,15 +11,17 @@ repositories { } dependencies { - api 'org.springframework.boot:spring-boot-starter:3.1.4' - api 'com.fasterxml.jackson.core:jackson-databind:2.15.2' - api 'org.beryx:text-io:3.4.1' - implementation 'org.springframework.boot:spring-boot-starter-web:3.1.5' - implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.1.5' - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.5' - implementation 'org.springframework.boot:spring-boot-starter-aop:3.1.5' - runtimeOnly(implementation 'mysql:mysql-connector-java:8.0.33') - testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.4' + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-aop' + implementation 'com.fasterxml.jackson.core:jackson-databind' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml' + implementation 'org.codehaus.woodstox:woodstox-core-asl:4.4.1' + runtimeOnly 'mysql:mysql-connector-java:8.0.33' + implementation 'org.beryx:text-io:3.4.1' + testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { @@ -40,4 +39,4 @@ tasks.withType(JavaCompile) { tasks.withType(Javadoc) { options.encoding = 'UTF-8' -} +} \ No newline at end of file From 309516c24b9ccc9da08588442987c4c97b5d6008 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 02:17:17 +0900 Subject: [PATCH 280/383] feat: configure MessageConverter of json & xml --- .../configuration/MvcConfig.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java index ed40b2da77..bce7c11dd0 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java @@ -1,9 +1,17 @@ package com.programmers.vouchermanagement.configuration; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.text.SimpleDateFormat; +import java.util.List; + @Configuration public class MvcConfig implements WebMvcConfigurer { @Override @@ -11,4 +19,14 @@ public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/*") .allowedOrigins("*"); } -} + + @Override + public void configureMessageConverters(List> converters) { + Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() + .indentOutput(true) + .dateFormat(new SimpleDateFormat("yyyy-MM-dd")) + .modulesToInstall(new ParameterNamesModule()); + converters.add(new MappingJackson2HttpMessageConverter(builder.build())); + converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); + } +} \ No newline at end of file From a7699036aa73b4e153233457b8ea0d21d674ed5f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 02:19:10 +0900 Subject: [PATCH 281/383] fix: return VoucherDto at readById --- .../voucher/controller/VoucherController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 95ab2f92a7..0e1a5c36b9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -38,8 +38,8 @@ public List readAll() { @GetMapping("/{voucherId}") @ResponseBody - public void readById(@PathVariable("voucherId") UUID voucherId) { - voucherService.readById(voucherId); + public VoucherDto readById(@PathVariable("voucherId") UUID voucherId) { + return voucherService.readById(voucherId); } @DeleteMapping("/{voucherId}") From 55f7e1721aa58f78ae6eeed1d9ee9c36a5f80366 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 02:19:28 +0900 Subject: [PATCH 282/383] refactor: return VoucherDto at update --- .../voucher/controller/VoucherController.java | 4 ++-- .../vouchermanagement/voucher/service/VoucherService.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 0e1a5c36b9..c5649ec20b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -56,8 +56,8 @@ public void deleteAll() { @PutMapping("/{voucherId}") @ResponseBody - public void update(@PathVariable("voucherId") UUID voucherId, @RequestBody CreateVoucherRequest createVoucherRequest) { - voucherService.update(voucherId, createVoucherRequest); + public VoucherDto update(@PathVariable("voucherId") UUID voucherId, @RequestBody CreateVoucherRequest createVoucherRequest) { + return voucherService.update(voucherId, createVoucherRequest); } @GetMapping("/created-at") diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index a94d5ad0d1..7ed3fe2196 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -69,11 +69,12 @@ public void deleteAll() { voucherRepository.deleteAll(); } - public void update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { + public VoucherDto update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { // TODO: modify code format VoucherDto voucherDto = readById(voucherId); Voucher voucher = new Voucher(voucherId, createVoucherRequest.discountValue(), createVoucherRequest.voucherType(), voucherDto.createdAt()); voucherRepository.update(voucher); + return VoucherDto.from(voucher); } public List readAllByType(VoucherType type) { From ba28910ea8673adc7fe52478abc915a3355c8df5 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 18:24:28 +0900 Subject: [PATCH 283/383] refactor: change name to ConsoleConfig and add console profile --- .../configuration/ConsoleConfig.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/configuration/ConsoleConfig.java diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/ConsoleConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/ConsoleConfig.java new file mode 100644 index 0000000000..990450ed1d --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/configuration/ConsoleConfig.java @@ -0,0 +1,16 @@ +package com.programmers.vouchermanagement.configuration; + +import org.beryx.textio.TextIO; +import org.beryx.textio.TextIoFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Profile("console") +@Configuration +public class ConsoleConfig { + @Bean + public TextIO textIO() { + return TextIoFactory.getTextIO(); + } +} From 6c5b83100e359d3c93a92395f17e0cfaff42bfc0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 18:25:06 +0900 Subject: [PATCH 284/383] refactor: add console profile --- .../vouchermanagement/consoleapp/io/ConsoleManager.java | 2 ++ .../vouchermanagement/consoleapp/menu/MenuHandler.java | 3 ++- .../vouchermanagement/consoleapp/runner/ConsoleAppRunner.java | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index d4c4844df7..85cfc71d71 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -9,12 +9,14 @@ import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import java.util.List; import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; +@Profile("console") @Component public class ConsoleManager { private static final Logger logger = LoggerFactory.getLogger(ConsoleManager.class); diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 76fc059518..fdb4152ab9 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -8,10 +8,11 @@ import com.programmers.vouchermanagement.voucher.dto.VoucherDto; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import java.util.List; - +@Profile("console") @Component public class MenuHandler { private static final Logger logger = LoggerFactory.getLogger(MenuHandler.class); diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java index 9f9cb5a221..48954f9eff 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleAppRunner.java @@ -3,8 +3,10 @@ import com.programmers.vouchermanagement.consoleapp.menu.MenuHandler; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; +@Profile("console") @Component public class ConsoleAppRunner implements ApplicationRunner { private final MenuHandler menuHandler; From 10edaba49ff828269c7f79bd1abcde0b90efec76 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 18:26:23 +0900 Subject: [PATCH 285/383] refactor: change profile name from "mvc" to "thyme" and change class name to *ThymeleafController --- ...rMVCController.java => CustomerThymeleafController.java} | 6 +++--- ...erMVCController.java => VoucherThymeleafController.java} | 6 +++--- ...letMVCController.java => WalletThymeleafController.java} | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) rename src/main/java/com/programmers/vouchermanagement/customer/controller/{CustomerMVCController.java => CustomerThymeleafController.java} (91%) rename src/main/java/com/programmers/vouchermanagement/voucher/controller/{VoucherMVCController.java => VoucherThymeleafController.java} (95%) rename src/main/java/com/programmers/vouchermanagement/wallet/controller/{WalletMVCController.java => WalletThymeleafController.java} (92%) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java similarity index 91% rename from src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java rename to src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java index 6915e0a039..3e533608c3 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java @@ -9,13 +9,13 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -@Profile("mvc") +@Profile("thyme") @RequestMapping("/customers") @Controller -public class CustomerMVCController { +public class CustomerThymeleafController { private final CustomerService customerService; - public CustomerMVCController(CustomerService customerService) { + public CustomerThymeleafController(CustomerService customerService) { this.customerService = customerService; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java similarity index 95% rename from src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java rename to src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java index cfa29dadf5..2485a8c15f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java @@ -11,13 +11,13 @@ import java.util.List; import java.util.UUID; -@Profile("mvc") +@Profile("thyme") @RequestMapping("/vouchers") @Controller -public class VoucherMVCController { +public class VoucherThymeleafController { private final VoucherService voucherService; - public VoucherMVCController(VoucherService voucherService) { + public VoucherThymeleafController(VoucherService voucherService) { this.voucherService = voucherService; } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletMVCController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java similarity index 92% rename from src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletMVCController.java rename to src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java index 9e54af075c..46f51f89bf 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletMVCController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java @@ -12,13 +12,13 @@ import java.util.List; import java.util.UUID; -@Profile("mvc") +@Profile("thyme") @RequestMapping("/wallets") @Controller -public class WalletMVCController { +public class WalletThymeleafController { private final WalletService walletService; - public WalletMVCController(WalletService walletService) { + public WalletThymeleafController(WalletService walletService) { this.walletService = walletService; } From fcd1e1cf6d385272ec69a5b4882338185bfd4fa8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 18:27:56 +0900 Subject: [PATCH 286/383] refactor: add jdbc profile and separate useless Bean in jdbc profile --- .../configuration/{AppConfig.java => JdbcConfig.java} | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) rename src/main/java/com/programmers/vouchermanagement/configuration/{AppConfig.java => JdbcConfig.java} (77%) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java similarity index 77% rename from src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java rename to src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java index 3b56d18753..05aed6b9e4 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/AppConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java @@ -1,21 +1,16 @@ package com.programmers.vouchermanagement.configuration; -import org.beryx.textio.TextIO; -import org.beryx.textio.TextIoFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import javax.sql.DataSource; +@Profile("jdbc") @Configuration -public class AppConfig { - @Bean - public TextIO textIO() { - return TextIoFactory.getTextIO(); - } - +public class JdbcConfig { @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); From ebb4a9056c782f3b801c710803e98db11df99acd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 18:28:11 +0900 Subject: [PATCH 287/383] refactor: add profile at MvcConfig --- .../programmers/vouchermanagement/configuration/MvcConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java index bce7c11dd0..68b95ced2e 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/MvcConfig.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; @@ -12,6 +13,7 @@ import java.text.SimpleDateFormat; import java.util.List; +@Profile({"thyme", "api"}) @Configuration public class MvcConfig implements WebMvcConfigurer { @Override From 6823244470d3788ca6b807d6e6286da8eca58a22 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 18:28:29 +0900 Subject: [PATCH 288/383] refactor: add "console", "api" profile --- .../vouchermanagement/voucher/controller/VoucherController.java | 2 +- .../vouchermanagement/wallet/controller/WalletController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index c5649ec20b..ab06d5e3b9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -14,7 +14,7 @@ import java.util.List; import java.util.UUID; -@Profile({"api", "console"}) +@Profile({"console","api"}) @RequestMapping("/api/v1/vouchers") @Controller public class VoucherController { diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java index b9fb4df28b..f62ca717c3 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.UUID; -@Profile("console") +@Profile({"console","api"}) @Controller public class WalletController { private final WalletService walletService; From 0fbb98910432c93c2bb440f4f342ac597f8c5a4d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 19:45:41 +0900 Subject: [PATCH 289/383] refactor: add "file" profile at CustomerFileManager and refactor JdbcConfig, TestConfig --- .../configuration/JdbcConfig.java | 10 ++++---- .../repository/CustomerFileManager.java | 2 ++ .../vouchermanagement/TestConfig.java | 23 ++----------------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java index 05aed6b9e4..ef138a6c13 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.configuration; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @@ -10,14 +11,11 @@ @Profile("jdbc") @Configuration +@ConfigurationPropertiesScan public class JdbcConfig { @Bean - public JdbcTemplate jdbcTemplate(DataSource dataSource) { - return new JdbcTemplate(dataSource); - } - - @Bean - public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); return new NamedParameterJdbcTemplate(jdbcTemplate); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java index b641098dc5..d5b108e151 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java @@ -4,6 +4,7 @@ import com.programmers.vouchermanagement.properties.AppProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import java.io.*; @@ -16,6 +17,7 @@ import static com.programmers.vouchermanagement.constant.Message.IO_EXCEPTION; @Component +@Profile("file") public class CustomerFileManager { private static final Logger logger = LoggerFactory.getLogger(CustomerFileManager.class); public final Map customers; diff --git a/src/test/java/com/programmers/vouchermanagement/TestConfig.java b/src/test/java/com/programmers/vouchermanagement/TestConfig.java index b5f321213b..6db7c7a781 100644 --- a/src/test/java/com/programmers/vouchermanagement/TestConfig.java +++ b/src/test/java/com/programmers/vouchermanagement/TestConfig.java @@ -1,8 +1,6 @@ package com.programmers.vouchermanagement; -import com.zaxxer.hikari.HikariDataSource; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; -import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -18,25 +16,8 @@ @ConfigurationPropertiesScan public class TestConfig { @Bean - public DataSource dataSource() { - var dataSource = DataSourceBuilder.create() - .url("jdbc:mysql://localhost:3306/test") - .username("root") - .password("20231028") - .type(HikariDataSource.class) - .build(); - dataSource.setMaximumPoolSize(1000); - dataSource.setMinimumIdle(100); - return dataSource; - } - - @Bean - public JdbcTemplate jdbcTemplate(DataSource dataSource) { - return new JdbcTemplate(dataSource); - } - - @Bean - public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) { + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); return new NamedParameterJdbcTemplate(jdbcTemplate); } } \ No newline at end of file From 501847ccdf32c9c513dde76abb493fd36086d87d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 19:48:14 +0900 Subject: [PATCH 290/383] refactor: refactor application properties at one yaml file --- src/main/resources/application-mvc.yaml | 0 src/main/resources/application.yaml | 16 +++++++++++++++- src/test/resources/application.yaml | 9 --------- 3 files changed, 15 insertions(+), 10 deletions(-) delete mode 100644 src/main/resources/application-mvc.yaml delete mode 100644 src/test/resources/application.yaml diff --git a/src/main/resources/application-mvc.yaml b/src/main/resources/application-mvc.yaml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 31042c6c8c..a80ad3b695 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -3,11 +3,15 @@ spring: url: jdbc:mysql://localhost:3306/ username: root password: 20231028 - mvc: hidden-method: filter: enabled: true +--- +spring: + config: + activate: + on-profile: file file: resources: path: src/main/resources/ @@ -18,3 +22,13 @@ file: voucher: file-name: voucher.json +--- +spring: + config: + activate: + on-profile: test + datasource: + url: jdbc:mysql://localhost:3306/ + username: root + password: 20231028 + diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml deleted file mode 100644 index 2f9a705608..0000000000 --- a/src/test/resources/application.yaml +++ /dev/null @@ -1,9 +0,0 @@ -file: - resources: - path: src/test/resources/ - - domains: - customer: - file-name: blacklist.csv - voucher: - file-name: voucher.json \ No newline at end of file From 0bc76d41326723e96f6e8a8d9fa0004fc5c7cb27 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:13:16 +0900 Subject: [PATCH 291/383] refactor: delete TestConfig --- .../vouchermanagement/TestConfig.java | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 src/test/java/com/programmers/vouchermanagement/TestConfig.java diff --git a/src/test/java/com/programmers/vouchermanagement/TestConfig.java b/src/test/java/com/programmers/vouchermanagement/TestConfig.java deleted file mode 100644 index 6db7c7a781..0000000000 --- a/src/test/java/com/programmers/vouchermanagement/TestConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.programmers.vouchermanagement; - -import org.springframework.boot.context.properties.ConfigurationPropertiesScan; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; - -import javax.sql.DataSource; - -@Configuration -@ComponentScan( - basePackages = {"com.programmers.vouchermanagement"} -) -@ConfigurationPropertiesScan -public class TestConfig { - @Bean - public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - return new NamedParameterJdbcTemplate(jdbcTemplate); - } -} \ No newline at end of file From 98fd375dde60b766f4ad49045345611ae2108bc3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:35:49 +0900 Subject: [PATCH 292/383] fix: fix db url --- src/main/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index a80ad3b695..49a97314b4 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,6 +1,6 @@ spring: datasource: - url: jdbc:mysql://localhost:3306/ + url: jdbc:mysql://localhost:3306/test username: root password: 20231028 mvc: @@ -28,7 +28,7 @@ spring: activate: on-profile: test datasource: - url: jdbc:mysql://localhost:3306/ + url: jdbc:mysql://localhost:3306/test username: root password: 20231028 From b6ffb67abca57705b0bededc4663ba9b31c2dbc7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:37:45 +0900 Subject: [PATCH 293/383] refactor: move Message, Constant to util package and set Constructor private --- .../vouchermanagement/consoleapp/io/ConsoleManager.java | 2 +- .../customer/repository/CustomerFileManager.java | 6 +++--- .../customer/repository/CustomerJDBCRepository.java | 4 ++-- .../vouchermanagement/{constant => util}/Constant.java | 4 +++- .../programmers/vouchermanagement/util/DomainMapper.java | 4 +++- .../vouchermanagement/{constant => util}/Message.java | 4 +++- .../voucher/repository/VoucherFileManager.java | 2 +- .../voucher/repository/VoucherFileRepository.java | 4 ++-- .../voucher/repository/VoucherInMemoryRepository.java | 4 ++-- .../voucher/repository/VoucherJDBCRepository.java | 4 ++-- .../vouchermanagement/voucher/service/VoucherService.java | 2 +- .../wallet/repository/WalletJDBCRepository.java | 6 +++--- .../vouchermanagement/wallet/service/WalletService.java | 2 +- 13 files changed, 27 insertions(+), 21 deletions(-) rename src/main/java/com/programmers/vouchermanagement/{constant => util}/Constant.java (76%) rename src/main/java/com/programmers/vouchermanagement/{constant => util}/Message.java (93%) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 85cfc71d71..bdb760e7f7 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -14,7 +14,7 @@ import java.util.List; -import static com.programmers.vouchermanagement.constant.Constant.LINE_SEPARATOR; +import static com.programmers.vouchermanagement.util.Constant.LINE_SEPARATOR; @Profile("console") @Component diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java index d5b108e151..f1525db8d3 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java @@ -12,9 +12,9 @@ import java.util.Map; import java.util.UUID; -import static com.programmers.vouchermanagement.constant.Constant.COMMA_SEPARATOR; -import static com.programmers.vouchermanagement.constant.Message.FILE_EXCEPTION; -import static com.programmers.vouchermanagement.constant.Message.IO_EXCEPTION; +import static com.programmers.vouchermanagement.util.Constant.COMMA_SEPARATOR; +import static com.programmers.vouchermanagement.util.Message.FILE_EXCEPTION; +import static com.programmers.vouchermanagement.util.Message.IO_EXCEPTION; @Component @Profile("file") diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 876eb7f0e1..0b29918a6b 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -10,8 +10,8 @@ import java.util.List; -import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; -import static com.programmers.vouchermanagement.constant.Message.NOT_INSERTED; +import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; +import static com.programmers.vouchermanagement.util.Message.NOT_INSERTED; import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.*; @Repository diff --git a/src/main/java/com/programmers/vouchermanagement/constant/Constant.java b/src/main/java/com/programmers/vouchermanagement/util/Constant.java similarity index 76% rename from src/main/java/com/programmers/vouchermanagement/constant/Constant.java rename to src/main/java/com/programmers/vouchermanagement/util/Constant.java index a42a70c56a..c596c1aef5 100644 --- a/src/main/java/com/programmers/vouchermanagement/constant/Constant.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Constant.java @@ -1,8 +1,10 @@ -package com.programmers.vouchermanagement.constant; +package com.programmers.vouchermanagement.util; public class Constant { public static final String LINE_SEPARATOR = System.lineSeparator(); public static final String COMMA_SEPARATOR = ", "; public static final int UPDATE_ONE_FLAG = 1; public static final int UPDATE_ZERO_FLAG = 0; + private Constant() { + } } diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index 1976daf641..2c353c2caf 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -27,7 +27,6 @@ public class DomainMapper { public static final String CREATED_AT_KEY = "created_at"; public static final String FROM_KEY = "from"; public static final String TO_KEY = "to"; - public final RowMapper voucherRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes(ID_KEY)); long discountValue = resultSet.getLong(DISCOUNT_VALUE_KEY); @@ -44,6 +43,9 @@ public class DomainMapper { return new Customer(id, name, isBlack); }; + private DomainMapper() { + } + private static UUID toUUID(byte[] bytes) { var byteBuffer = ByteBuffer.wrap(bytes); return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); diff --git a/src/main/java/com/programmers/vouchermanagement/constant/Message.java b/src/main/java/com/programmers/vouchermanagement/util/Message.java similarity index 93% rename from src/main/java/com/programmers/vouchermanagement/constant/Message.java rename to src/main/java/com/programmers/vouchermanagement/util/Message.java index 9c9fc1bbca..22f48d20c8 100644 --- a/src/main/java/com/programmers/vouchermanagement/constant/Message.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Message.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.constant; +package com.programmers.vouchermanagement.util; public class Message { public final static String NOT_INSERTED = "Noting was inserted!"; @@ -14,4 +14,6 @@ public class Message { public static final String ALREADY_EMPTY_TABLE = "The table is already empty."; public static final String FILE_EXCEPTION = "Error raised while opening the file."; public static final String INVALID_VOUCHER_TYPE = "Voucher type should be either fixed amount or percent discount voucher."; + private Message() { + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java index 55513cd088..ea7cbc840c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java @@ -16,7 +16,7 @@ import java.time.LocalDateTime; import java.util.*; -import static com.programmers.vouchermanagement.constant.Message.*; +import static com.programmers.vouchermanagement.util.Message.*; @Component @Profile("file") diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 15a0d3f268..8c1843ac76 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -12,8 +12,8 @@ import java.util.Optional; import java.util.UUID; -import static com.programmers.vouchermanagement.constant.Message.NOT_DELETED; -import static com.programmers.vouchermanagement.constant.Message.NOT_UPDATED; +import static com.programmers.vouchermanagement.util.Message.NOT_DELETED; +import static com.programmers.vouchermanagement.util.Message.NOT_UPDATED; @Repository @Profile("file") diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index 9499a339fd..bd605118d9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -8,8 +8,8 @@ import java.time.LocalDateTime; import java.util.*; -import static com.programmers.vouchermanagement.constant.Message.NOT_DELETED; -import static com.programmers.vouchermanagement.constant.Message.NOT_UPDATED; +import static com.programmers.vouchermanagement.util.Message.NOT_DELETED; +import static com.programmers.vouchermanagement.util.Message.NOT_UPDATED; @Repository @Profile("memory") diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 86af70728f..e723400a3c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -13,8 +13,8 @@ import java.time.LocalDateTime; import java.util.*; -import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; -import static com.programmers.vouchermanagement.constant.Message.*; +import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; +import static com.programmers.vouchermanagement.util.Message.*; import static com.programmers.vouchermanagement.voucher.repository.VoucherQuery.*; @Profile("jdbc") diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 7ed3fe2196..5034a39c9f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -13,7 +13,7 @@ import java.util.NoSuchElementException; import java.util.UUID; -import static com.programmers.vouchermanagement.constant.Message.NOT_FOUND_VOUCHER; +import static com.programmers.vouchermanagement.util.Message.NOT_FOUND_VOUCHER; @Service public class VoucherService { diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 35f26ac5a5..d01fc6b623 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -15,9 +15,9 @@ import java.util.Optional; import java.util.UUID; -import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ONE_FLAG; -import static com.programmers.vouchermanagement.constant.Constant.UPDATE_ZERO_FLAG; -import static com.programmers.vouchermanagement.constant.Message.*; +import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; +import static com.programmers.vouchermanagement.util.Constant.UPDATE_ZERO_FLAG; +import static com.programmers.vouchermanagement.util.Message.*; import static com.programmers.vouchermanagement.wallet.repository.WalletQuery.*; @Repository diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index db6c39ae8e..8bde4cefcd 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -15,7 +15,7 @@ import java.util.NoSuchElementException; import java.util.UUID; -import static com.programmers.vouchermanagement.constant.Message.NOT_FOUND_VOUCHER_ALLOCATION; +import static com.programmers.vouchermanagement.util.Message.NOT_FOUND_VOUCHER_ALLOCATION; @Service public class WalletService { From f45b4c605ddcffc944eca969b54a8dc8fc545efa Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:38:15 +0900 Subject: [PATCH 294/383] refactor: set Constructor private --- .../vouchermanagement/customer/repository/CustomerQuery.java | 2 ++ .../java/com/programmers/vouchermanagement/util/Validator.java | 3 ++- .../vouchermanagement/voucher/repository/VoucherQuery.java | 2 ++ .../vouchermanagement/wallet/repository/WalletQuery.java | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java index 97d9d3f996..50926e39e5 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java @@ -4,4 +4,6 @@ public class CustomerQuery { public static final String FIND_ALL_BLACK_CUSTOMER = "SELECT * FROM test.customers WHERE black = TRUE"; public static final String INSERT = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; public static final String FIND_ALL = "SELECT * FROM test.customers"; + private CustomerQuery() { + } } diff --git a/src/main/java/com/programmers/vouchermanagement/util/Validator.java b/src/main/java/com/programmers/vouchermanagement/util/Validator.java index e91286fae8..6c5eaf6632 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/Validator.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Validator.java @@ -7,7 +7,6 @@ public class Validator { private static final Logger logger = LoggerFactory.getLogger(Validator.class); private static final long MAX_LONG_LENGTH = String.valueOf(Long.MAX_VALUE).length(); - //messages private static final String INVALID_DISCOUNT_AMOUNT_MESSAGE = "Input should be a number greater than 0"; @@ -15,6 +14,8 @@ public class Validator { "Input should be a number greater than 0 and smaller than 100"; private static final String INVALID_DISCOUNT_VALUE_MESSAGE = "Input should be a number greater than 0 and smaller than 999,999,999,999,999,999(length: 18)"; + private Validator() { + } public static void validateDiscountValue(VoucherType voucherType, String discountValueStr) { validateLongBoundary(discountValueStr); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java index 6a4ed06dc5..5f73cd9905 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java @@ -9,4 +9,6 @@ public class VoucherQuery { public static final String DELETE_VOUCHER = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; public static final String DELETE_ALL = "DELETE FROM test.vouchers"; public static final String UPDATE_VOUCHER = "UPDATE test.vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; + private VoucherQuery() { + } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java index d04977800a..0d06755ac6 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java @@ -6,4 +6,6 @@ public class WalletQuery { public static final String DELETE_ALL = "TRUNCATE TABLE test.ownership"; public static final String FIND_CUSTOMER_BY_VOUCHER_ID = "SELECT c.* FROM test.ownership as o JOIN test.customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)"; public static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID = "SELECT v.* FROM test.ownership as o JOIN test.vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)"; + private WalletQuery() { + } } From 7b90e69ef00d52a6d0887e1e8160c16957bc4448 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:38:40 +0900 Subject: [PATCH 295/383] chore: make new database called prod --- src/main/resources/schema.sql | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 045d5c7efe..c3dee17095 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,3 +1,29 @@ +CREATE DATABASE prod; +use prod; +CREATE TABLE customers +( + id BINARY(16) PRIMARY KEY, + name varchar(20) NOT NULL, + black boolean not null, + CONSTRAINT name UNIQUE (name) +); + +CREATE TABLE vouchers +( + id BINARY(16) PRIMARY KEY, + type enum ('FIXED', 'PERCENT') NOT NULL, + discount_value varchar(50) NOT NULL, + created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) +); + +CREATE TABLE ownership +( + voucher_id BINARY(16) PRIMARY KEY, + customer_id BINARY(16), + FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, + FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE +); + CREATE DATABASE test; use test; CREATE TABLE customers From f0ee1331311ba95f371e4e10c917727678a3aa97 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:40:30 +0900 Subject: [PATCH 296/383] fix: fix database url --- src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 49a97314b4..5d0550299f 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,6 +1,6 @@ spring: datasource: - url: jdbc:mysql://localhost:3306/test + url: jdbc:mysql://localhost:3306/prod username: root password: 20231028 mvc: From cdc57aff43be5d7fd2dda1f5bf5c1a63bcbe0fb6 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:42:18 +0900 Subject: [PATCH 297/383] fix: set convention --- .../com/programmers/vouchermanagement/util/Message.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/Message.java b/src/main/java/com/programmers/vouchermanagement/util/Message.java index 22f48d20c8..45393e6935 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/Message.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Message.java @@ -1,10 +1,10 @@ package com.programmers.vouchermanagement.util; public class Message { - public final static String NOT_INSERTED = "Noting was inserted!"; - public final static String NOT_UPDATED = "Noting was updated!"; - public final static String NOT_DELETED = "Noting was deleted!"; - public final static String EMPTY_RESULT = "Got empty result!"; + public static final String NOT_INSERTED = "Noting was inserted!"; + public static final String NOT_UPDATED = "Noting was updated!"; + public static final String NOT_DELETED = "Noting was deleted!"; + public static final String EMPTY_RESULT = "Got empty result!"; public static final String IO_EXCEPTION = "Error raised while reading file!"; public static final String NOT_FOUND_VOUCHER = "There is no such voucher."; public static final String NOT_FOUND_CUSTOMER = "There is no such customer."; @@ -14,6 +14,7 @@ public class Message { public static final String ALREADY_EMPTY_TABLE = "The table is already empty."; public static final String FILE_EXCEPTION = "Error raised while opening the file."; public static final String INVALID_VOUCHER_TYPE = "Voucher type should be either fixed amount or percent discount voucher."; + private Message() { } } From 2acd086f38e7fc0b048a32b2cfb4f0f7ee24239a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 20:53:55 +0900 Subject: [PATCH 298/383] refactor: change method name from save to insert --- .../repository/CustomerFileRepository.java | 2 +- .../CustomerInMemoryRepository.java | 2 +- .../repository/CustomerJDBCRepository.java | 14 ++++---- .../repository/CustomerRepository.java | 2 +- .../repository/VoucherFileRepository.java | 2 +- .../repository/VoucherInMemoryRepository.java | 2 +- .../repository/VoucherJDBCRepository.java | 2 +- .../voucher/repository/VoucherRepository.java | 2 +- .../voucher/service/VoucherService.java | 2 +- .../repository/WalletJDBCRepository.java | 2 +- .../wallet/repository/WalletRepository.java | 2 +- .../wallet/service/WalletService.java | 2 +- .../VoucherInMemoryRepositoryTest.java | 4 +-- .../repository/VoucherJDBCRepositoryTest.java | 12 +++---- .../voucher/service/VoucherServiceTest.java | 4 +-- .../repository/WalletJDBCRepositoryTest.java | 36 +++++++++---------- .../wallet/service/WalletServiceTest.java | 2 +- 17 files changed, 48 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 39168499ac..88dc7377e7 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -19,7 +19,7 @@ public CustomerFileRepository(CustomerFileManager customerFileManager) { } @Override - public void save(Customer customer) { + public void insert(Customer customer) { customerFileManager.customers.put(customer.getId(), customer); customerFileManager.saveFile(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java index 31e5c4f0f1..d528b7e40f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java @@ -22,7 +22,7 @@ public CustomerInMemoryRepository() { } @Override - public void save(Customer customer) { + public void insert(Customer customer) { customers.put(customer.getId(), customer); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 0b29918a6b..d5a84b43a1 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -10,9 +10,9 @@ import java.util.List; +import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.*; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Message.NOT_INSERTED; -import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.*; @Repository @Profile("jdbc") @@ -27,11 +27,7 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMap } @Override - public List findAllBlackCustomer() { - return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); - } - - public void save(Customer customer) { + public void insert(Customer customer) { int update = jdbcTemplate.update(INSERT, domainMapper.customerToParamMap(customer)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_INSERTED); @@ -39,6 +35,12 @@ public void save(Customer customer) { } } + @Override + public List findAllBlackCustomer() { + return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); + } + + @Override public List findAll() { return jdbcTemplate.query(FIND_ALL, domainMapper.customerRowMapper); diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java index 651486907f..5ee7d00dc9 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerRepository.java @@ -5,7 +5,7 @@ import java.util.List; public interface CustomerRepository { - void save(Customer customer); + void insert(Customer customer); List findAll(); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 8c1843ac76..a1119f9eaa 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -27,7 +27,7 @@ public VoucherFileRepository(VoucherFileManager voucherFileManager) { } @Override - public void save(Voucher voucher) { + public void insert(Voucher voucher) { voucherFileManager.vouchers.put(voucher.voucherId(), voucher); voucherFileManager.saveFile(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index bd605118d9..726750e664 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -21,7 +21,7 @@ public VoucherInMemoryRepository() { } @Override - public void save(Voucher voucher) { + public void insert(Voucher voucher) { vouchers.put(voucher.voucherId(), voucher); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index e723400a3c..4c871e08e6 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -30,7 +30,7 @@ public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapp } @Override - public void save(Voucher voucher) { + public void insert(Voucher voucher) { int update = jdbcTemplate.update(INSERT, domainMapper.voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { throw new RuntimeException(NOT_INSERTED); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index 286b5b3d4c..c90a522b16 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -9,7 +9,7 @@ import java.util.UUID; public interface VoucherRepository { - void save(Voucher voucher); + void insert(Voucher voucher); List findAll(); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 5034a39c9f..992d39bdfd 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -26,7 +26,7 @@ public VoucherService(VoucherRepository voucherRepository) { public VoucherDto create(CreateVoucherRequest createVoucherRequest) { //TODO: now? DB vs Application Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType(), LocalDateTime.now()); - voucherRepository.save(voucher); + voucherRepository.insert(voucher); return VoucherDto.from(voucher); } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index d01fc6b623..0f46b3b6ca 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -32,7 +32,7 @@ public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMappe } @Override - public void save(Ownership ownership) { + public void insert(Ownership ownership) { int update = jdbcTemplate.update(INSERT, domainMapper.ownershipToParamMap(ownership)); if (update != UPDATE_ONE_FLAG) { logger.error(CAN_NOT_INSERT_OWNERSHIP); diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java index 1f1b1e0263..8e2299da30 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletRepository.java @@ -9,7 +9,7 @@ import java.util.UUID; public interface WalletRepository { - void save(Ownership ownership); + void insert(Ownership ownership); List findAllVoucherByCustomerId(UUID customerId); diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index 8bde4cefcd..bf1caaa414 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -27,7 +27,7 @@ public WalletService(WalletRepository walletRepository) { } public void allocate(Ownership ownership) { - walletRepository.save(ownership); + walletRepository.insert(ownership); } public CustomerDto readCustomerByVoucherId(UUID voucherId) { diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java index 5d42525f73..c6eedc255a 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java @@ -20,7 +20,7 @@ class VoucherInMemoryRepositoryTest { @DisplayName("🆗 바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); - voucherInMemoryRepository.save(voucher); + voucherInMemoryRepository.insert(voucher); voucherInMemoryRepository.delete(voucher.voucherId()); @@ -39,7 +39,7 @@ void deleteNonExistVoucherFail() { @DisplayName("🆗 바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); - voucherInMemoryRepository.save(voucher); + voucherInMemoryRepository.insert(voucher); Voucher updatedVoucher = new Voucher(voucher.voucherId(), 100, VoucherType.PERCENT); voucherInMemoryRepository.update(updatedVoucher); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index b26955d313..6cd1a25702 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -39,7 +39,7 @@ void init() { @DisplayName("🆗 고정 금액 할인 바우처를 추가할 수 있다.") void saveFixedAmountVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); @@ -51,7 +51,7 @@ void saveFixedAmountVoucher() { @DisplayName("🆗 퍼센트 할인 바우처를 추가할 수 있다.") void savePercentVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 50, VoucherType.PERCENT); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); @@ -63,7 +63,7 @@ void savePercentVoucher() { @DisplayName("🆗 모든 바우처를 조회할 수 있다. 단, 없다면 빈 list를 반환한다.") void findAllVoucher() { for (int i = 1; i < 6; i++) - voucherJDBCRepository.save(new Voucher(UUID.randomUUID(), i * 100, VoucherType.PERCENT)); + voucherJDBCRepository.insert(new Voucher(UUID.randomUUID(), i * 100, VoucherType.PERCENT)); List vouchers = voucherJDBCRepository.findAll(); @@ -74,7 +74,7 @@ void findAllVoucher() { @DisplayName("🆗 바우처를 아이디로 조회할 수 있다.") void findVoucherById() { Voucher voucher = new Voucher(UUID.randomUUID(), 1234, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); @@ -96,7 +96,7 @@ void findNonExistentVoucherById() { @DisplayName("🆗 바우처를 아이디로 삭제할 수 있다.") void deleteVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); voucherJDBCRepository.delete(voucher.voucherId()); @@ -113,7 +113,7 @@ void deleteNonExistentVoucher() { @DisplayName("🆗 바우처를 업데이트 할 수 있다.") void updateVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Voucher updatedVoucher = new Voucher(voucher.voucherId(), 100, VoucherType.PERCENT); voucherJDBCRepository.update(updatedVoucher); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index ee114edd6a..4eb2b95f08 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -43,7 +43,7 @@ void createFixedAmountVoucherSucceed() { CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(1000, VoucherType.FIXED); voucherService.create(createVoucherRequest); - verify(voucherRepository, times(1)).save(any(Voucher.class)); + verify(voucherRepository, times(1)).insert(any(Voucher.class)); } @Test @@ -52,7 +52,7 @@ void createPercentDiscountVoucherSucceed() { CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(100, VoucherType.PERCENT); voucherService.create(createVoucherRequest); - verify(voucherRepository, times(1)).save(any(Voucher.class)); + verify(voucherRepository, times(1)).insert(any(Voucher.class)); } @Test diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index 2c69ea35b6..4359c56f29 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -62,37 +62,37 @@ void injectionTest() { @DisplayName("🆗 고객에게 바우처를 할당할 수 있다.") void save() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처 주인"); customerJDBCRepository.save(customer); Ownership newOwnership = new Ownership(voucher.voucherId(), customer.getCustomerId()); - walletJDBCRepository.save(newOwnership); + walletJDBCRepository.insert(newOwnership); } @Test @DisplayName("🚨 이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") void saveAllocatedVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처를 가진 고객"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); Customer customer2 = new Customer(UUID.randomUUID(), "바우처를 가지지 못하는 고객"); customerJDBCRepository.save(customer2); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer2.getCustomerId()))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer2.getCustomerId()))); } @Test @DisplayName("🚨 고객 id에 해당하는 고객이 없다면, 고객에게 바우처를 할당할 수 없다.") void saveNonExistentCustomer() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(voucher.voucherId(), NON_EXISTENT_CUSTOMER_ID))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(voucher.voucherId(), NON_EXISTENT_CUSTOMER_ID))); } @Test @@ -101,13 +101,13 @@ void saveNonExistentVoucher() { Customer customer = new Customer(UUID.randomUUID(), "바우처를 가지지 못한 고객"); customerJDBCRepository.save(customer); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(NON_EXISTENT_VOUCHER_ID, customer.getCustomerId()))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(NON_EXISTENT_VOUCHER_ID, customer.getCustomerId()))); } @Test @DisplayName("🚨 id에 해당하는 바우처와 고객이 모두 없다면, 바우처를 고객에게 할당할 수 없다.") void saveNonExistentBoth() { - assertThrows(RuntimeException.class, () -> walletJDBCRepository.save(new Ownership(NON_EXISTENT_VOUCHER_ID, NON_EXISTENT_CUSTOMER_ID))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(NON_EXISTENT_VOUCHER_ID, NON_EXISTENT_CUSTOMER_ID))); } @Test @@ -118,8 +118,8 @@ void findAllVoucherByCustomerId() { for (int i = 1; i < 6; i++) { Voucher voucher = new Voucher(UUID.randomUUID(), i, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); - walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); + voucherJDBCRepository.insert(voucher); + walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); } // If the customer don't have any voucher, then return empty list. @@ -136,11 +136,11 @@ void findAllVoucherByNonExistentCustomerId() { @DisplayName("🆗 바우처 id를 통해 할당 정보를 삭제할 수 있다. 단, 바우처 자체는 삭제되지 않는다.") void delete() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "1개의 삭제될 바우처를 가진 주인"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); walletJDBCRepository.delete(voucher.voucherId()); @@ -152,7 +152,7 @@ void delete() { @DisplayName("🚨 바우처에 대한 할당 정보가 없다면, 함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 없다.") void deleteNonAllocatedVoucher() { Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); assertThrows(RuntimeException.class, () -> walletJDBCRepository.delete(voucher.voucherId())); } @@ -161,11 +161,11 @@ void deleteNonAllocatedVoucher() { @DisplayName("🆗 바우처 id로 바우처를 가진 고객 정보를 가져올 수 있다.") void findCustomerByVoucherId() { Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "조회될 고객"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()); @@ -183,11 +183,11 @@ void findCustomerByNonExistentVoucherId() { @DisplayName("🆗 바우처 자체를 삭제하면, 바우처 소유 정보가 사라진다.") void autoDeleteAfterVoucherDelete() { Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); - voucherJDBCRepository.save(voucher); + voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "삭제될 바우처를 가진 고객"); customerJDBCRepository.save(customer); - walletJDBCRepository.save(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); voucherJDBCRepository.delete(voucher.voucherId()); diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java index 5378e42b5c..866c925150 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java @@ -47,7 +47,7 @@ void initTest() { void allocate() { walletService.allocate(ownership); - verify(walletRepository, times(1)).save(ownership); + verify(walletRepository, times(1)).insert(ownership); } @Test From fbdd43715a1a8f7dd0b30683eb0bb04897cb2df0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 22:55:24 +0900 Subject: [PATCH 299/383] refactor: change name from VoucherDto to VoucherResponse and implement VoucherTypeManager --- .../consoleapp/io/ConsoleManager.java | 26 +++++----- .../consoleapp/menu/MenuHandler.java | 7 +-- .../vouchermanagement/util/Validator.java | 49 ------------------- .../voucher/controller/VoucherController.java | 18 +++---- .../VoucherThymeleafController.java | 8 +-- .../vouchertype/VoucherTypeManager.java | 27 ++++++++++ .../voucher/dto/VoucherDto.java | 15 ------ .../voucher/dto/VoucherResponse.java | 12 +++++ .../voucher/service/VoucherService.java | 34 ++++++------- .../wallet/controller/WalletController.java | 6 +-- .../controller/WalletThymeleafController.java | 4 +- .../wallet/service/WalletService.java | 6 +-- 12 files changed, 92 insertions(+), 120 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/util/Validator.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManager.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index bdb760e7f7..77530b2219 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -2,10 +2,10 @@ import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.customer.dto.CustomerDto; -import com.programmers.vouchermanagement.util.Validator; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,6 +13,7 @@ import org.springframework.stereotype.Component; import java.util.List; +import java.util.Objects; import static com.programmers.vouchermanagement.util.Constant.LINE_SEPARATOR; @@ -67,23 +68,18 @@ public Menu selectMenu() { public CreateVoucherRequest instructCreate() { String createMenu = textIO.newStringInputReader() .read(CREATE_SELECTION_INSTRUCTION); - VoucherType voucherType = VoucherType.findCreateMenu(createMenu) - .orElseThrow(() -> { - logger.error(INVALID_VOUCHER_TYPE_MESSAGE); - return new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE); - }); + VoucherType voucherType = VoucherTypeManager.get(createMenu); String discountValueStr = textIO.newStringInputReader() .read(VOUCHER_DISCOUNT_AMOUNT_INSTRUCTION); - Validator.validateDiscountValue(voucherType, discountValueStr); - return new CreateVoucherRequest(Long.parseLong(discountValueStr), voucherType); + return new CreateVoucherRequest(voucherType.getName(), Long.parseLong(discountValueStr)); } - public void printCreateResult(VoucherDto voucher) { + public void printCreateResult(VoucherResponse voucher) { textIO.getTextTerminal().println(CREATE_SUCCESS_MESSAGE.formatted(voucher.id())); } - public void printReadAllVouchers(List vouchers) { + public void printReadAllVouchers(List vouchers) { if (vouchers.isEmpty()) { textIO.getTextTerminal().println(NO_CONTENT.formatted("voucher")); } @@ -105,16 +101,16 @@ private String formatCustomer(CustomerDto customer) { .formatted(customer.id(), customer.name()); } - private String formatVoucherDTO(VoucherDto voucher) { + private String formatVoucherDTO(VoucherResponse voucher) { return """ Voucher ID : %s Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------""" .formatted(voucher.id(), - voucher.voucherTypeName(), + voucher.typeName(), voucher.discountValue() + - (voucher.isPercent() ? PERCENTAGE : EMPTY)); + (Objects.equals(voucher.typeName(), "PERCENT") ? PERCENTAGE : EMPTY)); } public void printExit() { diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index fdb4152ab9..3045ccdad2 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -5,13 +5,14 @@ import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.voucher.controller.VoucherController; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import java.util.List; + @Profile("console") @Component public class MenuHandler { @@ -66,11 +67,11 @@ private void executeMenu(Menu menu) { case INCORRECT_MENU -> consoleManager.printIncorrectMenu(); case CREATE -> { CreateVoucherRequest createVoucherRequest = consoleManager.instructCreate(); - VoucherDto voucher = voucherController.create(createVoucherRequest); + VoucherResponse voucher = voucherController.create(createVoucherRequest); consoleManager.printCreateResult(voucher); } case LIST -> { - List vouchers = voucherController.readAll(); + List vouchers = voucherController.readAll(); consoleManager.printReadAllVouchers(vouchers); } //TODO: customerDTO diff --git a/src/main/java/com/programmers/vouchermanagement/util/Validator.java b/src/main/java/com/programmers/vouchermanagement/util/Validator.java deleted file mode 100644 index 6c5eaf6632..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/util/Validator.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.programmers.vouchermanagement.util; - -import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Validator { - private static final Logger logger = LoggerFactory.getLogger(Validator.class); - private static final long MAX_LONG_LENGTH = String.valueOf(Long.MAX_VALUE).length(); - //messages - private static final String INVALID_DISCOUNT_AMOUNT_MESSAGE = - "Input should be a number greater than 0"; - private static final String INVALID_DISCOUNT_PERCENT_MESSAGE = - "Input should be a number greater than 0 and smaller than 100"; - private static final String INVALID_DISCOUNT_VALUE_MESSAGE = - "Input should be a number greater than 0 and smaller than 999,999,999,999,999,999(length: 18)"; - private Validator() { - } - - public static void validateDiscountValue(VoucherType voucherType, String discountValueStr) { - validateLongBoundary(discountValueStr); - long discountValue = Long.parseLong(discountValueStr); - switch (voucherType) { - case FIXED -> validateDiscountAmount(discountValue); - case PERCENT -> validateDiscountPercent(discountValue); - } - } - - private static void validateLongBoundary(String discountAmount) { - if (MAX_LONG_LENGTH <= discountAmount.length()) { - logger.error(INVALID_DISCOUNT_VALUE_MESSAGE); - throw new IllegalArgumentException(INVALID_DISCOUNT_VALUE_MESSAGE); - } - } - - private static void validateDiscountAmount(long discountAmount) { - if (discountAmount <= 0) { - logger.error(INVALID_DISCOUNT_AMOUNT_MESSAGE); - throw new IllegalArgumentException(INVALID_DISCOUNT_AMOUNT_MESSAGE); - } - } - - private static void validateDiscountPercent(long discountPercent) { - if (discountPercent <= 0 || discountPercent > 100) { - logger.error(INVALID_DISCOUNT_PERCENT_MESSAGE); - throw new IllegalArgumentException(INVALID_DISCOUNT_PERCENT_MESSAGE); - } - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index ab06d5e3b9..84ad775cee 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,8 +1,8 @@ package com.programmers.vouchermanagement.voucher.controller; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; @@ -14,7 +14,7 @@ import java.util.List; import java.util.UUID; -@Profile({"console","api"}) +@Profile({"console", "api"}) @RequestMapping("/api/v1/vouchers") @Controller public class VoucherController { @@ -26,19 +26,19 @@ public VoucherController(VoucherService voucherService) { @PostMapping @ResponseBody - public VoucherDto create(@RequestBody CreateVoucherRequest createVoucherRequest) { + public VoucherResponse create(@RequestBody CreateVoucherRequest createVoucherRequest) { return voucherService.create(createVoucherRequest); } @GetMapping @ResponseBody - public List readAll() { + public List readAll() { return voucherService.readAll(); } @GetMapping("/{voucherId}") @ResponseBody - public VoucherDto readById(@PathVariable("voucherId") UUID voucherId) { + public VoucherResponse readById(@PathVariable("voucherId") UUID voucherId) { return voucherService.readById(voucherId); } @@ -56,13 +56,13 @@ public void deleteAll() { @PutMapping("/{voucherId}") @ResponseBody - public VoucherDto update(@PathVariable("voucherId") UUID voucherId, @RequestBody CreateVoucherRequest createVoucherRequest) { + public VoucherResponse update(@PathVariable("voucherId") UUID voucherId, @RequestBody CreateVoucherRequest createVoucherRequest) { return voucherService.update(voucherId, createVoucherRequest); } @GetMapping("/created-at") @ResponseBody - public List readAllByCreatedAt(@RequestParam(name = "from") LocalDate from, @RequestParam(name = "to") LocalDate to) { + public List readAllByCreatedAt(@RequestParam(name = "from") LocalDate from, @RequestParam(name = "to") LocalDate to) { LocalDateTime fromDateTime = LocalDateTime.of(from, LocalTime.of(0, 0, 0)); LocalDateTime toDateTime = LocalDateTime.of(to, LocalTime.of(23, 59, 59)); return voucherService.readAllByCreatedAt(fromDateTime, toDateTime); @@ -70,7 +70,7 @@ public List readAllByCreatedAt(@RequestParam(name = "from") LocalDat @GetMapping("type/{type}") @ResponseBody - public List readAllByType(@PathVariable("type") VoucherType type) { + public List readAllByType(@PathVariable("type") VoucherType type) { return voucherService.readAllByType(type); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java index 2485a8c15f..c414535caf 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.voucher.controller; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; @@ -34,7 +34,7 @@ public String ViewCreatePage(Model model) { @GetMapping public String viewVouchersPage(Model model) { - List vouchers = voucherService.readAll(); + List vouchers = voucherService.readAll(); model.addAttribute("vouchers", vouchers); return "voucher/vouchers"; } @@ -42,7 +42,7 @@ public String viewVouchersPage(Model model) { @GetMapping("/{voucherId}") public String readById(@PathVariable("voucherId") UUID voucherId, Model model) { try { - VoucherDto voucher = voucherService.readById(voucherId); + VoucherResponse voucher = voucherService.readById(voucherId); model.addAttribute("voucher", voucher); return "voucher/voucher-detail"; } catch (RuntimeException e) { @@ -72,7 +72,7 @@ public String update(@PathVariable("voucherId") UUID voucherId, CreateVoucherReq @GetMapping("/update/{voucherId}") public String viewUpdatePage(@PathVariable("voucherId") UUID voucherId, Model model) { try { - VoucherDto voucher = voucherService.readById(voucherId); + VoucherResponse voucher = voucherService.readById(voucherId); model.addAttribute("voucher", voucher); return "voucher/voucher-update"; } catch (RuntimeException e) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManager.java new file mode 100644 index 0000000000..8036ab501b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManager.java @@ -0,0 +1,27 @@ +package com.programmers.vouchermanagement.voucher.domain.vouchertype; + +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.function.Supplier; + +public enum VoucherTypeManager { + FIXED(FixedAmountVoucherType::getInstance), + PERCENT(PercentVoucherType::getInstance); + + private final Supplier voucherTypeSupplier; + + VoucherTypeManager(Supplier voucherTypeSupplier) { + this.voucherTypeSupplier = voucherTypeSupplier; + } + + public static VoucherType get(String typeName) { + return getGenerator(typeName).voucherTypeSupplier.get(); + } + + private static VoucherTypeManager getGenerator(String typeName) { + return Arrays.stream(values()) + .filter(type -> type.name().equals(typeName)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(MessageFormat.format("There is no such type: {0}.", typeName))); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java deleted file mode 100644 index ad213fd280..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.programmers.vouchermanagement.voucher.dto; - -import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; - -import java.time.LocalDateTime; -import java.util.UUID; - -public record VoucherDto(UUID id, long discountValue, String voucherTypeName, boolean isPercent, - LocalDateTime createdAt) { - public static VoucherDto from(Voucher voucher) { - VoucherType voucherType = voucher.voucherType(); - return new VoucherDto(voucher.voucherId(), voucher.discountValue(), voucherType.displayTypeName(), voucherType.isPercent(), voucher.createdAt()); - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java new file mode 100644 index 0000000000..c8d5a4bf1a --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -0,0 +1,12 @@ +package com.programmers.vouchermanagement.voucher.dto; + +import com.programmers.vouchermanagement.voucher.domain.Voucher; + +import java.time.LocalDateTime; +import java.util.UUID; + +public record VoucherResponse(UUID id, LocalDateTime createdAt, String typeName, long discountValue) { + public static VoucherResponse from(Voucher voucher) { + return new VoucherResponse(voucher.getId(), voucher.getCreatedAt(), voucher.getTypeName(), voucher.getDiscountValue()); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 992d39bdfd..807a5debc2 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,9 +1,9 @@ package com.programmers.vouchermanagement.voucher.service; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; @@ -23,14 +23,14 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public VoucherDto create(CreateVoucherRequest createVoucherRequest) { + public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { //TODO: now? DB vs Application - Voucher voucher = new Voucher(UUID.randomUUID(), createVoucherRequest.discountValue(), createVoucherRequest.voucherType(), LocalDateTime.now()); + Voucher voucher = new Voucher(UUID.randomUUID(), LocalDateTime.now(), createVoucherRequest.typeName(), createVoucherRequest.discountValue()); voucherRepository.insert(voucher); - return VoucherDto.from(voucher); + return VoucherResponse.from(voucher); } - public List readAll() { + public List readAll() { List vouchers = voucherRepository.findAll(); if (vouchers.isEmpty()) { @@ -38,11 +38,11 @@ public List readAll() { } return vouchers.stream() - .map(VoucherDto::from) + .map(VoucherResponse::from) .toList(); } - public List readAllByCreatedAt(LocalDateTime from, LocalDateTime to) { + public List readAllByCreatedAt(LocalDateTime from, LocalDateTime to) { List vouchers = voucherRepository.findAllByCreatedAt(from, to); if (vouchers.isEmpty()) { @@ -50,15 +50,15 @@ public List readAllByCreatedAt(LocalDateTime from, LocalDateTime to) } return vouchers.stream() - .map(VoucherDto::from) + .map(VoucherResponse::from) .toList(); } - public VoucherDto readById(UUID voucherId) { + public VoucherResponse readById(UUID voucherId) { Voucher voucher = voucherRepository .findById(voucherId) .orElseThrow(() -> new NoSuchElementException(NOT_FOUND_VOUCHER)); - return VoucherDto.from(voucher); + return VoucherResponse.from(voucher); } public void delete(UUID voucherId) { @@ -69,15 +69,15 @@ public void deleteAll() { voucherRepository.deleteAll(); } - public VoucherDto update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { + public VoucherResponse update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { // TODO: modify code format - VoucherDto voucherDto = readById(voucherId); - Voucher voucher = new Voucher(voucherId, createVoucherRequest.discountValue(), createVoucherRequest.voucherType(), voucherDto.createdAt()); + VoucherResponse voucherResponse = readById(voucherId); + Voucher voucher = new Voucher(voucherId, voucherResponse.createdAt(), createVoucherRequest.typeName(), createVoucherRequest.discountValue()); voucherRepository.update(voucher); - return VoucherDto.from(voucher); + return VoucherResponse.from(voucher); } - public List readAllByType(VoucherType type) { - return voucherRepository.findAllByType(type).stream().map(VoucherDto::from).toList(); + public List readAllByType(VoucherType type) { + return voucherRepository.findAllByType(type).stream().map(VoucherResponse::from).toList(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java index f62ca717c3..db0d93e636 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.wallet.controller; import com.programmers.vouchermanagement.customer.dto.CustomerDto; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.service.WalletService; import org.springframework.context.annotation.Profile; @@ -11,7 +11,7 @@ import java.util.List; import java.util.UUID; -@Profile({"console","api"}) +@Profile({"console", "api"}) @Controller public class WalletController { private final WalletService walletService; @@ -28,7 +28,7 @@ public CustomerDto readCustomerByVoucherId(UUID voucherId, Model model) { return walletService.readCustomerByVoucherId(voucherId); } - public List readAllVoucherByCustomerId(UUID customerId, Model model) { + public List readAllVoucherByCustomerId(UUID customerId, Model model) { return walletService.readAllVoucherByCustomerId(customerId); } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java index 46f51f89bf..68642b3809 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.wallet.controller; import com.programmers.vouchermanagement.customer.dto.CustomerDto; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.service.WalletService; import org.springframework.context.annotation.Profile; @@ -36,7 +36,7 @@ public String readCustomerByVoucherId(@PathVariable("voucherId") UUID voucherId, @GetMapping("/customers/{customerId}") public String readAllVoucherByCustomerId(@PathVariable("customerId") UUID customerId, Model model) { - List vouchers = walletService.readAllVoucherByCustomerId(customerId); + List vouchers = walletService.readAllVoucherByCustomerId(customerId); model.addAttribute("vouchers", List.of(vouchers)); return "views/vouchers"; } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index bf1caaa414..2ad685ece3 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -3,7 +3,7 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.dto.CustomerDto; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.dto.VoucherDto; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.repository.WalletRepository; import org.slf4j.Logger; @@ -38,10 +38,10 @@ public CustomerDto readCustomerByVoucherId(UUID voucherId) { return CustomerDto.from(customer); } - public List readAllVoucherByCustomerId(UUID customerId) { + public List readAllVoucherByCustomerId(UUID customerId) { List vouchers = walletRepository.findAllVoucherByCustomerId(customerId); if (vouchers.isEmpty()) return Collections.emptyList(); - return vouchers.stream().map(VoucherDto::from).toList(); + return vouchers.stream().map(VoucherResponse::from).toList(); } public void deleteVoucherFromCustomer(UUID voucherId) { From f02c0cf9be13112b02be3995c98a551724f3f453 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 22:57:25 +0900 Subject: [PATCH 300/383] refactor: refactor VoucherType from enum to abstract class and apply --- .../customer/service/CustomerService.java | 2 +- .../vouchermanagement/util/DomainMapper.java | 11 ++- .../voucher/domain/Voucher.java | 41 +++++++++- .../voucher/domain/VoucherType.java | 34 -------- .../vouchertype/FixedAmountVoucherType.java | 28 +++++++ .../vouchertype/PercentVoucherType.java | 28 +++++++ .../domain/vouchertype/VoucherType.java | 9 +++ .../repository/VoucherFileManager.java | 25 +++--- .../repository/VoucherFileRepository.java | 12 +-- .../repository/VoucherInMemoryRepository.java | 15 ++-- .../repository/VoucherJDBCRepository.java | 14 +--- .../voucher/repository/VoucherRepository.java | 2 +- .../VoucherInMemoryRepositoryTest.java | 17 ++-- .../repository/VoucherJDBCRepositoryTest.java | 63 ++++++++------- .../voucher/service/VoucherServiceTest.java | 19 +++-- .../repository/WalletJDBCRepositoryTest.java | 80 +++++++++---------- 16 files changed, 226 insertions(+), 174 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherType.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index ec6bb66329..78db0f04f9 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -20,7 +20,7 @@ public CustomerService(CustomerRepository customerRepository) { public void create(CreateCustomerRequest createCustomerRequest) { Customer customer = new Customer(UUID.randomUUID(), createCustomerRequest.name(), createCustomerRequest.isBlack()); - customerRepository.save(customer); + customerRepository.insert(customer); } public List readAll() { diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index 2c353c2caf..ed7df1bfca 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -2,7 +2,6 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; @@ -33,7 +32,7 @@ public class DomainMapper { String voucherTypeStr = resultSet.getString(TYPE_KEY); LocalDateTime createdAt = resultSet.getTimestamp(CREATED_AT_KEY).toLocalDateTime(); - return new Voucher(id, discountValue, VoucherType.valueOf(voucherTypeStr), createdAt); + return new Voucher(id, createdAt, voucherTypeStr, discountValue); }; public final RowMapper customerRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes(ID_KEY)); @@ -74,10 +73,10 @@ public Map uuidToParamMap(UUID id) { public Map voucherToParamMap(Voucher voucher) { Map paramMap = new HashMap<>(); - paramMap.put(ID_KEY, voucher.voucherId().toString().getBytes()); - paramMap.put(TYPE_KEY, voucher.voucherType().name()); - paramMap.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); - paramMap.put(CREATED_AT_KEY, Timestamp.valueOf(voucher.createdAt())); + paramMap.put(ID_KEY, voucher.getId().toString().getBytes()); + paramMap.put(CREATED_AT_KEY, Timestamp.valueOf(voucher.getCreatedAt())); + paramMap.put(TYPE_KEY, voucher.getTypeName()); + paramMap.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); return paramMap; } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 5bf734ee6c..2995f3e974 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -1,7 +1,46 @@ package com.programmers.vouchermanagement.voucher.domain; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; + import java.time.LocalDateTime; import java.util.UUID; -public record Voucher(UUID voucherId, long discountValue, VoucherType voucherType, LocalDateTime createdAt) { +public class Voucher { + private final UUID id; + private final LocalDateTime createdAt; + private VoucherType type; + private long discountValue; + + public Voucher(String typeName, long discountValue) { + id = UUID.randomUUID(); + createdAt = LocalDateTime.now(); + + this.type = VoucherTypeManager.get(typeName); + type.validateDiscountValue(discountValue); + this.discountValue = discountValue; + } + + public Voucher(UUID id, LocalDateTime createdAt, String typeName, long discountValue) { + this.id = id; + this.createdAt = createdAt; + this.type = VoucherTypeManager.get(typeName); + this.discountValue = discountValue; + } + + public String getTypeName() { + return type.getName(); + } + + public UUID getId() { + return id; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public long getDiscountValue() { + return discountValue; + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java deleted file mode 100644 index 257a4c442d..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.programmers.vouchermanagement.voucher.domain; - -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; - -public enum VoucherType { - FIXED("Fixed Amount"), - PERCENT("Percent"); - - private final String typeName; - - VoucherType(String typeName) { - this.typeName = typeName; - } - - public static Optional findCreateMenu(String input) { - return Arrays.stream(VoucherType.values()) - .filter(menu -> menu.isMatching(input)) - .findFirst(); - } - - private boolean isMatching(String input) { - return Objects.equals(this.name().toLowerCase(), input.toLowerCase()); - } - - public boolean isPercent() { - return this == PERCENT; - } - - public String displayTypeName() { - return typeName; - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java new file mode 100644 index 0000000000..33b5ac4846 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java @@ -0,0 +1,28 @@ +package com.programmers.vouchermanagement.voucher.domain.vouchertype; + +import java.text.MessageFormat; + +public class FixedAmountVoucherType extends VoucherType { + private static final String NAME = "FIXED"; + private static final FixedAmountVoucherType INSTANCE = new FixedAmountVoucherType(); + private static final long MAX_DISCOUNT_VALUE = 100000000; + + private FixedAmountVoucherType() { + } + + public static VoucherType getInstance() { + return INSTANCE; + } + + @Override + public void validateDiscountValue(long discountValue) { + if (discountValue < MIN_DISCOUNT_VALUE || discountValue > MAX_DISCOUNT_VALUE) { + throw new IllegalArgumentException(MessageFormat.format("The discount price({0}) is not appropriate at FixedAmountVoucher.", discountValue)); + } + } + + @Override + public String getName() { + return NAME; + } +} \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java new file mode 100644 index 0000000000..eabc2621e7 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java @@ -0,0 +1,28 @@ +package com.programmers.vouchermanagement.voucher.domain.vouchertype; + +import java.text.MessageFormat; + +public class PercentVoucherType extends VoucherType { + private static final String NAME = "PERCENT"; + private static final PercentVoucherType INSTANCE = new PercentVoucherType(); + private static final long MAX_DISCOUNT_VALUE = 100; + + private PercentVoucherType() { + } + + public static VoucherType getInstance() { + return INSTANCE; + } + + @Override + public void validateDiscountValue(long discountValue) { + if (discountValue < MIN_DISCOUNT_VALUE || discountValue > MAX_DISCOUNT_VALUE) { + throw new IllegalArgumentException(MessageFormat.format("The discount price({0}) is not appropriate at PercentVoucher.", discountValue)); + } + } + + @Override + public String getName() { + return NAME; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherType.java new file mode 100644 index 0000000000..aa23bc4d71 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherType.java @@ -0,0 +1,9 @@ +package com.programmers.vouchermanagement.voucher.domain.vouchertype; + +public abstract class VoucherType { + protected static final long MIN_DISCOUNT_VALUE = 0; + + abstract public void validateDiscountValue(long discountValue); + + abstract public String getName(); +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java index ea7cbc840c..1ec7a2a2e1 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.programmers.vouchermanagement.properties.AppProperties; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -16,7 +15,8 @@ import java.time.LocalDateTime; import java.util.*; -import static com.programmers.vouchermanagement.util.Message.*; +import static com.programmers.vouchermanagement.util.Message.FILE_EXCEPTION; +import static com.programmers.vouchermanagement.util.Message.IO_EXCEPTION; @Component @Profile("file") @@ -50,22 +50,17 @@ public void loadFile() { public void loadVouchers(Map[] voucherObjects) { Arrays.stream(voucherObjects).forEach(voucherObject -> { Voucher voucher = objectToVoucher(voucherObject); - vouchers.put(voucher.voucherId(), voucher); + vouchers.put(voucher.getId(), voucher); }); } private Voucher objectToVoucher(Map voucherObject) { UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(VOUCHER_ID_KEY))); - long discountValue = Long.parseLong(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); + LocalDateTime createdAt = (LocalDateTime) voucherObject.get(CREATED_AT_KEY); String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); - VoucherType voucherType = VoucherType.findCreateMenu(voucherTypeName) - .orElseThrow(() -> { - logger.error(INVALID_VOUCHER_TYPE); - return new NoSuchElementException(INVALID_VOUCHER_TYPE); - }); + long discountValue = Long.parseLong(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); //TODO: check save format - LocalDateTime createdAt = (LocalDateTime) voucherObject.get(CREATED_AT_KEY); - return new Voucher(voucherId, discountValue, voucherType, createdAt); + return new Voucher(voucherId, createdAt, voucherTypeName, discountValue); } public void saveFile() { @@ -87,10 +82,10 @@ public void saveFile() { private HashMap voucherToObject(Voucher voucher) { HashMap voucherObject = new HashMap<>(); - voucherObject.put(VOUCHER_ID_KEY, voucher.voucherId().toString()); - voucherObject.put(DISCOUNT_VALUE_KEY, voucher.discountValue()); - voucherObject.put(VOUCHER_TYPE_KEY, voucher.voucherType().name()); - voucherObject.put(CREATED_AT_KEY, voucher.createdAt().toString()); + voucherObject.put(VOUCHER_ID_KEY, voucher.getId().toString()); + voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); + voucherObject.put(VOUCHER_TYPE_KEY, voucher.getTypeName()); + voucherObject.put(CREATED_AT_KEY, voucher.getCreatedAt().toString()); return voucherObject; } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index a1119f9eaa..5b719296b4 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -28,7 +28,7 @@ public VoucherFileRepository(VoucherFileManager voucherFileManager) { @Override public void insert(Voucher voucher) { - voucherFileManager.vouchers.put(voucher.voucherId(), voucher); + voucherFileManager.vouchers.put(voucher.getId(), voucher); voucherFileManager.saveFile(); } @@ -45,7 +45,7 @@ public Optional findById(UUID id) { @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { return voucherFileManager.vouchers.values().stream().filter(voucher -> { - LocalDateTime createdAt = voucher.createdAt(); + LocalDateTime createdAt = voucher.getCreatedAt(); return createdAt.isAfter(from) && createdAt.isBefore(to); }).toList(); } @@ -64,13 +64,13 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - Optional.ofNullable(voucherFileManager.vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); - voucherFileManager.vouchers.put(voucher.voucherId(), voucher); + Optional.ofNullable(voucherFileManager.vouchers.get(voucher.getId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); + voucherFileManager.vouchers.put(voucher.getId(), voucher); voucherFileManager.saveFile(); } @Override public List findAllByType(VoucherType voucherType) { - return voucherFileManager.vouchers.values().stream().filter(voucher -> voucher.voucherType().equals(voucherType)).toList(); + return voucherFileManager.vouchers.values().stream().filter(voucher -> voucher.getTypeName().equals(voucherType.getName())).toList(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index 726750e664..149543e9b3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; @@ -22,7 +22,7 @@ public VoucherInMemoryRepository() { @Override public void insert(Voucher voucher) { - vouchers.put(voucher.voucherId(), voucher); + vouchers.put(voucher.getId(), voucher); } @Override @@ -38,7 +38,7 @@ public Optional findById(UUID id) { @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { return vouchers.values().stream().filter(voucher -> { - LocalDateTime createdAt = voucher.createdAt(); + LocalDateTime createdAt = voucher.getCreatedAt(); return createdAt.isAfter(from) && createdAt.isBefore(to); }).toList(); } @@ -50,18 +50,17 @@ public void delete(UUID id) { @Override public void deleteAll() { - if (!vouchers.isEmpty()) - vouchers.clear(); + if (!vouchers.isEmpty()) vouchers.clear(); } @Override public void update(Voucher voucher) { - Optional.ofNullable(vouchers.get(voucher.voucherId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); - vouchers.put(voucher.voucherId(), voucher); + Optional.ofNullable(vouchers.get(voucher.getId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); + vouchers.put(voucher.getId(), voucher); } @Override public List findAllByType(VoucherType voucherType) { - return vouchers.values().stream().filter(voucher -> voucher.voucherType().equals(voucherType)).toList(); + return vouchers.values().stream().filter(voucher -> voucher.getTypeName().equals(voucherType.getName())).toList(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 4c871e08e6..b5cde4795c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -45,9 +45,7 @@ public List findAll() { @Override public Optional findById(UUID id) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, - Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes()), - domainMapper.voucherRowMapper)); + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes()), domainMapper.voucherRowMapper)); } catch (EmptyResultDataAccessException e) { logger.error(EMPTY_RESULT, e); return Optional.empty(); @@ -56,9 +54,7 @@ public Optional findById(UUID id) { @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { - return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, - Map.of(DomainMapper.FROM_KEY, from.toString(), DomainMapper.TO_KEY, to.toString()), - domainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, Map.of(DomainMapper.FROM_KEY, from.toString(), DomainMapper.TO_KEY, to.toString()), domainMapper.voucherRowMapper); } @Override @@ -84,8 +80,6 @@ public void update(Voucher voucher) { @Override public List findAllByType(VoucherType type) { - return jdbcTemplate.query(FIND_ALL_BY_TYPE, - Map.of(DomainMapper.TYPE_KEY, type.name()), - domainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL_BY_TYPE, Map.of(DomainMapper.TYPE_KEY, type.getName()), domainMapper.voucherRowMapper); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index c90a522b16..b60550a253 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import java.time.LocalDateTime; import java.util.List; diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java index c6eedc255a..0690822243 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java @@ -1,7 +1,6 @@ package com.programmers.vouchermanagement.voucher.repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -19,12 +18,12 @@ class VoucherInMemoryRepositoryTest { @Test @DisplayName("🆗 바우처를 아이디로 삭제할 수 있다.") void deleteVoucherSucceed() { - Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 5555); voucherInMemoryRepository.insert(voucher); - voucherInMemoryRepository.delete(voucher.voucherId()); + voucherInMemoryRepository.delete(voucher.getId()); - assertThat(voucherInMemoryRepository.findById(voucher.voucherId()).isEmpty()).isTrue(); + assertThat(voucherInMemoryRepository.findById(voucher.getId()).isEmpty()).isTrue(); } @Test @@ -38,15 +37,15 @@ void deleteNonExistVoucherFail() { @Test @DisplayName("🆗 바우처를 업데이트 할 수 있다.") void updateVoucherSucceed() { - Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 5555); voucherInMemoryRepository.insert(voucher); - Voucher updatedVoucher = new Voucher(voucher.voucherId(), 100, VoucherType.PERCENT); + Voucher updatedVoucher = new Voucher("PERCENT", 100); voucherInMemoryRepository.update(updatedVoucher); - Optional retrievedVoucher = voucherInMemoryRepository.findById(voucher.voucherId()); + Optional retrievedVoucher = voucherInMemoryRepository.findById(voucher.getId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().discountValue()).isEqualTo(updatedVoucher.discountValue()); - assertThat(retrievedVoucher.get().voucherType()).isEqualTo(updatedVoucher.voucherType()); + assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); + assertThat(retrievedVoucher.get().getTypeName()).isEqualTo(updatedVoucher.getTypeName()); } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index 6cd1a25702..ef4628f662 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -1,9 +1,11 @@ package com.programmers.vouchermanagement.voucher.repository; -import com.programmers.vouchermanagement.TestConfig; +import com.programmers.vouchermanagement.configuration.JdbcConfig; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; @@ -19,7 +21,7 @@ @SpringJUnitConfig @TestInstance(TestInstance.Lifecycle.PER_CLASS) -@ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = JdbcConfig.class, loader = AnnotationConfigContextLoader.class) class VoucherJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); @Autowired @@ -38,32 +40,31 @@ void init() { @Test @DisplayName("🆗 고정 금액 할인 바우처를 추가할 수 있다.") void saveFixedAmountVoucher() { - Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); - voucherJDBCRepository.insert(voucher); + Voucher voucher = new Voucher("FIXED", 1000); - Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().voucherId()).isEqualTo(voucher.voucherId()); + assertThat(retrievedVoucher.get().getId()).isEqualTo(voucher.getId()); } @Test @DisplayName("🆗 퍼센트 할인 바우처를 추가할 수 있다.") void savePercentVoucher() { - Voucher voucher = new Voucher(UUID.randomUUID(), 50, VoucherType.PERCENT); + Voucher voucher = new Voucher("PERCENT", 50); voucherJDBCRepository.insert(voucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().voucherId()).isEqualTo(voucher.voucherId()); + assertThat(retrievedVoucher.get().getId()).isEqualTo(voucher.getId()); } @Test @DisplayName("🆗 모든 바우처를 조회할 수 있다. 단, 없다면 빈 list를 반환한다.") void findAllVoucher() { for (int i = 1; i < 6; i++) - voucherJDBCRepository.insert(new Voucher(UUID.randomUUID(), i * 100, VoucherType.PERCENT)); + voucherJDBCRepository.insert(new Voucher("PERCENT", i * 100)); List vouchers = voucherJDBCRepository.findAll(); @@ -73,15 +74,15 @@ void findAllVoucher() { @Test @DisplayName("🆗 바우처를 아이디로 조회할 수 있다.") void findVoucherById() { - Voucher voucher = new Voucher(UUID.randomUUID(), 1234, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 1234); voucherJDBCRepository.insert(voucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getId()); assertThat(retrievedVoucher.isPresent()).isTrue(); - assertThat(retrievedVoucher.get().voucherId()).isEqualTo(voucher.voucherId()); - assertThat(retrievedVoucher.get().discountValue()).isEqualTo(voucher.discountValue()); - assertThat(retrievedVoucher.get().voucherType()).isEqualTo(voucher.voucherType()); + assertThat(retrievedVoucher.get().getId()).isEqualTo(voucher.getId()); + assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(voucher.getDiscountValue()); + assertThat(retrievedVoucher.get().getTypeName()).isEqualTo(voucher.getTypeName()); } @Test @@ -95,12 +96,12 @@ void findNonExistentVoucherById() { @Test @DisplayName("🆗 바우처를 아이디로 삭제할 수 있다.") void deleteVoucher() { - Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 5555); voucherJDBCRepository.insert(voucher); - voucherJDBCRepository.delete(voucher.voucherId()); + voucherJDBCRepository.delete(voucher.getId()); - assertThat(voucherJDBCRepository.findById(voucher.voucherId()).isEmpty()).isTrue(); + assertThat(voucherJDBCRepository.findById(voucher.getId()).isEmpty()).isTrue(); } @Test @@ -112,21 +113,21 @@ void deleteNonExistentVoucher() { @Test @DisplayName("🆗 바우처를 업데이트 할 수 있다.") void updateVoucher() { - Voucher voucher = new Voucher(UUID.randomUUID(), 5555, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 5555); voucherJDBCRepository.insert(voucher); - Voucher updatedVoucher = new Voucher(voucher.voucherId(), 100, VoucherType.PERCENT); + Voucher updatedVoucher = new Voucher(voucher.getId(), voucher.getCreatedAt(), "PERCENT", 100); voucherJDBCRepository.update(updatedVoucher); - Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.voucherId()); + Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getId()); assertThat(retrievedVoucher.isEmpty()).isFalse(); - assertThat(retrievedVoucher.get().discountValue()).isEqualTo(updatedVoucher.discountValue()); - assertThat(retrievedVoucher.get().voucherType()).isEqualTo(updatedVoucher.voucherType()); - } - - @Test - @DisplayName("🚨 해당하는 바우처가 없다면, 바우처를 업데이트 할 수 없다.") - void updateNonExistentVoucher() { - assertThrows(RuntimeException.class, () -> voucherJDBCRepository.update(new Voucher(NON_EXISTENT_VOUCHER_ID, 100, VoucherType.PERCENT))); + assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); + assertThat(retrievedVoucher.get().getTypeName()).isEqualTo(updatedVoucher.getTypeName()); } +// +// @Test +// @DisplayName("🚨 해당하는 바우처가 없다면, 바우처를 업데이트 할 수 없다.") +// void updateNonExistentVoucher() { +// assertThrows(RuntimeException.class, () -> voucherJDBCRepository.update(new Voucher(NON_EXISTENT_VOUCHER_ID, "PERCENT", 100))); +// } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 4eb2b95f08..89401cd6d4 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -1,7 +1,6 @@ package com.programmers.vouchermanagement.voucher.service; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.junit.jupiter.api.DisplayName; @@ -40,7 +39,7 @@ void initTest() { @Test @DisplayName("고정 할인 금액 바우처 객체를 생성할 수 있다.") void createFixedAmountVoucherSucceed() { - CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(1000, VoucherType.FIXED); + CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest("FIXED", 1000); voucherService.create(createVoucherRequest); verify(voucherRepository, times(1)).insert(any(Voucher.class)); @@ -49,7 +48,7 @@ void createFixedAmountVoucherSucceed() { @Test @DisplayName("퍼센트 할인 바우처 객체를 생성할 수 있다.") void createPercentDiscountVoucherSucceed() { - CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest(100, VoucherType.PERCENT); + CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest("PERCENT", 100); voucherService.create(createVoucherRequest); verify(voucherRepository, times(1)).insert(any(Voucher.class)); @@ -83,11 +82,11 @@ void deleteVoucherSucceed() { verify(voucherRepository, times(1)).delete(any(UUID.class)); } - @Test - @DisplayName("바우처를 업데이트할 수 있다.") - void updateVoucherSucceed() { - voucherService.update(new Voucher(UUID.randomUUID(), 100, VoucherType.FIXED)); - - verify(voucherRepository, times(1)).update(any(Voucher.class)); - } +// @Test +// @DisplayName("바우처를 업데이트할 수 있다.") +// void updateVoucherSucceed() { +// voucherService.update(new Voucher("FIXED", 100)); +// +// verify(voucherRepository, times(1)).update(any(Voucher.class)); +// } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index 4359c56f29..b26c8253a3 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -1,10 +1,9 @@ package com.programmers.vouchermanagement.wallet.repository; -import com.programmers.vouchermanagement.TestConfig; +import com.programmers.vouchermanagement.configuration.JdbcConfig; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerJDBCRepository; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.repository.VoucherJDBCRepository; import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.junit.jupiter.api.*; @@ -24,7 +23,7 @@ @SpringJUnitConfig @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) -@ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = JdbcConfig.class, loader = AnnotationConfigContextLoader.class) class WalletJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); private final static UUID NON_EXISTENT_CUSTOMER_ID = UUID.randomUUID(); @@ -47,61 +46,58 @@ void init() { jdbcTemplate.execute("TRUNCATE TABLE test.customers"); jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); } + @Test @Order(1) @DisplayName("🆗 의존성 주입 테스트.") void injectionTest() { - assertAll( - () -> assertThat(walletJDBCRepository).isNotNull(), - () -> assertThat(voucherJDBCRepository).isNotNull(), - () -> assertThat(customerJDBCRepository).isNotNull() - ); + assertAll(() -> assertThat(walletJDBCRepository).isNotNull(), () -> assertThat(voucherJDBCRepository).isNotNull(), () -> assertThat(customerJDBCRepository).isNotNull()); } @Test @DisplayName("🆗 고객에게 바우처를 할당할 수 있다.") void save() { - Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 333); voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처 주인"); - customerJDBCRepository.save(customer); + customerJDBCRepository.insert(customer); - Ownership newOwnership = new Ownership(voucher.voucherId(), customer.getCustomerId()); + Ownership newOwnership = new Ownership(voucher.getId(), customer.getId()); walletJDBCRepository.insert(newOwnership); } @Test @DisplayName("🚨 이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") void saveAllocatedVoucher() { - Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 333); voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처를 가진 고객"); - customerJDBCRepository.save(customer); + customerJDBCRepository.insert(customer); - walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); Customer customer2 = new Customer(UUID.randomUUID(), "바우처를 가지지 못하는 고객"); - customerJDBCRepository.save(customer2); + customerJDBCRepository.insert(customer2); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer2.getCustomerId()))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(voucher.getId(), customer2.getId()))); } @Test @DisplayName("🚨 고객 id에 해당하는 고객이 없다면, 고객에게 바우처를 할당할 수 없다.") void saveNonExistentCustomer() { - Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 333); voucherJDBCRepository.insert(voucher); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(voucher.voucherId(), NON_EXISTENT_CUSTOMER_ID))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(voucher.getId(), NON_EXISTENT_CUSTOMER_ID))); } @Test @DisplayName("🚨 바우처 id에 해당하는 바우처가 없다면, 바우처를 고객에게 할당할 수 없다.") void saveNonExistentVoucher() { Customer customer = new Customer(UUID.randomUUID(), "바우처를 가지지 못한 고객"); - customerJDBCRepository.save(customer); + customerJDBCRepository.insert(customer); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(NON_EXISTENT_VOUCHER_ID, customer.getCustomerId()))); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(NON_EXISTENT_VOUCHER_ID, customer.getId()))); } @Test @@ -114,16 +110,16 @@ void saveNonExistentBoth() { @DisplayName("🆗 고객 id로 고객이 가진 바우처들을 가져올 수 있다.") void findAllVoucherByCustomerId() { Customer customer = new Customer(UUID.randomUUID(), "조회하려는 바우처들의 주인"); - customerJDBCRepository.save(customer); + customerJDBCRepository.insert(customer); for (int i = 1; i < 6; i++) { - Voucher voucher = new Voucher(UUID.randomUUID(), i, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", i); voucherJDBCRepository.insert(voucher); - walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); } // If the customer don't have any voucher, then return empty list. - assertThat(walletJDBCRepository.findAllVoucherByCustomerId(customer.getCustomerId()).isEmpty()).isFalse(); + assertThat(walletJDBCRepository.findAllVoucherByCustomerId(customer.getId()).isEmpty()).isFalse(); } @Test @@ -135,42 +131,42 @@ void findAllVoucherByNonExistentCustomerId() { @Test @DisplayName("🆗 바우처 id를 통해 할당 정보를 삭제할 수 있다. 단, 바우처 자체는 삭제되지 않는다.") void delete() { - Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 333); voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "1개의 삭제될 바우처를 가진 주인"); - customerJDBCRepository.save(customer); + customerJDBCRepository.insert(customer); - walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); - walletJDBCRepository.delete(voucher.voucherId()); + walletJDBCRepository.delete(voucher.getId()); - assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()).isEmpty()).isTrue(); - assertThat(voucherJDBCRepository.findById(voucher.voucherId()).isPresent()).isTrue(); + assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getId()).isEmpty()).isTrue(); + assertThat(voucherJDBCRepository.findById(voucher.getId()).isPresent()).isTrue(); } @Test @DisplayName("🚨 바우처에 대한 할당 정보가 없다면, 함께 저장된 고객 id와 바우처 id 정보를 삭제할 수 없다.") void deleteNonAllocatedVoucher() { - Voucher voucher = new Voucher(UUID.randomUUID(), 333, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 333); voucherJDBCRepository.insert(voucher); - assertThrows(RuntimeException.class, () -> walletJDBCRepository.delete(voucher.voucherId())); + assertThrows(RuntimeException.class, () -> walletJDBCRepository.delete(voucher.getId())); } @Test @DisplayName("🆗 바우처 id로 바우처를 가진 고객 정보를 가져올 수 있다.") void findCustomerByVoucherId() { - Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 555); voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "조회될 고객"); - customerJDBCRepository.save(customer); + customerJDBCRepository.insert(customer); - walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); - Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()); + Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.getId()); assertThat(retrievedCustomer.isPresent()).isTrue(); - assertThat(retrievedCustomer.get().getCustomerId()).isEqualTo(customer.getCustomerId()); + assertThat(retrievedCustomer.get().getId()).isEqualTo(customer.getId()); } @Test @@ -182,15 +178,15 @@ void findCustomerByNonExistentVoucherId() { @Test @DisplayName("🆗 바우처 자체를 삭제하면, 바우처 소유 정보가 사라진다.") void autoDeleteAfterVoucherDelete() { - Voucher voucher = new Voucher(UUID.randomUUID(), 555, VoucherType.FIXED); + Voucher voucher = new Voucher("FIXED", 555); voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "삭제될 바우처를 가진 고객"); - customerJDBCRepository.save(customer); + customerJDBCRepository.insert(customer); - walletJDBCRepository.insert(new Ownership(voucher.voucherId(), customer.getCustomerId())); + walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); - voucherJDBCRepository.delete(voucher.voucherId()); + voucherJDBCRepository.delete(voucher.getId()); - assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.voucherId()).isEmpty()).isTrue(); + assertThat(walletJDBCRepository.findCustomerByVoucherId(voucher.getId()).isEmpty()).isTrue(); } } From 4b2f50f52b88cbf49bf1497d42f5f7a2328b669a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 22:57:55 +0900 Subject: [PATCH 301/383] refactor: refactor CreateVoucherRequest construct argument order --- .../vouchermanagement/voucher/dto/CreateVoucherRequest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java index 6868664618..d1599d18b7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java @@ -1,6 +1,4 @@ package com.programmers.vouchermanagement.voucher.dto; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; - -public record CreateVoucherRequest(long discountValue, VoucherType voucherType) { +public record CreateVoucherRequest(String typeName, long discountValue) { } From c788b5ea5bd2f414350d5d91b6c7bb4f663fabd2 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 23:10:32 +0900 Subject: [PATCH 302/383] chore: add "drop DATABASE if exists *" query --- src/main/resources/schema.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index c3dee17095..23b8ede2e7 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,3 +1,4 @@ +drop DATABASE if exists prod; CREATE DATABASE prod; use prod; CREATE TABLE customers @@ -7,7 +8,6 @@ CREATE TABLE customers black boolean not null, CONSTRAINT name UNIQUE (name) ); - CREATE TABLE vouchers ( id BINARY(16) PRIMARY KEY, @@ -23,7 +23,7 @@ CREATE TABLE ownership FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE ); - +drop DATABASE if exists test; CREATE DATABASE test; use test; CREATE TABLE customers From ec70b009a9fd4f67601c37d89655d9b294b530c8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 23:41:29 +0900 Subject: [PATCH 303/383] refactor: fix query --- .../customer/repository/CustomerQuery.java | 7 ++++--- .../voucher/repository/VoucherQuery.java | 16 ++++++++-------- .../wallet/repository/WalletQuery.java | 10 +++++----- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java index 50926e39e5..42cf510f73 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java @@ -1,9 +1,10 @@ package com.programmers.vouchermanagement.customer.repository; public class CustomerQuery { - public static final String FIND_ALL_BLACK_CUSTOMER = "SELECT * FROM test.customers WHERE black = TRUE"; - public static final String INSERT = "INSERT INTO test.customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; - public static final String FIND_ALL = "SELECT * FROM test.customers"; + public static final String FIND_ALL_BLACK_CUSTOMER = "SELECT * FROM customers WHERE black = TRUE"; + public static final String INSERT = "INSERT INTO customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; + public static final String FIND_ALL = "SELECT * FROM customers"; + private CustomerQuery() { } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java index 5f73cd9905..9a2786157a 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java @@ -1,14 +1,14 @@ package com.programmers.vouchermanagement.voucher.repository; public class VoucherQuery { - public static final String INSERT = "INSERT INTO test.vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discount_value)"; - public static final String FIND_BY_ID = "SELECT * FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; - public static final String FIND_ALL = "SELECT * FROM test.vouchers"; - public static final String FIND_ALL_BY_CREATED_AT = "SELECT * FROM test.vouchers WHERE created_at BETWEEN DATE(:from) AND DATE(:to)"; - public static final String FIND_ALL_BY_TYPE = "SELECT * FROM test.vouchers WHERE type = :type"; - public static final String DELETE_VOUCHER = "DELETE FROM test.vouchers WHERE id = UUID_TO_BIN(:id)"; - public static final String DELETE_ALL = "DELETE FROM test.vouchers"; - public static final String UPDATE_VOUCHER = "UPDATE test.vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; + public static final String INSERT = "INSERT INTO vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discount_value)"; + public static final String FIND_BY_ID = "SELECT * FROM vouchers WHERE id = UUID_TO_BIN(:id)"; + public static final String FIND_ALL = "SELECT * FROM vouchers"; + public static final String FIND_ALL_BY_CREATED_AT = "SELECT * FROM vouchers WHERE created_at BETWEEN DATE(:from) AND DATE(:to)"; + public static final String FIND_ALL_BY_TYPE = "SELECT * FROM vouchers WHERE type = :type"; + public static final String DELETE_VOUCHER = "DELETE FROM vouchers WHERE id = UUID_TO_BIN(:id)"; + public static final String DELETE_ALL = "DELETE FROM vouchers"; + public static final String UPDATE_VOUCHER = "UPDATE vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; private VoucherQuery() { } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java index 0d06755ac6..a5065c9b82 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java @@ -1,11 +1,11 @@ package com.programmers.vouchermanagement.wallet.repository; public class WalletQuery { - public static final String INSERT = "INSERT INTO test.ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucher_id), UUID_TO_BIN(:customer_id))"; - public static final String DELETE_OWNERSHIP = "DELETE FROM test.ownership WHERE voucher_id = UUID_TO_BIN(:id)"; - public static final String DELETE_ALL = "TRUNCATE TABLE test.ownership"; - public static final String FIND_CUSTOMER_BY_VOUCHER_ID = "SELECT c.* FROM test.ownership as o JOIN test.customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)"; - public static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID = "SELECT v.* FROM test.ownership as o JOIN test.vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)"; + public static final String INSERT = "INSERT INTO ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucher_id), UUID_TO_BIN(:customer_id))"; + public static final String DELETE_OWNERSHIP = "DELETE FROM ownership WHERE voucher_id = UUID_TO_BIN(:id)"; + public static final String DELETE_ALL = "TRUNCATE TABLE ownership"; + public static final String FIND_CUSTOMER_BY_VOUCHER_ID = "SELECT c.* FROM ownership as o JOIN customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)"; + public static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID = "SELECT v.* FROM ownership as o JOIN vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)"; private WalletQuery() { } } From 99269c97915184083f7c04d2d7adf43ac020f4d0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 23:41:43 +0900 Subject: [PATCH 304/383] refactor: fix value name --- src/main/resources/templates/voucher/voucher-detail.html | 2 +- src/main/resources/templates/voucher/voucher-new.html | 2 +- src/main/resources/templates/voucher/voucher-update.html | 4 ++-- src/main/resources/templates/voucher/vouchers.html | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/templates/voucher/voucher-detail.html b/src/main/resources/templates/voucher/voucher-detail.html index 66966cec7d..d4497aff8e 100644 --- a/src/main/resources/templates/voucher/voucher-detail.html +++ b/src/main/resources/templates/voucher/voucher-detail.html @@ -15,7 +15,7 @@

Voucher Id

diff --git a/src/main/resources/templates/voucher/voucher-new.html b/src/main/resources/templates/voucher/voucher-new.html index e8a7e17ad8..8929a62feb 100644 --- a/src/main/resources/templates/voucher/voucher-new.html +++ b/src/main/resources/templates/voucher/voucher-new.html @@ -14,7 +14,7 @@

Vouchers

New Voucher

- diff --git a/src/main/resources/templates/voucher/voucher-update.html b/src/main/resources/templates/voucher/voucher-update.html index 01dd59e861..ba1c1c2d46 100644 --- a/src/main/resources/templates/voucher/voucher-update.html +++ b/src/main/resources/templates/voucher/voucher-update.html @@ -14,9 +14,9 @@

Vouchers

New Voucher

- - + diff --git a/src/main/resources/templates/voucher/vouchers.html b/src/main/resources/templates/voucher/vouchers.html index 84807a6916..2067a097a1 100644 --- a/src/main/resources/templates/voucher/vouchers.html +++ b/src/main/resources/templates/voucher/vouchers.html @@ -28,7 +28,7 @@

Voucher List

- +
Detail Update From f3849405d5968048c46b986536b9e635f72707ec Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 23:41:54 +0900 Subject: [PATCH 305/383] refactor: remove useless class --- .../CustomerInMemoryRepository.java | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java deleted file mode 100644 index d528b7e40f..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerInMemoryRepository.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.programmers.vouchermanagement.customer.repository; - -import com.programmers.vouchermanagement.customer.domain.Customer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Repository; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -@Repository -@Profile("memory") -public class CustomerInMemoryRepository implements CustomerRepository { - private static final Logger logger = LoggerFactory.getLogger(CustomerInMemoryRepository.class); - private final Map customers; - - public CustomerInMemoryRepository() { - customers = new HashMap<>(); - } - - @Override - public void insert(Customer customer) { - customers.put(customer.getId(), customer); - } - - @Override - public List findAll() { - return customers.values().stream().toList(); - } - - @Override - public List findAllBlackCustomer() { - return customers.values() - .stream() - .filter(Customer::isBlack) - .toList(); - } -} \ No newline at end of file From 5e7c086e4087bac4945579fecae1b767d07fe618 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 23:42:10 +0900 Subject: [PATCH 306/383] refactor: add memory property at CustomerFileRepository --- .../customer/repository/CustomerFileRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 88dc7377e7..2f61a05e0a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -9,7 +9,7 @@ import java.util.List; @Repository -@Profile("file") +@Profile({"file", "memory"}) public class CustomerFileRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerFileRepository.class); private final CustomerFileManager customerFileManager; From a3aa8283f08a0079096f62e51f9b67db5c2bb262 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 5 Nov 2023 23:42:43 +0900 Subject: [PATCH 307/383] refactor: apply specific exception --- .../voucher/repository/VoucherFileRepository.java | 5 +++-- .../voucher/repository/VoucherInMemoryRepository.java | 4 ++-- .../voucher/repository/VoucherJDBCRepository.java | 4 ++-- .../wallet/repository/WalletJDBCRepository.java | 7 ++----- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 5b719296b4..03c6aae6c2 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -9,6 +9,7 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.UUID; @@ -52,7 +53,7 @@ public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { @Override public void delete(UUID id) { - Optional.ofNullable(voucherFileManager.vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); + Optional.ofNullable(voucherFileManager.vouchers.remove(id)).orElseThrow(() -> new NoSuchElementException(NOT_DELETED)); voucherFileManager.saveFile(); } @@ -64,7 +65,7 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - Optional.ofNullable(voucherFileManager.vouchers.get(voucher.getId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); + Optional.ofNullable(voucherFileManager.vouchers.get(voucher.getId())).orElseThrow(() -> new NoSuchElementException(NOT_UPDATED)); voucherFileManager.vouchers.put(voucher.getId(), voucher); voucherFileManager.saveFile(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index 149543e9b3..74941c2dae 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -45,7 +45,7 @@ public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { @Override public void delete(UUID id) { - Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new RuntimeException(NOT_DELETED)); + Optional.ofNullable(vouchers.remove(id)).orElseThrow(() -> new NoSuchElementException(NOT_DELETED)); } @Override @@ -55,7 +55,7 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - Optional.ofNullable(vouchers.get(voucher.getId())).orElseThrow(() -> new RuntimeException(NOT_UPDATED)); + Optional.ofNullable(vouchers.get(voucher.getId())).orElseThrow(() -> new NoSuchElementException(NOT_UPDATED)); vouchers.put(voucher.getId(), voucher); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index b5cde4795c..dbac25e840 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -61,7 +61,7 @@ public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { public void delete(UUID id) { int update = jdbcTemplate.update(DELETE_VOUCHER, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes())); if (update != UPDATE_ONE_FLAG) { - throw new RuntimeException(NOT_DELETED); + throw new NoSuchElementException(NOT_DELETED); } } @@ -74,7 +74,7 @@ public void deleteAll() { public void update(Voucher voucher) { int update = jdbcTemplate.update(UPDATE_VOUCHER, domainMapper.voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { - throw new RuntimeException(NOT_UPDATED); + throw new NoSuchElementException(NOT_UPDATED); } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 0f46b3b6ca..6e21bf0bd2 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -10,10 +10,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ZERO_FLAG; @@ -63,7 +60,7 @@ public void delete(UUID voucherId) { int update = jdbcTemplate.update(DELETE_OWNERSHIP, domainMapper.uuidToParamMap(voucherId)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_FOUND_VOUCHER_ALLOCATION); - throw new RuntimeException(NOT_FOUND_VOUCHER_ALLOCATION); + throw new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); } } From 18125b90e85de8d6e620e6ae82d1b94ec696213d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:17:24 +0900 Subject: [PATCH 308/383] refactor: apply discount value validator at view --- .../templates/voucher/voucher-new.html | 17 ++++++++++++++--- .../templates/voucher/voucher-update.html | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/main/resources/templates/voucher/voucher-new.html b/src/main/resources/templates/voucher/voucher-new.html index 8929a62feb..b7d7930f7a 100644 --- a/src/main/resources/templates/voucher/voucher-new.html +++ b/src/main/resources/templates/voucher/voucher-new.html @@ -14,14 +14,25 @@

Vouchers

New Voucher

- - +
+ \ No newline at end of file diff --git a/src/main/resources/templates/voucher/voucher-update.html b/src/main/resources/templates/voucher/voucher-update.html index ba1c1c2d46..310a1a8013 100644 --- a/src/main/resources/templates/voucher/voucher-update.html +++ b/src/main/resources/templates/voucher/voucher-update.html @@ -11,18 +11,29 @@

Vouchers

-

New Voucher

+

- + aria-label="Discount Value" name="discountValue" id="discountValue" th:value="${voucher.discountValue}">
Cancel
+ \ No newline at end of file From 902a497ffa1f0b59799b1643ccdcad3444a364ad Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:17:45 +0900 Subject: [PATCH 309/383] refactor: set code format --- .../voucher/domain/vouchertype/FixedAmountVoucherType.java | 2 +- .../voucher/domain/vouchertype/PercentVoucherType.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java index 33b5ac4846..a05edaa634 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherType.java @@ -16,7 +16,7 @@ public static VoucherType getInstance() { @Override public void validateDiscountValue(long discountValue) { - if (discountValue < MIN_DISCOUNT_VALUE || discountValue > MAX_DISCOUNT_VALUE) { + if (discountValue < MIN_DISCOUNT_VALUE || MAX_DISCOUNT_VALUE < discountValue) { throw new IllegalArgumentException(MessageFormat.format("The discount price({0}) is not appropriate at FixedAmountVoucher.", discountValue)); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java index eabc2621e7..5ce616308d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherType.java @@ -16,7 +16,7 @@ public static VoucherType getInstance() { @Override public void validateDiscountValue(long discountValue) { - if (discountValue < MIN_DISCOUNT_VALUE || discountValue > MAX_DISCOUNT_VALUE) { + if (discountValue < MIN_DISCOUNT_VALUE || MAX_DISCOUNT_VALUE < discountValue) { throw new IllegalArgumentException(MessageFormat.format("The discount price({0}) is not appropriate at PercentVoucher.", discountValue)); } } From 9404942411b3048568b14e59fb88fe45b9d0d95a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:23:26 +0900 Subject: [PATCH 310/383] fix: add voucher validator at another constructor and apply --- .../programmers/vouchermanagement/voucher/domain/Voucher.java | 1 + .../vouchermanagement/voucher/service/VoucherService.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 2995f3e974..adf05eef33 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -25,6 +25,7 @@ public Voucher(UUID id, LocalDateTime createdAt, String typeName, long discountV this.id = id; this.createdAt = createdAt; this.type = VoucherTypeManager.get(typeName); + type.validateDiscountValue(discountValue); this.discountValue = discountValue; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 807a5debc2..5fb45ea717 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -25,7 +25,7 @@ public VoucherService(VoucherRepository voucherRepository) { public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { //TODO: now? DB vs Application - Voucher voucher = new Voucher(UUID.randomUUID(), LocalDateTime.now(), createVoucherRequest.typeName(), createVoucherRequest.discountValue()); + Voucher voucher = new Voucher(createVoucherRequest.typeName(), createVoucherRequest.discountValue()); voucherRepository.insert(voucher); return VoucherResponse.from(voucher); } From 4e365c3901a444938a4424808c5eddd02f1f2cca Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:31:01 +0900 Subject: [PATCH 311/383] fix: add customer validator at customer and apply --- .../programmers/vouchermanagement/customer/domain/Customer.java | 2 ++ src/main/resources/templates/customer/customer-new.html | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 5aefd771e3..7c20344335 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -12,6 +12,8 @@ public Customer(UUID id, String name) { } public Customer(UUID id, String name, boolean black) { + if (name.isBlank() || name.length() > 20) + throw new IllegalArgumentException("The name length should be between 0 to 20."); this.id = id; this.name = name; this.black = black; diff --git a/src/main/resources/templates/customer/customer-new.html b/src/main/resources/templates/customer/customer-new.html index d1819050e0..37ff0ab04d 100644 --- a/src/main/resources/templates/customer/customer-new.html +++ b/src/main/resources/templates/customer/customer-new.html @@ -15,7 +15,7 @@

New Customer

- +
From 23312dd245b35e6ed824a3039be5597dee09ad03 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:32:13 +0900 Subject: [PATCH 312/383] refactor: change CustomerDto to CustomerResponse and apply --- .../consoleapp/io/ConsoleManager.java | 6 +++--- .../consoleapp/menu/MenuHandler.java | 5 ++--- .../customer/controller/CustomerController.java | 6 +++--- .../vouchermanagement/customer/dto/CustomerDto.java | 11 ----------- .../customer/dto/CustomerResponse.java | 11 +++++++++++ .../customer/service/CustomerService.java | 10 +++++----- .../wallet/controller/WalletController.java | 4 ++-- .../wallet/controller/WalletThymeleafController.java | 4 ++-- .../wallet/service/WalletService.java | 6 +++--- 9 files changed, 31 insertions(+), 32 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerResponse.java diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 77530b2219..fb44db055f 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.consoleapp.io; import com.programmers.vouchermanagement.consoleapp.menu.Menu; -import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; @@ -86,14 +86,14 @@ public void printReadAllVouchers(List vouchers) { vouchers.forEach(voucher -> textIO.getTextTerminal().println(formatVoucherDTO(voucher))); } - public void printReadBlacklist(List customers) { + public void printReadBlacklist(List customers) { if (customers.isEmpty()) { textIO.getTextTerminal().println(NO_CONTENT.formatted("black customer")); } customers.forEach(customer -> textIO.getTextTerminal().println(formatCustomer(customer))); } - private String formatCustomer(CustomerDto customer) { + private String formatCustomer(CustomerResponse customer) { return """ Customer ID : %s Customer Name : %s diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 3045ccdad2..39171a7d2b 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; import com.programmers.vouchermanagement.customer.controller.CustomerController; -import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.controller.VoucherController; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; @@ -74,9 +74,8 @@ private void executeMenu(Menu menu) { List vouchers = voucherController.readAll(); consoleManager.printReadAllVouchers(vouchers); } - //TODO: customerDTO case BLACKLIST -> { - List blackCustomers = customerController.readAllBlackCustomer(); + List blackCustomers = customerController.readAllBlackCustomer(); consoleManager.printReadBlacklist(blackCustomers); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 6a853d264a..eeef165369 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.customer.controller; import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; -import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.service.CustomerService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; @@ -30,13 +30,13 @@ public void create(CreateCustomerRequest createCustomerRequest) { @GetMapping @ResponseBody - public List readAll() { + public List readAll() { return customerService.readAll(); } @GetMapping("/blacklist") @ResponseBody - public List readAllBlackCustomer() { + public List readAllBlackCustomer() { return customerService.readAllBlackCustomer(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java b/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java deleted file mode 100644 index c9a10eef42..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.programmers.vouchermanagement.customer.dto; - -import com.programmers.vouchermanagement.customer.domain.Customer; - -import java.util.UUID; - -public record CustomerDto(UUID id, String name, boolean isBlack) { - public static CustomerDto from(Customer customer) { - return new CustomerDto(customer.getId(), customer.getName(), customer.isBlack()); - } -} \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerResponse.java b/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerResponse.java new file mode 100644 index 0000000000..091d29c295 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerResponse.java @@ -0,0 +1,11 @@ +package com.programmers.vouchermanagement.customer.dto; + +import com.programmers.vouchermanagement.customer.domain.Customer; + +import java.util.UUID; + +public record CustomerResponse(UUID id, String name, boolean isBlack) { + public static CustomerResponse from(Customer customer) { + return new CustomerResponse(customer.getId(), customer.getName(), customer.isBlack()); + } +} \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 78db0f04f9..156001f8d7 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -2,7 +2,7 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; -import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import org.springframework.stereotype.Service; @@ -23,19 +23,19 @@ public void create(CreateCustomerRequest createCustomerRequest) { customerRepository.insert(customer); } - public List readAll() { + public List readAll() { List customers = customerRepository.findAll(); if (customers.isEmpty()) { return Collections.emptyList(); } - return customers.stream().map(CustomerDto::from).toList(); + return customers.stream().map(CustomerResponse::from).toList(); } - public List readAllBlackCustomer() { + public List readAllBlackCustomer() { List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { return Collections.emptyList(); } - return blacklist.stream().map(CustomerDto::from).toList(); + return blacklist.stream().map(CustomerResponse::from).toList(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java index db0d93e636..dba7ea2cc8 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java @@ -1,6 +1,6 @@ package com.programmers.vouchermanagement.wallet.controller; -import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.service.WalletService; @@ -24,7 +24,7 @@ public void allocate(Ownership ownership) { walletService.allocate(ownership); } - public CustomerDto readCustomerByVoucherId(UUID voucherId, Model model) { + public CustomerResponse readCustomerByVoucherId(UUID voucherId, Model model) { return walletService.readCustomerByVoucherId(voucherId); } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java index 68642b3809..e6564b8bd0 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java @@ -1,6 +1,6 @@ package com.programmers.vouchermanagement.wallet.controller; -import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.service.WalletService; @@ -29,7 +29,7 @@ public void allocate(Ownership ownership) { @GetMapping("/vouchers/{voucherId}") public String readCustomerByVoucherId(@PathVariable("voucherId") UUID voucherId, Model model) { - CustomerDto customer = walletService.readCustomerByVoucherId(voucherId); + CustomerResponse customer = walletService.readCustomerByVoucherId(voucherId); model.addAttribute("customers", List.of(customer)); return "views/customers"; } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index 2ad685ece3..8bc53d0651 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.wallet.service; import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.customer.dto.CustomerDto; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; @@ -30,12 +30,12 @@ public void allocate(Ownership ownership) { walletRepository.insert(ownership); } - public CustomerDto readCustomerByVoucherId(UUID voucherId) { + public CustomerResponse readCustomerByVoucherId(UUID voucherId) { Customer customer = walletRepository.findCustomerByVoucherId(voucherId).orElseThrow(() -> { logger.error(NOT_FOUND_VOUCHER_ALLOCATION); return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); }); - return CustomerDto.from(customer); + return CustomerResponse.from(customer); } public List readAllVoucherByCustomerId(UUID customerId) { From 056740c6e23124ba1e7aeae6c2bcfebe4a49b7c1 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:38:29 +0900 Subject: [PATCH 313/383] enhance: apply EmptyResultDataAccessException ay *JDBCRepository --- .../customer/repository/CustomerJDBCRepository.java | 3 ++- .../voucher/repository/VoucherJDBCRepository.java | 2 +- .../wallet/repository/WalletJDBCRepository.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index d5a84b43a1..951e276d8f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -31,7 +32,7 @@ public void insert(Customer customer) { int update = jdbcTemplate.update(INSERT, domainMapper.customerToParamMap(customer)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_INSERTED); - throw new RuntimeException(NOT_INSERTED); + throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index dbac25e840..e2abdfe371 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -33,7 +33,7 @@ public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapp public void insert(Voucher voucher) { int update = jdbcTemplate.update(INSERT, domainMapper.voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { - throw new RuntimeException(NOT_INSERTED); + throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 6e21bf0bd2..4b6ccb6696 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -33,7 +33,7 @@ public void insert(Ownership ownership) { int update = jdbcTemplate.update(INSERT, domainMapper.ownershipToParamMap(ownership)); if (update != UPDATE_ONE_FLAG) { logger.error(CAN_NOT_INSERT_OWNERSHIP); - throw new RuntimeException(CAN_NOT_INSERT_OWNERSHIP); + throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); } } From 601d360992ee2e431bc2c1fe25749c6f793545f9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:45:32 +0900 Subject: [PATCH 314/383] fix: fix readAllByType logic --- .../voucher/controller/VoucherController.java | 4 ++-- .../vouchermanagement/voucher/service/VoucherService.java | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 84ad775cee..645577c8d0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -70,7 +70,7 @@ public List readAllByCreatedAt(@RequestParam(name = "from") Loc @GetMapping("type/{type}") @ResponseBody - public List readAllByType(@PathVariable("type") VoucherType type) { - return voucherService.readAllByType(type); + public List readAllByType(@PathVariable("type") String typeName) { + return voucherService.readAllByType(typeName); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 5fb45ea717..bd59edf4c8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -2,6 +2,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; @@ -77,7 +78,8 @@ public VoucherResponse update(UUID voucherId, CreateVoucherRequest createVoucher return VoucherResponse.from(voucher); } - public List readAllByType(VoucherType type) { - return voucherRepository.findAllByType(type).stream().map(VoucherResponse::from).toList(); + public List readAllByType(String typeName) { + VoucherType voucherType = VoucherTypeManager.get(typeName); + return voucherRepository.findAllByType(voucherType).stream().map(VoucherResponse::from).toList(); } } From 62f93aa1915131b16766119374d77bdc6d9f5a88 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 00:45:32 +0900 Subject: [PATCH 315/383] refactor: make DomainMapper to util class --- .../repository/CustomerJDBCRepository.java | 10 ++++------ .../vouchermanagement/util/DomainMapper.java | 14 ++++++-------- .../voucher/controller/VoucherController.java | 4 ++-- .../repository/VoucherJDBCRepository.java | 16 +++++++--------- .../voucher/service/VoucherService.java | 6 ++++-- .../wallet/repository/WalletJDBCRepository.java | 12 +++++------- 6 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 951e276d8f..229f7b31ff 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -20,16 +20,14 @@ public class CustomerJDBCRepository implements CustomerRepository { private static final Logger logger = LoggerFactory.getLogger(CustomerJDBCRepository.class); private final NamedParameterJdbcTemplate jdbcTemplate; - private final DomainMapper domainMapper; - public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapper domainMapper) { + public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; - this.domainMapper = domainMapper; } @Override public void insert(Customer customer) { - int update = jdbcTemplate.update(INSERT, domainMapper.customerToParamMap(customer)); + int update = jdbcTemplate.update(INSERT, DomainMapper.customerToParamMap(customer)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_INSERTED); throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); @@ -38,12 +36,12 @@ public void insert(Customer customer) { @Override public List findAllBlackCustomer() { - return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, domainMapper.customerRowMapper); + return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, DomainMapper.customerRowMapper); } @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL, domainMapper.customerRowMapper); + return jdbcTemplate.query(FIND_ALL, DomainMapper.customerRowMapper); } } diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index ed7df1bfca..b654ef36ba 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -4,7 +4,6 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.springframework.jdbc.core.RowMapper; -import org.springframework.stereotype.Component; import java.nio.ByteBuffer; import java.sql.Timestamp; @@ -13,7 +12,6 @@ import java.util.Map; import java.util.UUID; -@Component public class DomainMapper { //TODO: split public static final String ID_KEY = "id"; @@ -26,7 +24,7 @@ public class DomainMapper { public static final String CREATED_AT_KEY = "created_at"; public static final String FROM_KEY = "from"; public static final String TO_KEY = "to"; - public final RowMapper voucherRowMapper = (resultSet, i) -> { + public static final RowMapper voucherRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes(ID_KEY)); long discountValue = resultSet.getLong(DISCOUNT_VALUE_KEY); String voucherTypeStr = resultSet.getString(TYPE_KEY); @@ -34,7 +32,7 @@ public class DomainMapper { return new Voucher(id, createdAt, voucherTypeStr, discountValue); }; - public final RowMapper customerRowMapper = (resultSet, i) -> { + public static final RowMapper customerRowMapper = (resultSet, i) -> { UUID id = toUUID(resultSet.getBytes(ID_KEY)); String name = resultSet.getString(NAME_KEY); boolean isBlack = resultSet.getBoolean(BLACK_KEY); @@ -50,7 +48,7 @@ private static UUID toUUID(byte[] bytes) { return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); } - public Map customerToParamMap(Customer customer) { + public static Map customerToParamMap(Customer customer) { Map paramMap = new HashMap<>(); paramMap.put(ID_KEY, customer.getId().toString().getBytes()); paramMap.put(NAME_KEY, customer.getName()); @@ -58,20 +56,20 @@ public Map customerToParamMap(Customer customer) { return paramMap; } - public Map ownershipToParamMap(Ownership ownership) { + public static Map ownershipToParamMap(Ownership ownership) { Map paramMap = new HashMap<>(); paramMap.put(VOUCHER_ID_KEY, ownership.voucherId().toString().getBytes()); paramMap.put(CUSTOMER_ID_KEY, ownership.customerId().toString().getBytes()); return paramMap; } - public Map uuidToParamMap(UUID id) { + public static Map uuidToParamMap(UUID id) { Map paramMap = new HashMap<>(); paramMap.put(ID_KEY, id.toString().getBytes()); return paramMap; } - public Map voucherToParamMap(Voucher voucher) { + public static Map voucherToParamMap(Voucher voucher) { Map paramMap = new HashMap<>(); paramMap.put(ID_KEY, voucher.getId().toString().getBytes()); paramMap.put(CREATED_AT_KEY, Timestamp.valueOf(voucher.getCreatedAt())); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 84ad775cee..645577c8d0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -70,7 +70,7 @@ public List readAllByCreatedAt(@RequestParam(name = "from") Loc @GetMapping("type/{type}") @ResponseBody - public List readAllByType(@PathVariable("type") VoucherType type) { - return voucherService.readAllByType(type); + public List readAllByType(@PathVariable("type") String typeName) { + return voucherService.readAllByType(typeName); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index e2abdfe371..5ceb72a90f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -22,16 +22,14 @@ public class VoucherJDBCRepository implements VoucherRepository { private static final Logger logger = LoggerFactory.getLogger(VoucherJDBCRepository.class); private final NamedParameterJdbcTemplate jdbcTemplate; - private final DomainMapper domainMapper; - public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapper domainMapper) { + public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; - this.domainMapper = domainMapper; } @Override public void insert(Voucher voucher) { - int update = jdbcTemplate.update(INSERT, domainMapper.voucherToParamMap(voucher)); + int update = jdbcTemplate.update(INSERT, DomainMapper.voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); } @@ -39,13 +37,13 @@ public void insert(Voucher voucher) { @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL, domainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL, DomainMapper.voucherRowMapper); } @Override public Optional findById(UUID id) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes()), domainMapper.voucherRowMapper)); + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes()), DomainMapper.voucherRowMapper)); } catch (EmptyResultDataAccessException e) { logger.error(EMPTY_RESULT, e); return Optional.empty(); @@ -54,7 +52,7 @@ public Optional findById(UUID id) { @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { - return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, Map.of(DomainMapper.FROM_KEY, from.toString(), DomainMapper.TO_KEY, to.toString()), domainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, Map.of(DomainMapper.FROM_KEY, from.toString(), DomainMapper.TO_KEY, to.toString()), DomainMapper.voucherRowMapper); } @Override @@ -72,7 +70,7 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - int update = jdbcTemplate.update(UPDATE_VOUCHER, domainMapper.voucherToParamMap(voucher)); + int update = jdbcTemplate.update(UPDATE_VOUCHER, DomainMapper.voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { throw new NoSuchElementException(NOT_UPDATED); } @@ -80,6 +78,6 @@ public void update(Voucher voucher) { @Override public List findAllByType(VoucherType type) { - return jdbcTemplate.query(FIND_ALL_BY_TYPE, Map.of(DomainMapper.TYPE_KEY, type.getName()), domainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL_BY_TYPE, Map.of(DomainMapper.TYPE_KEY, type.getName()), DomainMapper.voucherRowMapper); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 5fb45ea717..bd59edf4c8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -2,6 +2,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; +import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; @@ -77,7 +78,8 @@ public VoucherResponse update(UUID voucherId, CreateVoucherRequest createVoucher return VoucherResponse.from(voucher); } - public List readAllByType(VoucherType type) { - return voucherRepository.findAllByType(type).stream().map(VoucherResponse::from).toList(); + public List readAllByType(String typeName) { + VoucherType voucherType = VoucherTypeManager.get(typeName); + return voucherRepository.findAllByType(voucherType).stream().map(VoucherResponse::from).toList(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 4b6ccb6696..e7f6504672 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -21,16 +21,14 @@ public class WalletJDBCRepository implements WalletRepository { private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepository.class); private final NamedParameterJdbcTemplate jdbcTemplate; - private final DomainMapper domainMapper; - public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate, DomainMapper domainMapper) { + public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; - this.domainMapper = domainMapper; } @Override public void insert(Ownership ownership) { - int update = jdbcTemplate.update(INSERT, domainMapper.ownershipToParamMap(ownership)); + int update = jdbcTemplate.update(INSERT, DomainMapper.ownershipToParamMap(ownership)); if (update != UPDATE_ONE_FLAG) { logger.error(CAN_NOT_INSERT_OWNERSHIP); throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); @@ -42,7 +40,7 @@ public Optional findCustomerByVoucherId(UUID voucherId) { try { return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID, Collections.singletonMap(DomainMapper.ID_KEY, voucherId.toString().getBytes()), - domainMapper.customerRowMapper)); + DomainMapper.customerRowMapper)); } catch (EmptyResultDataAccessException e) { return Optional.empty(); } @@ -52,12 +50,12 @@ public Optional findCustomerByVoucherId(UUID voucherId) { public List findAllVoucherByCustomerId(UUID customerId) { return jdbcTemplate.query(FIND_ALL_VOUCHER_BY_CUSTOMER_ID, Collections.singletonMap(DomainMapper.ID_KEY, customerId.toString().getBytes()), - domainMapper.voucherRowMapper); + DomainMapper.voucherRowMapper); } @Override public void delete(UUID voucherId) { - int update = jdbcTemplate.update(DELETE_OWNERSHIP, domainMapper.uuidToParamMap(voucherId)); + int update = jdbcTemplate.update(DELETE_OWNERSHIP, DomainMapper.uuidToParamMap(voucherId)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_FOUND_VOUCHER_ALLOCATION); throw new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); From e74c09c560f5db5597c92db3bd07121fae20006f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 09:57:30 +0900 Subject: [PATCH 316/383] fix: re-write voucher.json file --- src/main/resources/voucher.json | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/resources/voucher.json b/src/main/resources/voucher.json index d9428d5c40..02c00045cc 100644 --- a/src/main/resources/voucher.json +++ b/src/main/resources/voucher.json @@ -1,9 +1,6 @@ [ { - "voucher_type" : "percent", - "voucher_id" : "ad9f0529-6f4e-4a36-b44e-d7d7b407c9a1", - "discount_value" : 100 -}, { - "voucher_type" : "fixed", - "voucher_id" : "ba65ee06-ae98-48cd-b31d-dfabb8c889a4", - "discount_value" : 100 + "discount_value" : 1233, + "created_at" : "2023-11-06T09:28:01.097908900", + "id" : "b8fcca99-5cdf-4c27-9212-16ec1d35c54e", + "type" : "FIXED" } ] \ No newline at end of file From 073eaa8b04f698ef61eb5f1d62622ea062712001 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 10:01:23 +0900 Subject: [PATCH 317/383] refactor: split DomainMapper --- .../repository/CustomerDomainMapper.java | 48 +++++++++++++++ .../repository/CustomerFileManager.java | 15 +---- .../repository/CustomerJDBCRepository.java | 9 +-- .../vouchermanagement/util/DomainMapper.java | 60 +------------------ .../repository/VoucherDomainMapper.java | 58 ++++++++++++++++++ .../repository/VoucherFileManager.java | 33 +++------- .../repository/VoucherJDBCRepository.java | 16 ++--- .../repository/OwnershipDomainMapper.java | 22 +++++++ .../repository/WalletJDBCRepository.java | 18 +++--- 9 files changed, 163 insertions(+), 116 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerDomainMapper.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherDomainMapper.java create mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/repository/OwnershipDomainMapper.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerDomainMapper.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerDomainMapper.java new file mode 100644 index 0000000000..19b977439a --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerDomainMapper.java @@ -0,0 +1,48 @@ +package com.programmers.vouchermanagement.customer.repository; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.util.DomainMapper; +import org.springframework.jdbc.core.RowMapper; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static com.programmers.vouchermanagement.util.Constant.COMMA_SEPARATOR; + +public class CustomerDomainMapper extends DomainMapper { + public static final String BLACK_KEY = "black"; + public static final String NAME_KEY = "name"; + public static final RowMapper customerRowMapper = (resultSet, i) -> { + UUID id = toUUID(resultSet.getBytes(ID_KEY)); + String name = resultSet.getString(NAME_KEY); + boolean isBlack = resultSet.getBoolean(BLACK_KEY); + + return new Customer(id, name, isBlack); + }; + + private CustomerDomainMapper() { + } + + public static Map customerToParamMap(Customer customer) { + Map paramMap = new HashMap<>(); + paramMap.put(ID_KEY, customer.getId().toString().getBytes()); + paramMap.put(NAME_KEY, customer.getName()); + paramMap.put(BLACK_KEY, customer.isBlack()); + return paramMap; + } + + public static Customer stringToCustomer(String line) { + String[] customerInfo = line.split(COMMA_SEPARATOR); + UUID customerId = UUID.fromString(customerInfo[0]); + String name = customerInfo[1]; + boolean isBlack = Boolean.parseBoolean(customerInfo[2]); + return new Customer(customerId, name, isBlack); + } + + public static String customerToString(Customer customer) { + return customer.getId().toString() + COMMA_SEPARATOR + + customer.getName() + COMMA_SEPARATOR + + customer.isBlack(); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java index f1525db8d3..b64f5ed2f6 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java @@ -12,7 +12,8 @@ import java.util.Map; import java.util.UUID; -import static com.programmers.vouchermanagement.util.Constant.COMMA_SEPARATOR; +import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerToString; +import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.stringToCustomer; import static com.programmers.vouchermanagement.util.Message.FILE_EXCEPTION; import static com.programmers.vouchermanagement.util.Message.IO_EXCEPTION; @@ -43,13 +44,6 @@ private void loadFile() { } } - private Customer stringToCustomer(String line) { - String[] customerInfo = line.split(COMMA_SEPARATOR); - UUID customerId = UUID.fromString(customerInfo[0]); - String name = customerInfo[1]; - boolean isBlack = Boolean.parseBoolean(customerInfo[2]); - return new Customer(customerId, name, isBlack); - } public void saveFile() { File csvOutputFile = new File(filePath); @@ -61,9 +55,4 @@ public void saveFile() { } } - private String customerToString(Customer customer) { - return customer.getId().toString() + COMMA_SEPARATOR - + customer.getName() + COMMA_SEPARATOR - + customer.isBlack(); - } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 229f7b31ff..e489f79f40 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -1,7 +1,6 @@ package com.programmers.vouchermanagement.customer.repository; import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.util.DomainMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -11,6 +10,8 @@ import java.util.List; +import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerRowMapper; +import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerToParamMap; import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.*; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Message.NOT_INSERTED; @@ -27,7 +28,7 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { @Override public void insert(Customer customer) { - int update = jdbcTemplate.update(INSERT, DomainMapper.customerToParamMap(customer)); + int update = jdbcTemplate.update(INSERT, customerToParamMap(customer)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_INSERTED); throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); @@ -36,12 +37,12 @@ public void insert(Customer customer) { @Override public List findAllBlackCustomer() { - return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, DomainMapper.customerRowMapper); + return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, customerRowMapper); } @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL, DomainMapper.customerRowMapper); + return jdbcTemplate.query(FIND_ALL, customerRowMapper); } } diff --git a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java index b654ef36ba..fd9eecb7f9 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/util/DomainMapper.java @@ -1,80 +1,24 @@ package com.programmers.vouchermanagement.util; -import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.wallet.domain.Ownership; -import org.springframework.jdbc.core.RowMapper; - import java.nio.ByteBuffer; -import java.sql.Timestamp; -import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class DomainMapper { - //TODO: split public static final String ID_KEY = "id"; - public static final String VOUCHER_ID_KEY = "voucher_id"; - public static final String CUSTOMER_ID_KEY = "customer_id"; - public static final String BLACK_KEY = "black"; - public static final String NAME_KEY = "name"; - public static final String DISCOUNT_VALUE_KEY = "discount_value"; - public static final String TYPE_KEY = "type"; - public static final String CREATED_AT_KEY = "created_at"; - public static final String FROM_KEY = "from"; - public static final String TO_KEY = "to"; - public static final RowMapper voucherRowMapper = (resultSet, i) -> { - UUID id = toUUID(resultSet.getBytes(ID_KEY)); - long discountValue = resultSet.getLong(DISCOUNT_VALUE_KEY); - String voucherTypeStr = resultSet.getString(TYPE_KEY); - LocalDateTime createdAt = resultSet.getTimestamp(CREATED_AT_KEY).toLocalDateTime(); - - return new Voucher(id, createdAt, voucherTypeStr, discountValue); - }; - public static final RowMapper customerRowMapper = (resultSet, i) -> { - UUID id = toUUID(resultSet.getBytes(ID_KEY)); - String name = resultSet.getString(NAME_KEY); - boolean isBlack = resultSet.getBoolean(BLACK_KEY); - return new Customer(id, name, isBlack); - }; - - private DomainMapper() { + protected DomainMapper() { } - private static UUID toUUID(byte[] bytes) { + protected static UUID toUUID(byte[] bytes) { var byteBuffer = ByteBuffer.wrap(bytes); return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); } - public static Map customerToParamMap(Customer customer) { - Map paramMap = new HashMap<>(); - paramMap.put(ID_KEY, customer.getId().toString().getBytes()); - paramMap.put(NAME_KEY, customer.getName()); - paramMap.put(BLACK_KEY, customer.isBlack()); - return paramMap; - } - - public static Map ownershipToParamMap(Ownership ownership) { - Map paramMap = new HashMap<>(); - paramMap.put(VOUCHER_ID_KEY, ownership.voucherId().toString().getBytes()); - paramMap.put(CUSTOMER_ID_KEY, ownership.customerId().toString().getBytes()); - return paramMap; - } - public static Map uuidToParamMap(UUID id) { Map paramMap = new HashMap<>(); paramMap.put(ID_KEY, id.toString().getBytes()); return paramMap; } - - public static Map voucherToParamMap(Voucher voucher) { - Map paramMap = new HashMap<>(); - paramMap.put(ID_KEY, voucher.getId().toString().getBytes()); - paramMap.put(CREATED_AT_KEY, Timestamp.valueOf(voucher.getCreatedAt())); - paramMap.put(TYPE_KEY, voucher.getTypeName()); - paramMap.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); - return paramMap; - } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherDomainMapper.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherDomainMapper.java new file mode 100644 index 0000000000..e42d2bfa99 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherDomainMapper.java @@ -0,0 +1,58 @@ +package com.programmers.vouchermanagement.voucher.repository; + +import com.programmers.vouchermanagement.util.DomainMapper; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class VoucherDomainMapper extends DomainMapper { + public static final String DISCOUNT_VALUE_KEY = "discount_value"; + public static final String TYPE_KEY = "type"; + public static final String CREATED_AT_KEY = "created_at"; + public static final String FROM_KEY = "from"; + public static final String TO_KEY = "to"; + public static final RowMapper voucherRowMapper = (resultSet, i) -> { + UUID id = toUUID(resultSet.getBytes(ID_KEY)); + long discountValue = resultSet.getLong(DISCOUNT_VALUE_KEY); + String voucherTypeStr = resultSet.getString(TYPE_KEY); + LocalDateTime createdAt = resultSet.getTimestamp(CREATED_AT_KEY).toLocalDateTime(); + + return new Voucher(id, createdAt, voucherTypeStr, discountValue); + }; + + private VoucherDomainMapper() { + } + + public static Map voucherToParamMap(Voucher voucher) { + Map paramMap = new HashMap<>(); + paramMap.put(ID_KEY, voucher.getId().toString().getBytes()); + paramMap.put(CREATED_AT_KEY, Timestamp.valueOf(voucher.getCreatedAt())); + paramMap.put(TYPE_KEY, voucher.getTypeName()); + paramMap.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); + return paramMap; + } + + + public static Voucher objectToVoucher(Map voucherObject) { + UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(ID_KEY))); + LocalDateTime createdAt = LocalDateTime.parse(voucherObject.get(CREATED_AT_KEY)); + String voucherTypeName = String.valueOf(voucherObject.get(TYPE_KEY)); + long discountValue = Long.parseLong(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); + //TODO: check save format + return new Voucher(voucherId, createdAt, voucherTypeName, discountValue); + } + + public static HashMap voucherToObject(Voucher voucher) { + HashMap voucherObject = new HashMap<>(); + voucherObject.put(ID_KEY, voucher.getId().toString()); + voucherObject.put(CREATED_AT_KEY, voucher.getCreatedAt().toString()); + voucherObject.put(TYPE_KEY, voucher.getTypeName()); + voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); + return voucherObject; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java index 1ec7a2a2e1..13fa6955fe 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java @@ -12,26 +12,24 @@ import java.io.FileWriter; import java.io.IOException; import java.io.UncheckedIOException; -import java.time.LocalDateTime; import java.util.*; import static com.programmers.vouchermanagement.util.Message.FILE_EXCEPTION; import static com.programmers.vouchermanagement.util.Message.IO_EXCEPTION; +import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.objectToVoucher; +import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.voucherToObject; @Component @Profile("file") public class VoucherFileManager { - static final String VOUCHER_TYPE_KEY = "voucher_type"; - static final String CREATED_AT_KEY = "created_at"; private static final Logger logger = LoggerFactory.getLogger(VoucherFileManager.class); - private static final String VOUCHER_ID_KEY = "voucher_id"; - private static final String DISCOUNT_VALUE_KEY = "discount_value"; public final Map vouchers; - private final ObjectMapper objectMapper = new ObjectMapper(); + private final ObjectMapper objectMapper; private final String filePath; - public VoucherFileManager(AppProperties appProperties) { + public VoucherFileManager(AppProperties appProperties, ObjectMapper objectMapper) { this.filePath = appProperties.resources().path() + appProperties.domains().get("voucher").fileName(); + this.objectMapper = objectMapper; vouchers = new HashMap<>(); loadFile(); } @@ -39,7 +37,7 @@ public VoucherFileManager(AppProperties appProperties) { public void loadFile() { try { File file = new File(filePath); - Map[] voucherObjects = objectMapper.readValue(file, Map[].class); + Map[] voucherObjects = objectMapper.readValue(file, Map[].class); loadVouchers(voucherObjects); } catch (IOException e) { logger.error(IO_EXCEPTION); @@ -47,22 +45,13 @@ public void loadFile() { } } - public void loadVouchers(Map[] voucherObjects) { + public void loadVouchers(Map[] voucherObjects) { Arrays.stream(voucherObjects).forEach(voucherObject -> { Voucher voucher = objectToVoucher(voucherObject); vouchers.put(voucher.getId(), voucher); }); } - private Voucher objectToVoucher(Map voucherObject) { - UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(VOUCHER_ID_KEY))); - LocalDateTime createdAt = (LocalDateTime) voucherObject.get(CREATED_AT_KEY); - String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); - long discountValue = Long.parseLong(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); - //TODO: check save format - return new Voucher(voucherId, createdAt, voucherTypeName, discountValue); - } - public void saveFile() { try (FileWriter fileWriter = new FileWriter(filePath)) { List> voucherObjects = new ArrayList<>(); @@ -80,12 +69,4 @@ public void saveFile() { } } - private HashMap voucherToObject(Voucher voucher) { - HashMap voucherObject = new HashMap<>(); - voucherObject.put(VOUCHER_ID_KEY, voucher.getId().toString()); - voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue()); - voucherObject.put(VOUCHER_TYPE_KEY, voucher.getTypeName()); - voucherObject.put(CREATED_AT_KEY, voucher.getCreatedAt().toString()); - return voucherObject; - } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 5ceb72a90f..7ce833ed49 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -1,6 +1,5 @@ package com.programmers.vouchermanagement.voucher.repository; -import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import org.slf4j.Logger; @@ -15,6 +14,7 @@ import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Message.*; +import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.*; import static com.programmers.vouchermanagement.voucher.repository.VoucherQuery.*; @Profile("jdbc") @@ -29,7 +29,7 @@ public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { @Override public void insert(Voucher voucher) { - int update = jdbcTemplate.update(INSERT, DomainMapper.voucherToParamMap(voucher)); + int update = jdbcTemplate.update(INSERT, voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); } @@ -37,13 +37,13 @@ public void insert(Voucher voucher) { @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL, DomainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL, voucherRowMapper); } @Override public Optional findById(UUID id) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes()), DomainMapper.voucherRowMapper)); + return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, Collections.singletonMap(ID_KEY, id.toString().getBytes()), voucherRowMapper)); } catch (EmptyResultDataAccessException e) { logger.error(EMPTY_RESULT, e); return Optional.empty(); @@ -52,12 +52,12 @@ public Optional findById(UUID id) { @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { - return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, Map.of(DomainMapper.FROM_KEY, from.toString(), DomainMapper.TO_KEY, to.toString()), DomainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, Map.of(FROM_KEY, from.toString(), TO_KEY, to.toString()), voucherRowMapper); } @Override public void delete(UUID id) { - int update = jdbcTemplate.update(DELETE_VOUCHER, Collections.singletonMap(DomainMapper.ID_KEY, id.toString().getBytes())); + int update = jdbcTemplate.update(DELETE_VOUCHER, Collections.singletonMap(ID_KEY, id.toString().getBytes())); if (update != UPDATE_ONE_FLAG) { throw new NoSuchElementException(NOT_DELETED); } @@ -70,7 +70,7 @@ public void deleteAll() { @Override public void update(Voucher voucher) { - int update = jdbcTemplate.update(UPDATE_VOUCHER, DomainMapper.voucherToParamMap(voucher)); + int update = jdbcTemplate.update(UPDATE_VOUCHER, voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { throw new NoSuchElementException(NOT_UPDATED); } @@ -78,6 +78,6 @@ public void update(Voucher voucher) { @Override public List findAllByType(VoucherType type) { - return jdbcTemplate.query(FIND_ALL_BY_TYPE, Map.of(DomainMapper.TYPE_KEY, type.getName()), DomainMapper.voucherRowMapper); + return jdbcTemplate.query(FIND_ALL_BY_TYPE, Map.of(TYPE_KEY, type.getName()), voucherRowMapper); } } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/OwnershipDomainMapper.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/OwnershipDomainMapper.java new file mode 100644 index 0000000000..f29761af85 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/OwnershipDomainMapper.java @@ -0,0 +1,22 @@ +package com.programmers.vouchermanagement.wallet.repository; + +import com.programmers.vouchermanagement.util.DomainMapper; +import com.programmers.vouchermanagement.wallet.domain.Ownership; + +import java.util.HashMap; +import java.util.Map; + +public class OwnershipDomainMapper extends DomainMapper { + public static final String VOUCHER_ID_KEY = "voucher_id"; + public static final String CUSTOMER_ID_KEY = "customer_id"; + + private OwnershipDomainMapper() { + } + + public static Map ownershipToParamMap(Ownership ownership) { + Map paramMap = new HashMap<>(); + paramMap.put(VOUCHER_ID_KEY, ownership.voucherId().toString().getBytes()); + paramMap.put(CUSTOMER_ID_KEY, ownership.customerId().toString().getBytes()); + return paramMap; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index e7f6504672..35b3bb4661 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -1,7 +1,6 @@ package com.programmers.vouchermanagement.wallet.repository; import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.slf4j.Logger; @@ -12,9 +11,14 @@ import java.util.*; +import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerRowMapper; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ZERO_FLAG; +import static com.programmers.vouchermanagement.util.DomainMapper.ID_KEY; import static com.programmers.vouchermanagement.util.Message.*; +import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.voucherRowMapper; +import static com.programmers.vouchermanagement.wallet.repository.OwnershipDomainMapper.ownershipToParamMap; +import static com.programmers.vouchermanagement.wallet.repository.OwnershipDomainMapper.uuidToParamMap; import static com.programmers.vouchermanagement.wallet.repository.WalletQuery.*; @Repository @@ -28,7 +32,7 @@ public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { @Override public void insert(Ownership ownership) { - int update = jdbcTemplate.update(INSERT, DomainMapper.ownershipToParamMap(ownership)); + int update = jdbcTemplate.update(INSERT, ownershipToParamMap(ownership)); if (update != UPDATE_ONE_FLAG) { logger.error(CAN_NOT_INSERT_OWNERSHIP); throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); @@ -39,8 +43,8 @@ public void insert(Ownership ownership) { public Optional findCustomerByVoucherId(UUID voucherId) { try { return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID, - Collections.singletonMap(DomainMapper.ID_KEY, voucherId.toString().getBytes()), - DomainMapper.customerRowMapper)); + Collections.singletonMap(ID_KEY, voucherId.toString().getBytes()), + customerRowMapper)); } catch (EmptyResultDataAccessException e) { return Optional.empty(); } @@ -49,13 +53,13 @@ public Optional findCustomerByVoucherId(UUID voucherId) { @Override public List findAllVoucherByCustomerId(UUID customerId) { return jdbcTemplate.query(FIND_ALL_VOUCHER_BY_CUSTOMER_ID, - Collections.singletonMap(DomainMapper.ID_KEY, customerId.toString().getBytes()), - DomainMapper.voucherRowMapper); + Collections.singletonMap(ID_KEY, customerId.toString().getBytes()), + voucherRowMapper); } @Override public void delete(UUID voucherId) { - int update = jdbcTemplate.update(DELETE_OWNERSHIP, DomainMapper.uuidToParamMap(voucherId)); + int update = jdbcTemplate.update(DELETE_OWNERSHIP, uuidToParamMap(voucherId)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_FOUND_VOUCHER_ALLOCATION); throw new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); From 1ea761055699db71ec5fda51ec564dd064001063 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 10:01:35 +0900 Subject: [PATCH 318/383] refactor: add objectMapper Bean --- .../configuration/FileConfig.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java new file mode 100644 index 0000000000..e0ab3f51d5 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java @@ -0,0 +1,15 @@ +package com.programmers.vouchermanagement.configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Profile("file") +@Configuration +public class FileConfig { + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } +} From c74eccd71613019962a9f2c95c8732630b6368fb Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 10:05:36 +0900 Subject: [PATCH 319/383] refactor: re-packaging repository package --- .../customer/repository/CustomerFileRepository.java | 1 + .../customer/repository/CustomerJDBCRepository.java | 6 +++--- .../repository/{ => util}/CustomerDomainMapper.java | 2 +- .../repository/{ => util}/CustomerFileManager.java | 6 +++--- .../customer/repository/{ => util}/CustomerQuery.java | 2 +- .../voucher/repository/VoucherFileRepository.java | 1 + .../voucher/repository/VoucherJDBCRepository.java | 4 ++-- .../repository/{ => util}/VoucherDomainMapper.java | 2 +- .../repository/{ => util}/VoucherFileManager.java | 6 +++--- .../voucher/repository/{ => util}/VoucherQuery.java | 2 +- .../wallet/repository/WalletJDBCRepository.java | 10 +++++----- .../repository/{ => util}/OwnershipDomainMapper.java | 2 +- .../wallet/repository/{ => util}/WalletQuery.java | 2 +- 13 files changed, 24 insertions(+), 22 deletions(-) rename src/main/java/com/programmers/vouchermanagement/customer/repository/{ => util}/CustomerDomainMapper.java (96%) rename src/main/java/com/programmers/vouchermanagement/customer/repository/{ => util}/CustomerFileManager.java (92%) rename src/main/java/com/programmers/vouchermanagement/customer/repository/{ => util}/CustomerQuery.java (84%) rename src/main/java/com/programmers/vouchermanagement/voucher/repository/{ => util}/VoucherDomainMapper.java (97%) rename src/main/java/com/programmers/vouchermanagement/voucher/repository/{ => util}/VoucherFileManager.java (94%) rename src/main/java/com/programmers/vouchermanagement/voucher/repository/{ => util}/VoucherQuery.java (93%) rename src/main/java/com/programmers/vouchermanagement/wallet/repository/{ => util}/OwnershipDomainMapper.java (91%) rename src/main/java/com/programmers/vouchermanagement/wallet/repository/{ => util}/WalletQuery.java (91%) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 2f61a05e0a..db0c7582d2 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.customer.repository; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.repository.util.CustomerFileManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index e489f79f40..4241b33be5 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -10,9 +10,9 @@ import java.util.List; -import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerRowMapper; -import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerToParamMap; -import static com.programmers.vouchermanagement.customer.repository.CustomerQuery.*; +import static com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper.customerRowMapper; +import static com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper.customerToParamMap; +import static com.programmers.vouchermanagement.customer.repository.util.CustomerQuery.*; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Message.NOT_INSERTED; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerDomainMapper.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerDomainMapper.java similarity index 96% rename from src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerDomainMapper.java rename to src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerDomainMapper.java index 19b977439a..f13fa32354 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerDomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerDomainMapper.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.customer.repository; +package com.programmers.vouchermanagement.customer.repository.util; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.util.DomainMapper; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java similarity index 92% rename from src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java rename to src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java index b64f5ed2f6..1ea6ea1e80 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.customer.repository; +package com.programmers.vouchermanagement.customer.repository.util; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.properties.AppProperties; @@ -12,8 +12,8 @@ import java.util.Map; import java.util.UUID; -import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerToString; -import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.stringToCustomer; +import static com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper.customerToString; +import static com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper.stringToCustomer; import static com.programmers.vouchermanagement.util.Message.FILE_EXCEPTION; import static com.programmers.vouchermanagement.util.Message.IO_EXCEPTION; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerQuery.java similarity index 84% rename from src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java rename to src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerQuery.java index 42cf510f73..942dad5fae 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerQuery.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.customer.repository; +package com.programmers.vouchermanagement.customer.repository.util; public class CustomerQuery { public static final String FIND_ALL_BLACK_CUSTOMER = "SELECT * FROM customers WHERE black = TRUE"; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 03c6aae6c2..31a97d3cdf 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -2,6 +2,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; +import com.programmers.vouchermanagement.voucher.repository.util.VoucherFileManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 7ce833ed49..566d3fbee5 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -14,8 +14,8 @@ import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Message.*; -import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.*; -import static com.programmers.vouchermanagement.voucher.repository.VoucherQuery.*; +import static com.programmers.vouchermanagement.voucher.repository.util.VoucherDomainMapper.*; +import static com.programmers.vouchermanagement.voucher.repository.util.VoucherQuery.*; @Profile("jdbc") @Repository diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherDomainMapper.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherDomainMapper.java similarity index 97% rename from src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherDomainMapper.java rename to src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherDomainMapper.java index e42d2bfa99..4e9b74b0f6 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherDomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherDomainMapper.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher.repository; +package com.programmers.vouchermanagement.voucher.repository.util; import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.voucher.domain.Voucher; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java similarity index 94% rename from src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java rename to src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java index 13fa6955fe..0a77a893d8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher.repository; +package com.programmers.vouchermanagement.voucher.repository.util; import com.fasterxml.jackson.databind.ObjectMapper; import com.programmers.vouchermanagement.properties.AppProperties; @@ -16,8 +16,8 @@ import static com.programmers.vouchermanagement.util.Message.FILE_EXCEPTION; import static com.programmers.vouchermanagement.util.Message.IO_EXCEPTION; -import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.objectToVoucher; -import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.voucherToObject; +import static com.programmers.vouchermanagement.voucher.repository.util.VoucherDomainMapper.objectToVoucher; +import static com.programmers.vouchermanagement.voucher.repository.util.VoucherDomainMapper.voucherToObject; @Component @Profile("file") diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherQuery.java similarity index 93% rename from src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java rename to src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherQuery.java index 9a2786157a..1e12a3eefd 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherQuery.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher.repository; +package com.programmers.vouchermanagement.voucher.repository.util; public class VoucherQuery { public static final String INSERT = "INSERT INTO vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discount_value)"; diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 35b3bb4661..9e047d9565 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -11,15 +11,15 @@ import java.util.*; -import static com.programmers.vouchermanagement.customer.repository.CustomerDomainMapper.customerRowMapper; +import static com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper.customerRowMapper; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ZERO_FLAG; import static com.programmers.vouchermanagement.util.DomainMapper.ID_KEY; import static com.programmers.vouchermanagement.util.Message.*; -import static com.programmers.vouchermanagement.voucher.repository.VoucherDomainMapper.voucherRowMapper; -import static com.programmers.vouchermanagement.wallet.repository.OwnershipDomainMapper.ownershipToParamMap; -import static com.programmers.vouchermanagement.wallet.repository.OwnershipDomainMapper.uuidToParamMap; -import static com.programmers.vouchermanagement.wallet.repository.WalletQuery.*; +import static com.programmers.vouchermanagement.voucher.repository.util.VoucherDomainMapper.voucherRowMapper; +import static com.programmers.vouchermanagement.wallet.repository.util.OwnershipDomainMapper.ownershipToParamMap; +import static com.programmers.vouchermanagement.wallet.repository.util.OwnershipDomainMapper.uuidToParamMap; +import static com.programmers.vouchermanagement.wallet.repository.util.WalletQuery.*; @Repository public class WalletJDBCRepository implements WalletRepository { diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/OwnershipDomainMapper.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/util/OwnershipDomainMapper.java similarity index 91% rename from src/main/java/com/programmers/vouchermanagement/wallet/repository/OwnershipDomainMapper.java rename to src/main/java/com/programmers/vouchermanagement/wallet/repository/util/OwnershipDomainMapper.java index f29761af85..2a6fc85b26 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/OwnershipDomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/util/OwnershipDomainMapper.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.wallet.repository; +package com.programmers.vouchermanagement.wallet.repository.util; import com.programmers.vouchermanagement.util.DomainMapper; import com.programmers.vouchermanagement.wallet.domain.Ownership; diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/util/WalletQuery.java similarity index 91% rename from src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java rename to src/main/java/com/programmers/vouchermanagement/wallet/repository/util/WalletQuery.java index a5065c9b82..ed366f41b1 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletQuery.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/util/WalletQuery.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.wallet.repository; +package com.programmers.vouchermanagement.wallet.repository.util; public class WalletQuery { public static final String INSERT = "INSERT INTO ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucher_id), UUID_TO_BIN(:customer_id))"; From 189baffe45fda5105c481236239ee152e7519faf Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 10:10:50 +0900 Subject: [PATCH 320/383] refactor: re-packaging controller package --- .../vouchermanagement/consoleapp/io/ConsoleManager.java | 6 +++--- .../vouchermanagement/consoleapp/menu/MenuHandler.java | 6 +++--- .../customer/controller/CustomerController.java | 4 ++-- .../customer/controller/CustomerThymeleafController.java | 2 +- .../{ => controller}/dto/CreateCustomerRequest.java | 2 +- .../customer/{ => controller}/dto/CustomerResponse.java | 2 +- .../vouchermanagement/customer/service/CustomerService.java | 4 ++-- .../voucher/controller/VoucherController.java | 5 ++--- .../voucher/controller/VoucherThymeleafController.java | 4 ++-- .../voucher/{ => controller}/dto/CreateVoucherRequest.java | 2 +- .../voucher/{ => controller}/dto/VoucherResponse.java | 2 +- .../vouchermanagement/voucher/service/VoucherService.java | 4 ++-- .../wallet/controller/WalletController.java | 4 ++-- .../wallet/controller/WalletThymeleafController.java | 4 ++-- .../vouchermanagement/wallet/service/WalletService.java | 4 ++-- 15 files changed, 27 insertions(+), 28 deletions(-) rename src/main/java/com/programmers/vouchermanagement/customer/{ => controller}/dto/CreateCustomerRequest.java (51%) rename src/main/java/com/programmers/vouchermanagement/customer/{ => controller}/dto/CustomerResponse.java (83%) rename src/main/java/com/programmers/vouchermanagement/voucher/{ => controller}/dto/CreateVoucherRequest.java (53%) rename src/main/java/com/programmers/vouchermanagement/voucher/{ => controller}/dto/VoucherResponse.java (86%) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index fb44db055f..3f9ba8ded5 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,11 +1,11 @@ package com.programmers.vouchermanagement.consoleapp.io; import com.programmers.vouchermanagement.consoleapp.menu.Menu; -import com.programmers.vouchermanagement.customer.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import org.beryx.textio.TextIO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 39171a7d2b..95b79e9491 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -2,10 +2,10 @@ import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; import com.programmers.vouchermanagement.customer.controller.CustomerController; -import com.programmers.vouchermanagement.customer.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.controller.VoucherController; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index eeef165369..0937e3df7f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.customer.controller; -import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; -import com.programmers.vouchermanagement.customer.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.service.CustomerService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java index 3e533608c3..a11db1c230 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java @@ -1,6 +1,6 @@ package com.programmers.vouchermanagement.customer.controller; -import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; +import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; import com.programmers.vouchermanagement.customer.service.CustomerService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/dto/CreateCustomerRequest.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CreateCustomerRequest.java similarity index 51% rename from src/main/java/com/programmers/vouchermanagement/customer/dto/CreateCustomerRequest.java rename to src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CreateCustomerRequest.java index 3b7ace0569..503104308c 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/dto/CreateCustomerRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CreateCustomerRequest.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.customer.dto; +package com.programmers.vouchermanagement.customer.controller.dto; public record CreateCustomerRequest(String name, boolean isBlack) { } \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerResponse.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CustomerResponse.java similarity index 83% rename from src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerResponse.java rename to src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CustomerResponse.java index 091d29c295..a45ba27818 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/dto/CustomerResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CustomerResponse.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.customer.dto; +package com.programmers.vouchermanagement.customer.controller.dto; import com.programmers.vouchermanagement.customer.domain.Customer; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 156001f8d7..dab63e9949 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -1,8 +1,8 @@ package com.programmers.vouchermanagement.customer.service; import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.customer.dto.CreateCustomerRequest; -import com.programmers.vouchermanagement.customer.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 645577c8d0..124fcb89d3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,8 +1,7 @@ package com.programmers.vouchermanagement.voucher.controller; -import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java index c414535caf..06564caa73 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.voucher.controller; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/dto/CreateVoucherRequest.java similarity index 53% rename from src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java rename to src/main/java/com/programmers/vouchermanagement/voucher/controller/dto/CreateVoucherRequest.java index d1599d18b7..d48f874042 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/dto/CreateVoucherRequest.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher.dto; +package com.programmers.vouchermanagement.voucher.controller.dto; public record CreateVoucherRequest(String typeName, long discountValue) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/dto/VoucherResponse.java similarity index 86% rename from src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java rename to src/main/java/com/programmers/vouchermanagement/voucher/controller/dto/VoucherResponse.java index c8d5a4bf1a..82268ce86b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/dto/VoucherResponse.java @@ -1,4 +1,4 @@ -package com.programmers.vouchermanagement.voucher.dto; +package com.programmers.vouchermanagement.voucher.controller.dto; import com.programmers.vouchermanagement.voucher.domain.Voucher; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index bd59edf4c8..74afa58975 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -3,8 +3,8 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java index dba7ea2cc8..750108d911 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.wallet.controller; -import com.programmers.vouchermanagement.customer.dto.CustomerResponse; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.service.WalletService; import org.springframework.context.annotation.Profile; diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java index e6564b8bd0..81fb1803b1 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.wallet.controller; -import com.programmers.vouchermanagement.customer.dto.CustomerResponse; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.service.WalletService; import org.springframework.context.annotation.Profile; diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index 8bc53d0651..bd6e278f49 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -1,9 +1,9 @@ package com.programmers.vouchermanagement.wallet.service; import com.programmers.vouchermanagement.customer.domain.Customer; -import com.programmers.vouchermanagement.customer.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.repository.WalletRepository; import org.slf4j.Logger; From 6cae5cc8eefb140cbdc267b6e46d044f5b25b5dd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 10:26:42 +0900 Subject: [PATCH 321/383] refactor: add equals & hashCode at domain classes --- .../customer/domain/Customer.java | 14 ++++++++++++++ .../vouchermanagement/voucher/domain/Voucher.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 7c20344335..e61b2cf55f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.customer.domain; +import java.util.Objects; import java.util.UUID; public class Customer { @@ -30,5 +31,18 @@ public boolean isBlack() { public String getName() { return name; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Customer customer = (Customer) o; + return black == customer.black && Objects.equals(id, customer.id) && Objects.equals(name, customer.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, black); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index adf05eef33..53637b30c3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -4,6 +4,7 @@ import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; import java.time.LocalDateTime; +import java.util.Objects; import java.util.UUID; public class Voucher { @@ -44,4 +45,17 @@ public LocalDateTime getCreatedAt() { public long getDiscountValue() { return discountValue; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Voucher voucher = (Voucher) o; + return discountValue == voucher.discountValue && Objects.equals(id, voucher.id) && Objects.equals(createdAt, voucher.createdAt) && Objects.equals(type, voucher.type); + } + + @Override + public int hashCode() { + return Objects.hash(id, createdAt, type, discountValue); + } } From ca750458c0da63a7b126334eb08ef9f6b6ca8a83 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 18:09:12 +0900 Subject: [PATCH 322/383] refactor: fix sql query --- src/main/resources/schema.sql | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 23b8ede2e7..3b8e0f9d9b 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -16,32 +16,6 @@ CREATE TABLE vouchers created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ); -CREATE TABLE ownership -( - voucher_id BINARY(16) PRIMARY KEY, - customer_id BINARY(16), - FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, - FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE -); -drop DATABASE if exists test; -CREATE DATABASE test; -use test; -CREATE TABLE customers -( - id BINARY(16) PRIMARY KEY, - name varchar(20) NOT NULL, - black boolean not null, - CONSTRAINT name UNIQUE (name) -); - -CREATE TABLE vouchers -( - id BINARY(16) PRIMARY KEY, - type enum ('FIXED', 'PERCENT') NOT NULL, - discount_value varchar(50) NOT NULL, - created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) -); - CREATE TABLE ownership ( voucher_id BINARY(16) PRIMARY KEY, From 1fc9543b4d1bcbea4c239e774347b035e00c8675 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 18:09:33 +0900 Subject: [PATCH 323/383] refactor: remove test profile properties --- src/main/resources/application.yaml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 5d0550299f..c95e7ba2cd 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -21,14 +21,4 @@ file: file-name: blacklist.csv voucher: - file-name: voucher.json ---- -spring: - config: - activate: - on-profile: test - datasource: - url: jdbc:mysql://localhost:3306/test - username: root - password: 20231028 - + file-name: voucher.json \ No newline at end of file From d914de40afcd750c1bdd6dd2aa0d0f3e55d13d2a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 18:11:08 +0900 Subject: [PATCH 324/383] refactor: apply @JdbcTest --- .../CustomerJDBCRepositoryTest.java | 45 +++++++++--------- .../VoucherInMemoryRepositoryTest.java | 2 +- .../repository/VoucherJDBCRepositoryTest.java | 47 +++++++++---------- .../voucher/service/VoucherServiceTest.java | 19 ++++---- .../repository/WalletJDBCRepositoryTest.java | 35 ++++++-------- 5 files changed, 69 insertions(+), 79 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 63128151d7..4caf9d1e53 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -1,53 +1,54 @@ package com.programmers.vouchermanagement.customer.repository; -import com.programmers.vouchermanagement.TestConfig; import com.programmers.vouchermanagement.customer.domain.Customer; -import org.junit.jupiter.api.AfterAll; +import com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import java.util.Collections; import java.util.List; import java.util.UUID; +import static com.programmers.vouchermanagement.util.DomainMapper.ID_KEY; import static org.assertj.core.api.Assertions.assertThat; -@SpringJUnitConfig -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class) +@JdbcTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class CustomerJDBCRepositoryTest { - @Autowired + NamedParameterJdbcTemplate jdbcTemplate; CustomerJDBCRepository customerJDBCRepository; @Autowired - JdbcTemplate jdbcTemplate; - - @AfterAll - void init() { - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 0"); - jdbcTemplate.execute("TRUNCATE TABLE test.customers"); - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); + CustomerJDBCRepositoryTest(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate); + customerJDBCRepository = new CustomerJDBCRepository(this.jdbcTemplate); } @Test @DisplayName("🆗 블랙리스트를 조회할 수 있다. 단, 블랙 고객이 없는 경우 빈 list가 반환된다.") void findAllBlackCustomerSucceed() { - customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객1", false)); - customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객2", true)); - customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객3", false)); + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객1", false)); + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객2", true)); + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객3", false)); List customers = customerJDBCRepository.findAllBlackCustomer(); - assertThat(customers.isEmpty()).isFalse(); + assertThat(customers).isNotEmpty(); assertThat(customers.stream().filter(customer -> !customer.isBlack()).toList()).isEmpty(); } @Test @DisplayName("🆗 고객 정보를 저장할 수 있다.") - void save() { - customerJDBCRepository.save(new Customer(UUID.randomUUID(), "고객4")); + void insert() { + Customer customer = new Customer(UUID.randomUUID(), "고객4"); + customerJDBCRepository.insert(customer); + Customer retrievedCustomer = jdbcTemplate + .queryForObject("SELECT * FROM customers WHERE id = UUID_TO_BIN(:id)", Collections.singletonMap(ID_KEY, customer.getId().toString().getBytes()), CustomerDomainMapper.customerRowMapper); + + assertThat(retrievedCustomer).isEqualTo(customer); } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java index 0690822243..a3b4c77a62 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepositoryTest.java @@ -40,7 +40,7 @@ void updateVoucherSucceed() { Voucher voucher = new Voucher("FIXED", 5555); voucherInMemoryRepository.insert(voucher); - Voucher updatedVoucher = new Voucher("PERCENT", 100); + Voucher updatedVoucher = new Voucher(voucher.getId(), voucher.getCreatedAt(), "PERCENT", 100); voucherInMemoryRepository.update(updatedVoucher); Optional retrievedVoucher = voucherInMemoryRepository.findById(voucher.getId()); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index ef4628f662..f48d91e679 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -1,50 +1,45 @@ package com.programmers.vouchermanagement.voucher.repository; -import com.programmers.vouchermanagement.configuration.JdbcConfig; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import java.time.LocalDateTime; import java.util.List; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -@SpringJUnitConfig -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@ContextConfiguration(classes = JdbcConfig.class, loader = AnnotationConfigContextLoader.class) +@JdbcTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class VoucherJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); - @Autowired + NamedParameterJdbcTemplate jdbcTemplate; VoucherJDBCRepository voucherJDBCRepository; @Autowired - JdbcTemplate jdbcTemplate; - - @AfterAll - void init() { - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 0"); - jdbcTemplate.execute("TRUNCATE TABLE test.vouchers"); - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); + VoucherJDBCRepositoryTest(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate); + voucherJDBCRepository = new VoucherJDBCRepository(this.jdbcTemplate); } @Test @DisplayName("🆗 고정 금액 할인 바우처를 추가할 수 있다.") void saveFixedAmountVoucher() { Voucher voucher = new Voucher("FIXED", 1000); + voucherJDBCRepository.insert(voucher); Optional retrievedVoucher = voucherJDBCRepository.findById(voucher.getId()); - assertThat(retrievedVoucher.isEmpty()).isFalse(); + assertThat(retrievedVoucher).isNotEmpty(); assertThat(retrievedVoucher.get().getId()).isEqualTo(voucher.getId()); } @@ -64,11 +59,11 @@ void savePercentVoucher() { @DisplayName("🆗 모든 바우처를 조회할 수 있다. 단, 없다면 빈 list를 반환한다.") void findAllVoucher() { for (int i = 1; i < 6; i++) - voucherJDBCRepository.insert(new Voucher("PERCENT", i * 100)); + voucherJDBCRepository.insert(new Voucher("PERCENT", i)); List vouchers = voucherJDBCRepository.findAll(); - assertThat(vouchers.isEmpty()).isFalse(); + assertThat(vouchers.size()).isGreaterThanOrEqualTo(5); } @Test @@ -124,10 +119,10 @@ void updateVoucher() { assertThat(retrievedVoucher.get().getDiscountValue()).isEqualTo(updatedVoucher.getDiscountValue()); assertThat(retrievedVoucher.get().getTypeName()).isEqualTo(updatedVoucher.getTypeName()); } -// -// @Test -// @DisplayName("🚨 해당하는 바우처가 없다면, 바우처를 업데이트 할 수 없다.") -// void updateNonExistentVoucher() { -// assertThrows(RuntimeException.class, () -> voucherJDBCRepository.update(new Voucher(NON_EXISTENT_VOUCHER_ID, "PERCENT", 100))); -// } + + @Test + @DisplayName("🚨 해당하는 바우처가 없다면, 바우처를 업데이트 할 수 없다.") + void updateNonExistentVoucher() { + assertThrows(NoSuchElementException.class, () -> voucherJDBCRepository.update(new Voucher(NON_EXISTENT_VOUCHER_ID, LocalDateTime.now(), "PERCENT", 100))); + } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 89401cd6d4..79195ae320 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.voucher.service; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -71,7 +71,7 @@ void readVoucherByIdSucceed() { when(voucherRepository.findById(mockId)).thenReturn(Optional.of(mockVoucher)); - verify(voucherRepository, times(1)).findById(any(UUID.class)); + verify(voucherRepository, times(1)).findById(mockId); } @Test @@ -82,11 +82,12 @@ void deleteVoucherSucceed() { verify(voucherRepository, times(1)).delete(any(UUID.class)); } -// @Test -// @DisplayName("바우처를 업데이트할 수 있다.") -// void updateVoucherSucceed() { -// voucherService.update(new Voucher("FIXED", 100)); -// -// verify(voucherRepository, times(1)).update(any(Voucher.class)); -// } + @Test + @DisplayName("바우처를 업데이트할 수 있다.") + void updateVoucherSucceed() { + + voucherService.update(mockId, new CreateVoucherRequest("FIXED", 100)); + + verify(voucherRepository, times(1)).update(any(Voucher.class)); + } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index b26c8253a3..eac7f7856c 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -1,17 +1,18 @@ package com.programmers.vouchermanagement.wallet.repository; -import com.programmers.vouchermanagement.configuration.JdbcConfig; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerJDBCRepository; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.repository.VoucherJDBCRepository; import com.programmers.vouchermanagement.wallet.domain.Ownership; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import java.util.Optional; import java.util.UUID; @@ -20,31 +21,23 @@ import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertThrows; -@SpringJUnitConfig -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@ContextConfiguration(classes = JdbcConfig.class, loader = AnnotationConfigContextLoader.class) +@JdbcTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class WalletJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); private final static UUID NON_EXISTENT_CUSTOMER_ID = UUID.randomUUID(); - @Autowired + NamedParameterJdbcTemplate jdbcTemplate; WalletJDBCRepository walletJDBCRepository; - @Autowired VoucherJDBCRepository voucherJDBCRepository; - @Autowired CustomerJDBCRepository customerJDBCRepository; @Autowired - JdbcTemplate jdbcTemplate; - - @AfterAll - void init() { - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 0"); - jdbcTemplate.execute("TRUNCATE TABLE test.vouchers"); - jdbcTemplate.execute("TRUNCATE TABLE test.ownership"); - jdbcTemplate.execute("TRUNCATE TABLE test.customers"); - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); + WalletJDBCRepositoryTest(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate); + walletJDBCRepository = new WalletJDBCRepository(this.jdbcTemplate); + voucherJDBCRepository = new VoucherJDBCRepository(this.jdbcTemplate); + customerJDBCRepository = new CustomerJDBCRepository(this.jdbcTemplate); } @Test From c3ced3fca399e714efe90681194cd70cc4fc6a72 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 18:12:49 +0900 Subject: [PATCH 325/383] refactor: make code shorter --- .../vouchermanagement/configuration/JdbcConfig.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java index ef138a6c13..6f52fbd509 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java @@ -4,7 +4,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import javax.sql.DataSource; @@ -15,7 +14,6 @@ public class JdbcConfig { @Bean public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - return new NamedParameterJdbcTemplate(jdbcTemplate); + return new NamedParameterJdbcTemplate(dataSource); } } From f9c0c9773ee390017852502bf69711b49eb8e1aa Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 18:13:04 +0900 Subject: [PATCH 326/383] refactor: refactor VoucherService --- .../voucher/service/VoucherService.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 74afa58975..82c2f390b3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,18 +1,15 @@ package com.programmers.vouchermanagement.voucher.service; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; -import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.UUID; +import java.util.*; import static com.programmers.vouchermanagement.util.Message.NOT_FOUND_VOUCHER; @@ -56,9 +53,9 @@ public List readAllByCreatedAt(LocalDateTime from, LocalDateTim } public VoucherResponse readById(UUID voucherId) { - Voucher voucher = voucherRepository - .findById(voucherId) - .orElseThrow(() -> new NoSuchElementException(NOT_FOUND_VOUCHER)); + Optional voucherOptional = voucherRepository + .findById(voucherId); + Voucher voucher = voucherOptional.orElseThrow(() -> new NoSuchElementException(NOT_FOUND_VOUCHER)); return VoucherResponse.from(voucher); } From 07bd0d31d264db1455715b76bcbedb4183ff8658 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 18:58:42 +0900 Subject: [PATCH 327/383] fix: make files and properties for test --- src/main/resources/application.yaml | 21 ++++++++++++++++++++- src/main/resources/schema.sql | 27 +++++++++++++++++++++++++++ src/test/resources/blacklist.csv | 4 +--- src/test/resources/voucher.json | 10 +--------- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index c95e7ba2cd..f09fead9e3 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -21,4 +21,23 @@ file: file-name: blacklist.csv voucher: - file-name: voucher.json \ No newline at end of file + file-name: voucher.json +--- +spring: + config: + activate: + on-profile: test + datasource: + url: jdbc:mysql://localhost:3306/test + username: root + password: 20231028 +file: + resources: + path: src/test/resources/ + + domains: + customer: + file-name: blacklist.csv + + voucher: + file-name: voucher.json diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 3b8e0f9d9b..d8b8a7e402 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -16,6 +16,33 @@ CREATE TABLE vouchers created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ); +CREATE TABLE ownership +( + voucher_id BINARY(16) PRIMARY KEY, + customer_id BINARY(16), + FOREIGN KEY (voucher_id) REFERENCES vouchers (id) ON DELETE CASCADE, + FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE +); + + +drop DATABASE if exists test; +CREATE DATABASE test; +use test; +CREATE TABLE customers +( + id BINARY(16) PRIMARY KEY, + name varchar(20) NOT NULL, + black boolean not null, + CONSTRAINT name UNIQUE (name) +); +CREATE TABLE vouchers +( + id BINARY(16) PRIMARY KEY, + type enum ('FIXED', 'PERCENT') NOT NULL, + discount_value varchar(50) NOT NULL, + created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) +); + CREATE TABLE ownership ( voucher_id BINARY(16) PRIMARY KEY, diff --git a/src/test/resources/blacklist.csv b/src/test/resources/blacklist.csv index e2efc7ccaa..79dfd50f04 100644 --- a/src/test/resources/blacklist.csv +++ b/src/test/resources/blacklist.csv @@ -1,3 +1 @@ -id,name -e8d88c24-668c-4b65-a658-44303bfbb805, 송인재 -9b46f523-03d4-41b2-a68e-0666f21c6f7d, 익명 +id,name \ No newline at end of file diff --git a/src/test/resources/voucher.json b/src/test/resources/voucher.json index d9428d5c40..0637a088a0 100644 --- a/src/test/resources/voucher.json +++ b/src/test/resources/voucher.json @@ -1,9 +1 @@ -[ { - "voucher_type" : "percent", - "voucher_id" : "ad9f0529-6f4e-4a36-b44e-d7d7b407c9a1", - "discount_value" : 100 -}, { - "voucher_type" : "fixed", - "voucher_id" : "ba65ee06-ae98-48cd-b31d-dfabb8c889a4", - "discount_value" : 100 -} ] \ No newline at end of file +[] \ No newline at end of file From 1c89375c2107cd761c4200492a3e8af32c9ca8a9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 18:59:47 +0900 Subject: [PATCH 328/383] refactor: apply test profile for test --- .../customer/repository/CustomerJDBCRepositoryTest.java | 5 +++-- .../voucher/repository/VoucherJDBCRepositoryTest.java | 2 ++ .../wallet/repository/WalletJDBCRepositoryTest.java | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 4caf9d1e53..960d7774ef 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -4,12 +4,12 @@ import com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import java.util.Collections; import java.util.List; @@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; @JdbcTest +@ActiveProfiles("test") @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class CustomerJDBCRepositoryTest { NamedParameterJdbcTemplate jdbcTemplate; @@ -38,7 +39,7 @@ void findAllBlackCustomerSucceed() { customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객3", false)); List customers = customerJDBCRepository.findAllBlackCustomer(); assertThat(customers).isNotEmpty(); - assertThat(customers.stream().filter(customer -> !customer.isBlack()).toList()).isEmpty(); + assertThat(customers.size()).isGreaterThanOrEqualTo(1); } @Test diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java index f48d91e679..be907cce27 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepositoryTest.java @@ -8,6 +8,7 @@ import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import java.time.LocalDateTime; import java.util.List; @@ -19,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @JdbcTest +@ActiveProfiles("test") @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class VoucherJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index eac7f7856c..e0a6090d18 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -13,6 +13,7 @@ import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import java.util.Optional; import java.util.UUID; @@ -22,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @JdbcTest +@ActiveProfiles("test") @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class WalletJDBCRepositoryTest { private final static UUID NON_EXISTENT_VOUCHER_ID = UUID.randomUUID(); From a058e133275dd03a804b6bf7353cdbc2d897fb6c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 19:20:04 +0900 Subject: [PATCH 329/383] refactor: add null check at customer constructor --- .../programmers/vouchermanagement/customer/domain/Customer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index e61b2cf55f..aaa479f8be 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -13,7 +13,7 @@ public Customer(UUID id, String name) { } public Customer(UUID id, String name, boolean black) { - if (name.isBlank() || name.length() > 20) + if (name == null || name.isBlank() || name.length() > 20) throw new IllegalArgumentException("The name length should be between 0 to 20."); this.id = id; this.name = name; From bf8699c5f353a22ab40771e4d6bde1d28b694400 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 19:20:14 +0900 Subject: [PATCH 330/383] test: test customer constructor --- .../customer/domain/CustomerTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java new file mode 100644 index 0000000000..84a4b24c62 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java @@ -0,0 +1,23 @@ +package com.programmers.vouchermanagement.customer.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CustomerTest { + @DisplayName("🚨 고객 이름이 빈칸(or null)이거나 20자가 넘으면 고객이 생성되지 않는다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {"", " ", "123456789012345678901"}) + void customerNameNullBlankOver20(String input) { + assertThrows(IllegalArgumentException.class, () -> { + new Customer(UUID.randomUUID(), input, true); + }); + } + +} \ No newline at end of file From 22be4042853c132931b8f31678b067d1d79ac14d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 19:57:08 +0900 Subject: [PATCH 331/383] test: voucher domain test --- .../FixedAmountVoucherTypeTest.java | 19 ++++++++++ .../vouchertype/PercentVoucherTypeTest.java | 19 ++++++++++ .../vouchertype/VoucherTypeManagerTest.java | 37 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherTypeTest.java create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherTypeTest.java create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManagerTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherTypeTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherTypeTest.java new file mode 100644 index 0000000000..11f7d45f7b --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/FixedAmountVoucherTypeTest.java @@ -0,0 +1,19 @@ +package com.programmers.vouchermanagement.voucher.domain.vouchertype; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class FixedAmountVoucherTypeTest { + @ParameterizedTest(name = "할인 금액이 {0}인 경우") + @DisplayName("할인 금액이 0미만이거나 100000000 초과일 경우 예외 발생") + @ValueSource(longs = {-1, 100000001}) + void discountValueUnder0AndOver100000000(long input) { + assertThrows(IllegalArgumentException.class, () -> { + VoucherType fixedAmountVoucherType = FixedAmountVoucherType.getInstance(); + fixedAmountVoucherType.validateDiscountValue(input); + }); + } +} \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherTypeTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherTypeTest.java new file mode 100644 index 0000000000..79dfea8f2b --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/PercentVoucherTypeTest.java @@ -0,0 +1,19 @@ +package com.programmers.vouchermanagement.voucher.domain.vouchertype; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class PercentVoucherTypeTest { + @ParameterizedTest(name = "할인 금액이 {0}인 경우") + @DisplayName("할인 금액이 0미만이거나 100 초과일 경우 예외 발생") + @ValueSource(longs = {-1, 101}) + void discountValueUnder0AndOver100(long input) { + assertThrows(IllegalArgumentException.class, () -> { + VoucherType percentVoucherType = PercentVoucherType.getInstance(); + percentVoucherType.validateDiscountValue(input); + }); + } +} \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManagerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManagerTest.java new file mode 100644 index 0000000000..2a70702cd7 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/domain/vouchertype/VoucherTypeManagerTest.java @@ -0,0 +1,37 @@ +package com.programmers.vouchermanagement.voucher.domain.vouchertype; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class VoucherTypeManagerTest { + + @Test + @DisplayName("타입 이름을 FIXED로 입력한 경우 FixedAmountVoucherType 반환") + void typeNameIsFIXED() { + VoucherType voucherType = VoucherTypeManager.get("FIXED"); + + assertThat(voucherType.getClass()).isEqualTo(FixedAmountVoucherType.class); + } + + @Test + @DisplayName("타입 이름을 PERCENT로 입력한 경우 PercentVoucherType 반환") + void typeNameIsPERCENT() { + VoucherType voucherType = VoucherTypeManager.get("PERCENT"); + + assertThat(voucherType.getClass()).isEqualTo(PercentVoucherType.class); + } + + @ParameterizedTest(name = "타입 입력이 {0}인 경우") + @DisplayName("타입 이름을 잘못입력한 경우 예외 발생") + @ValueSource(strings = {"ANOTHER", "FIIXED", "PERRCENT"}) + void typeNameIsNotCorrect(String input) { + assertThrows(IllegalArgumentException.class, () -> { + VoucherTypeManager.get(input); + }); + } +} \ No newline at end of file From 67b41a6453980fd8f357ce0c41e32d6488207678 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 20:55:37 +0900 Subject: [PATCH 332/383] refactor: refactor WalletService --- .../wallet/service/WalletService.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index bd6e278f49..2a39c447af 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -1,19 +1,16 @@ package com.programmers.vouchermanagement.wallet.service; -import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; -import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.repository.WalletRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import java.util.Collections; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.UUID; +import java.util.*; import static com.programmers.vouchermanagement.util.Message.NOT_FOUND_VOUCHER_ALLOCATION; @@ -31,7 +28,8 @@ public void allocate(Ownership ownership) { } public CustomerResponse readCustomerByVoucherId(UUID voucherId) { - Customer customer = walletRepository.findCustomerByVoucherId(voucherId).orElseThrow(() -> { + Optional customerOptional = walletRepository.findCustomerByVoucherId(voucherId); + Customer customer = customerOptional.orElseThrow(() -> { logger.error(NOT_FOUND_VOUCHER_ALLOCATION); return new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); }); From 2274583153cdbf2545f866d751ae64686248b0ba Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 20:57:04 +0900 Subject: [PATCH 333/383] test: make VoucherServiceTest code run --- .../voucher/service/VoucherServiceTest.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 79195ae320..d92622eee4 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -10,6 +10,7 @@ import org.mockito.Mock; import org.springframework.test.context.junit.jupiter.SpringExtension; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Optional; import java.util.UUID; @@ -27,6 +28,8 @@ class VoucherServiceTest { @Mock UUID mockId; @Mock + LocalDateTime mockLocalDateTime; + @Mock Voucher mockVoucher; @Test @@ -67,10 +70,10 @@ void readAllVouchersSucceed() { @Test @DisplayName("바우처를 id로 조회할 수 있다.") void readVoucherByIdSucceed() { - voucherService.readById(mockId); - when(voucherRepository.findById(mockId)).thenReturn(Optional.of(mockVoucher)); + voucherService.readById(mockId); + verify(voucherRepository, times(1)).findById(mockId); } @@ -85,6 +88,7 @@ void deleteVoucherSucceed() { @Test @DisplayName("바우처를 업데이트할 수 있다.") void updateVoucherSucceed() { + when(voucherRepository.findById(mockId)).thenReturn(Optional.of(new Voucher(mockId, mockLocalDateTime, "FIXED", 130))); voucherService.update(mockId, new CreateVoucherRequest("FIXED", 100)); From bd4261ca5a2b02e25612c78b59d01d1ed9427afc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 20:57:14 +0900 Subject: [PATCH 334/383] test: make WalletServiceTest code run --- .../wallet/service/WalletServiceTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java index 866c925150..97911efca1 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/service/WalletServiceTest.java @@ -1,6 +1,8 @@ package com.programmers.vouchermanagement.wallet.service; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.wallet.domain.Ownership; import com.programmers.vouchermanagement.wallet.repository.WalletRepository; @@ -56,7 +58,7 @@ void findAllVoucherByCustomerId() { List mockVoucherList = mock(List.class); when(walletRepository.findAllVoucherByCustomerId(mockUUID)).thenReturn(mockVoucherList); - assertThat(walletService.readAllVoucherByCustomerId(mockUUID)).isEqualTo(mockVoucherList); + assertThat(walletService.readAllVoucherByCustomerId(mockUUID)).isEqualTo(mockVoucherList.stream().map(VoucherResponse::from).toList()); verify(walletRepository, times(1)).findAllVoucherByCustomerId(mockUUID); } @@ -72,10 +74,9 @@ void deleteVoucherFromCustomer() { @Test @DisplayName("🆗 바우처 id로 바우처가 할당된 고객을 조회할 수 있다.") void findCustomerByVoucherId() { - Optional customerOptional = Optional.of(mockCustomer); - when(walletRepository.findCustomerByVoucherId(mockUUID)).thenReturn(customerOptional); + when(walletRepository.findCustomerByVoucherId(mockUUID)).thenReturn(Optional.of(mockCustomer)); - assertThat(walletService.readCustomerByVoucherId(mockUUID)).isEqualTo(customerOptional.get()); + assertThat(walletService.readCustomerByVoucherId(mockUUID)).isEqualTo(CustomerResponse.from(mockCustomer)); verify(walletRepository, times(1)).findCustomerByVoucherId(mockUUID); } From 52bc813b32a66df254311a9ada61865497910c0f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 22:12:00 +0900 Subject: [PATCH 335/383] refactor: set environment variable at app properties --- src/main/resources/application.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index f09fead9e3..06f3665344 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,8 +1,8 @@ spring: datasource: url: jdbc:mysql://localhost:3306/prod - username: root - password: 20231028 + username: ${USER} + password: ${PASSWORD} mvc: hidden-method: filter: @@ -29,8 +29,8 @@ spring: on-profile: test datasource: url: jdbc:mysql://localhost:3306/test - username: root - password: 20231028 + username: ${USER} + password: ${PASSWORD} file: resources: path: src/test/resources/ From 30e61b4742981632a98c4e52b46d68858f0a03e9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 23:38:09 +0900 Subject: [PATCH 336/383] refactor: delete todo --- .../vouchermanagement/voucher/service/VoucherService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 82c2f390b3..fc1f735f7e 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -22,7 +22,6 @@ public VoucherService(VoucherRepository voucherRepository) { } public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { - //TODO: now? DB vs Application Voucher voucher = new Voucher(createVoucherRequest.typeName(), createVoucherRequest.discountValue()); voucherRepository.insert(voucher); return VoucherResponse.from(voucher); From dac2da89112b2671040b0df975409233f927ecac Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Mon, 6 Nov 2023 23:40:09 +0900 Subject: [PATCH 337/383] refactor: change test method name --- .../voucher/service/VoucherServiceTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index d92622eee4..9ada527837 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -41,7 +41,7 @@ void initTest() { @Test @DisplayName("고정 할인 금액 바우처 객체를 생성할 수 있다.") - void createFixedAmountVoucherSucceed() { + void createFixedAmountVoucher() { CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest("FIXED", 1000); voucherService.create(createVoucherRequest); @@ -50,7 +50,7 @@ void createFixedAmountVoucherSucceed() { @Test @DisplayName("퍼센트 할인 바우처 객체를 생성할 수 있다.") - void createPercentDiscountVoucherSucceed() { + void createPercentDiscountVoucher() { CreateVoucherRequest createVoucherRequest = new CreateVoucherRequest("PERCENT", 100); voucherService.create(createVoucherRequest); @@ -59,7 +59,7 @@ void createPercentDiscountVoucherSucceed() { @Test @DisplayName("모든 바우처를 조회할 수 있다.") - void readAllVouchersSucceed() { + void readAllVouchers() { voucherService.readAll(); when(voucherRepository.findAll()).thenReturn(new ArrayList<>()); @@ -69,7 +69,7 @@ void readAllVouchersSucceed() { @Test @DisplayName("바우처를 id로 조회할 수 있다.") - void readVoucherByIdSucceed() { + void readVoucherById() { when(voucherRepository.findById(mockId)).thenReturn(Optional.of(mockVoucher)); voucherService.readById(mockId); @@ -79,7 +79,7 @@ void readVoucherByIdSucceed() { @Test @DisplayName("바우처를 id로 삭제할 수 있다.") - void deleteVoucherSucceed() { + void deleteVoucher() { voucherService.delete(mockId); verify(voucherRepository, times(1)).delete(any(UUID.class)); @@ -87,7 +87,7 @@ void deleteVoucherSucceed() { @Test @DisplayName("바우처를 업데이트할 수 있다.") - void updateVoucherSucceed() { + void updateVoucher() { when(voucherRepository.findById(mockId)).thenReturn(Optional.of(new Voucher(mockId, mockLocalDateTime, "FIXED", 130))); voucherService.update(mockId, new CreateVoucherRequest("FIXED", 100)); From c7026e7ab0452091391528fbefbf72a9a257cb4d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 00:47:57 +0900 Subject: [PATCH 338/383] refactor: remove @ConfigurationPropertiesScan annotation --- .../programmers/vouchermanagement/configuration/JdbcConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java index 6f52fbd509..3a06ffe94a 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java @@ -10,7 +10,6 @@ @Profile("jdbc") @Configuration -@ConfigurationPropertiesScan public class JdbcConfig { @Bean public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { From e099ebe018906c71e82ffd702991b0ec2d4cf104 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 15:08:45 +0900 Subject: [PATCH 339/383] refactor: implement findAllBlackCustomerAndReturnEmpty() and refactor code --- .../CustomerJDBCRepositoryTest.java | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 960d7774ef..589b847148 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -31,17 +31,6 @@ class CustomerJDBCRepositoryTest { customerJDBCRepository = new CustomerJDBCRepository(this.jdbcTemplate); } - @Test - @DisplayName("🆗 블랙리스트를 조회할 수 있다. 단, 블랙 고객이 없는 경우 빈 list가 반환된다.") - void findAllBlackCustomerSucceed() { - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객1", false)); - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객2", true)); - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객3", false)); - List customers = customerJDBCRepository.findAllBlackCustomer(); - assertThat(customers).isNotEmpty(); - assertThat(customers.size()).isGreaterThanOrEqualTo(1); - } - @Test @DisplayName("🆗 고객 정보를 저장할 수 있다.") void insert() { @@ -52,4 +41,34 @@ void insert() { assertThat(retrievedCustomer).isEqualTo(customer); } + + @Test + @DisplayName("🆗 블랙리스트를 조회할 수 있다. 단, 블랙 고객이 없는 경우 빈 list가 반환된다.") + void findAllBlackCustomer() { + insertCustomersWithBlackCustomers(); + List customers = customerJDBCRepository.findAllBlackCustomer(); + assertThat(customers).isNotEmpty(); + assertThat(customers.size()).isGreaterThanOrEqualTo(1); + } + + void insertCustomersWithBlackCustomers() { + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객1", false)); + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객2", true)); + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객3", false)); + } + + + @Test + @DisplayName("🚨 블랙 고객이 없는 경우 빈 list가 반환된다.") + void findAllBlackCustomerAndReturnEmpty() { + insertCustomersWithNonBlackCustomers(); + List customers = customerJDBCRepository.findAllBlackCustomer(); + assertThat(customers).isEmpty(); + } + + void insertCustomersWithNonBlackCustomers() { + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객1", false)); + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객2", false)); + customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객3", false)); + } } \ No newline at end of file From 1032186f1739bd6686d361379ad94b1439701c67 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 16:47:07 +0900 Subject: [PATCH 340/383] refactor: return deleted voucher when delete voucher --- .../voucher/controller/VoucherController.java | 4 ++-- .../vouchermanagement/voucher/service/VoucherService.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 124fcb89d3..343eab80fe 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -43,8 +43,8 @@ public VoucherResponse readById(@PathVariable("voucherId") UUID voucherId) { @DeleteMapping("/{voucherId}") @ResponseBody - public void delete(@PathVariable("voucherId") UUID voucherId) { - voucherService.delete(voucherId); + public VoucherResponse delete(@PathVariable("voucherId") UUID voucherId) { + return voucherService.delete(voucherId); } @DeleteMapping diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index fc1f735f7e..a282266866 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -58,8 +58,10 @@ public VoucherResponse readById(UUID voucherId) { return VoucherResponse.from(voucher); } - public void delete(UUID voucherId) { + public VoucherResponse delete(UUID voucherId) { + VoucherResponse voucher = readById(voucherId); voucherRepository.delete(voucherId); + return voucher; } public void deleteAll() { From 6157b1fc6e2101dd4c458b554d486ae5948667bd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 17:02:27 +0900 Subject: [PATCH 341/383] chore: add jackson-datatype-jsr310 for local-datetime parsing while test --- build.gradle | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index bb64bc5e5f..eb3061aa0d 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ dependencies { implementation 'org.codehaus.woodstox:woodstox-core-asl:4.4.1' runtimeOnly 'mysql:mysql-connector-java:8.0.33' implementation 'org.beryx:text-io:3.4.1' + testImplementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' testImplementation 'org.springframework.boot:spring-boot-starter-test' } @@ -33,10 +34,10 @@ version = '0.0.1-SNAPSHOT' description = 'voucherManagement' java.sourceCompatibility = JavaVersion.VERSION_17 -tasks.withType(JavaCompile) { +tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' } -tasks.withType(Javadoc) { +tasks.withType(Javadoc).configureEach { options.encoding = 'UTF-8' } \ No newline at end of file From 06d137973768d3fdea58bd097bc71a28fda60e06 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 17:03:44 +0900 Subject: [PATCH 342/383] test: test voucher rest controller without readAllByCreatedAt, readAllByType --- .../controller/VoucherControllerTest.java | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java new file mode 100644 index 0000000000..b12a3dbd1f --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java @@ -0,0 +1,143 @@ +package com.programmers.vouchermanagement.voucher.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.service.VoucherService; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(VoucherController.class) +@ActiveProfiles("api") +class VoucherControllerTest { + static ObjectMapper objectMapper; + static List vouchers; + static Voucher voucher; + static UUID voucherId; + static CreateVoucherRequest createVoucherRequest; + static VoucherResponse voucherResponse; + + @Autowired + MockMvc mockMvc; + @MockBean + VoucherService voucherService; + + @BeforeAll + static void init() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + vouchers = List.of( + VoucherResponse.from(new Voucher("FIXED", 100)), + VoucherResponse.from(new Voucher("PERCENT", 50)) + ); + + createVoucherRequest = new CreateVoucherRequest("PERCENT", 50); + voucher = new Voucher(createVoucherRequest.typeName(), createVoucherRequest.discountValue()); + voucherId = voucher.getId(); + voucherResponse = VoucherResponse.from(voucher); + } + + @Test + @DisplayName("바우처 생성을 요청한다.") + void createVoucher() throws Exception { + when(voucherService.create(createVoucherRequest)).thenReturn(voucherResponse); + + String response = mockMvc.perform(post("/api/v1/vouchers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createVoucherRequest))) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(voucherResponse)); + } + + @Test + @DisplayName("모든 바우처 조회를 요청한다.") + void readAllVouchers() throws Exception { + when(voucherService.readAll()).thenReturn(vouchers); + + String response = mockMvc.perform(get("/api/v1/vouchers")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchers)); + } + + @Test + @DisplayName("바우처 id로 바우처 조회를 요청한다.") + void readVoucherById() throws Exception { + when(voucherService.readById(voucherId)).thenReturn(voucherResponse); + + String response = mockMvc.perform(get("/api/v1/vouchers/" + voucherId.toString())) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(voucherResponse)); + } + + @Test + @DisplayName("바우처 id로 바우처를 삭제한다.") + void deleteVoucher() throws Exception { + when(voucherService.delete(voucherId)).thenReturn(voucherResponse); + + String response = mockMvc.perform(delete("/api/v1/vouchers/" + voucherId.toString())) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(voucherResponse)); + } + + @Test + @DisplayName("바우처 id로 바우처를 업데이트한다.") + void update() throws Exception { + CreateVoucherRequest updateVoucherRequest = new CreateVoucherRequest("FIXED", 100000); + VoucherResponse updatedVoucherResponse = new VoucherResponse(voucherId, voucher.getCreatedAt(), createVoucherRequest.typeName(), createVoucherRequest.discountValue()); + when(voucherService.update(voucherId, updateVoucherRequest)).thenReturn(updatedVoucherResponse); + + String response = mockMvc.perform(put("/api/v1/vouchers/" + voucherId.toString()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateVoucherRequest))) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(updatedVoucherResponse)); + } + +// @Test +// void readAllByCreatedAt() { +// } +// +// @Test +// void readAllByType() { +// } +} \ No newline at end of file From f22e87402cb706bc2b60baab46629f18bd6f66ba Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 17:48:12 +0900 Subject: [PATCH 343/383] refactor: refactor WalletJDBCRepositoryTest code --- .../repository/WalletJDBCRepositoryTest.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index e0a6090d18..f0d042c6d6 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -53,8 +53,9 @@ void injectionTest() { @DisplayName("🆗 고객에게 바우처를 할당할 수 있다.") void save() { Voucher voucher = new Voucher("FIXED", 333); - voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처 주인"); + + voucherJDBCRepository.insert(voucher); customerJDBCRepository.insert(customer); Ownership newOwnership = new Ownership(voucher.getId(), customer.getId()); @@ -65,10 +66,10 @@ void save() { @DisplayName("🚨 이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") void saveAllocatedVoucher() { Voucher voucher = new Voucher("FIXED", 333); - voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "바우처를 가진 고객"); - customerJDBCRepository.insert(customer); + voucherJDBCRepository.insert(voucher); + customerJDBCRepository.insert(customer); walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); Customer customer2 = new Customer(UUID.randomUUID(), "바우처를 가지지 못하는 고객"); @@ -127,10 +128,10 @@ void findAllVoucherByNonExistentCustomerId() { @DisplayName("🆗 바우처 id를 통해 할당 정보를 삭제할 수 있다. 단, 바우처 자체는 삭제되지 않는다.") void delete() { Voucher voucher = new Voucher("FIXED", 333); - voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "1개의 삭제될 바우처를 가진 주인"); - customerJDBCRepository.insert(customer); + voucherJDBCRepository.insert(voucher); + customerJDBCRepository.insert(customer); walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); walletJDBCRepository.delete(voucher.getId()); @@ -152,10 +153,10 @@ void deleteNonAllocatedVoucher() { @DisplayName("🆗 바우처 id로 바우처를 가진 고객 정보를 가져올 수 있다.") void findCustomerByVoucherId() { Voucher voucher = new Voucher("FIXED", 555); - voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "조회될 고객"); - customerJDBCRepository.insert(customer); + voucherJDBCRepository.insert(voucher); + customerJDBCRepository.insert(customer); walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); Optional retrievedCustomer = walletJDBCRepository.findCustomerByVoucherId(voucher.getId()); @@ -174,10 +175,10 @@ void findCustomerByNonExistentVoucherId() { @DisplayName("🆗 바우처 자체를 삭제하면, 바우처 소유 정보가 사라진다.") void autoDeleteAfterVoucherDelete() { Voucher voucher = new Voucher("FIXED", 555); - voucherJDBCRepository.insert(voucher); Customer customer = new Customer(UUID.randomUUID(), "삭제될 바우처를 가진 고객"); - customerJDBCRepository.insert(customer); + voucherJDBCRepository.insert(voucher); + customerJDBCRepository.insert(customer); walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); voucherJDBCRepository.delete(voucher.getId()); From 07a74b4def84fa2ccd760784d63eeef2d54d3b75 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 17:51:03 +0900 Subject: [PATCH 344/383] fix: fix deleteVoucher test at VoucherServiceTest --- .../vouchermanagement/voucher/service/VoucherServiceTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 9ada527837..96eed8c028 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -80,6 +80,8 @@ void readVoucherById() { @Test @DisplayName("바우처를 id로 삭제할 수 있다.") void deleteVoucher() { + when(voucherRepository.findById(mockId)).thenReturn(Optional.of(mockVoucher)); + voucherService.delete(mockId); verify(voucherRepository, times(1)).delete(any(UUID.class)); From 8f69208b1706d267bc5994b60f0d5958d15471ed Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 18:36:48 +0900 Subject: [PATCH 345/383] refactor: return CustomerResponse when insert customer --- .../customer/controller/CustomerController.java | 4 ++-- .../vouchermanagement/customer/service/CustomerService.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 0937e3df7f..185204766f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -24,8 +24,8 @@ public CustomerController(CustomerService customerService) { @PostMapping @ResponseBody - public void create(CreateCustomerRequest createCustomerRequest) { - customerService.create(createCustomerRequest); + public CustomerResponse create(CreateCustomerRequest createCustomerRequest) { + return customerService.create(createCustomerRequest); } @GetMapping diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index dab63e9949..041b59e760 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -1,8 +1,8 @@ package com.programmers.vouchermanagement.customer.service; -import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import org.springframework.stereotype.Service; @@ -18,9 +18,10 @@ public CustomerService(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } - public void create(CreateCustomerRequest createCustomerRequest) { + public CustomerResponse create(CreateCustomerRequest createCustomerRequest) { Customer customer = new Customer(UUID.randomUUID(), createCustomerRequest.name(), createCustomerRequest.isBlack()); customerRepository.insert(customer); + return CustomerResponse.from(customer); } public List readAll() { From 3475505b9b3eb83e3afd6d56f41b6833e0a709b9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 18:41:51 +0900 Subject: [PATCH 346/383] fix: add @RequestBody at create customer method parameter --- .../customer/controller/CustomerController.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java index 185204766f..08ee53ada3 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java @@ -5,10 +5,7 @@ import com.programmers.vouchermanagement.customer.service.CustomerService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -24,7 +21,7 @@ public CustomerController(CustomerService customerService) { @PostMapping @ResponseBody - public CustomerResponse create(CreateCustomerRequest createCustomerRequest) { + public CustomerResponse create(@RequestBody CreateCustomerRequest createCustomerRequest) { return customerService.create(createCustomerRequest); } From 182b6eaec720cbc1823e801313ce434c6b15437c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 19:52:13 +0900 Subject: [PATCH 347/383] refactor: refactor uuid created in the customer constructor --- .../customer/domain/Customer.java | 10 ++++++---- .../customer/service/CustomerService.java | 3 +-- .../customer/domain/CustomerTest.java | 2 +- .../repository/CustomerJDBCRepositoryTest.java | 15 +++++++-------- .../repository/WalletJDBCRepositoryTest.java | 16 ++++++++-------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index aaa479f8be..82c629655d 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -8,14 +8,16 @@ public class Customer { private final String name; private final boolean black; - public Customer(UUID id, String name) { - this(id, name, false); + public Customer(UUID id, String name, boolean black) { + this.id = id; + this.name = name; + this.black = black; } - public Customer(UUID id, String name, boolean black) { + public Customer(String name, boolean black) { if (name == null || name.isBlank() || name.length() > 20) throw new IllegalArgumentException("The name length should be between 0 to 20."); - this.id = id; + this.id = UUID.randomUUID(); this.name = name; this.black = black; } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 041b59e760..23e2be3147 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -8,7 +8,6 @@ import java.util.Collections; import java.util.List; -import java.util.UUID; @Service public class CustomerService { @@ -19,7 +18,7 @@ public CustomerService(CustomerRepository customerRepository) { } public CustomerResponse create(CreateCustomerRequest createCustomerRequest) { - Customer customer = new Customer(UUID.randomUUID(), createCustomerRequest.name(), createCustomerRequest.isBlack()); + Customer customer = new Customer(createCustomerRequest.name(), createCustomerRequest.isBlack()); customerRepository.insert(customer); return CustomerResponse.from(customer); } diff --git a/src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java index 84a4b24c62..6a71c205b8 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/domain/CustomerTest.java @@ -16,7 +16,7 @@ class CustomerTest { @ValueSource(strings = {"", " ", "123456789012345678901"}) void customerNameNullBlankOver20(String input) { assertThrows(IllegalArgumentException.class, () -> { - new Customer(UUID.randomUUID(), input, true); + new Customer(input, true); }); } diff --git a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java index 589b847148..670329c4cf 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepositoryTest.java @@ -13,7 +13,6 @@ import java.util.Collections; import java.util.List; -import java.util.UUID; import static com.programmers.vouchermanagement.util.DomainMapper.ID_KEY; import static org.assertj.core.api.Assertions.assertThat; @@ -34,7 +33,7 @@ class CustomerJDBCRepositoryTest { @Test @DisplayName("🆗 고객 정보를 저장할 수 있다.") void insert() { - Customer customer = new Customer(UUID.randomUUID(), "고객4"); + Customer customer = new Customer("고객4", true); customerJDBCRepository.insert(customer); Customer retrievedCustomer = jdbcTemplate .queryForObject("SELECT * FROM customers WHERE id = UUID_TO_BIN(:id)", Collections.singletonMap(ID_KEY, customer.getId().toString().getBytes()), CustomerDomainMapper.customerRowMapper); @@ -52,9 +51,9 @@ void findAllBlackCustomer() { } void insertCustomersWithBlackCustomers() { - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객1", false)); - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객2", true)); - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객3", false)); + customerJDBCRepository.insert(new Customer("고객1", false)); + customerJDBCRepository.insert(new Customer("고객2", true)); + customerJDBCRepository.insert(new Customer("고객3", false)); } @@ -67,8 +66,8 @@ void findAllBlackCustomerAndReturnEmpty() { } void insertCustomersWithNonBlackCustomers() { - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객1", false)); - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객2", false)); - customerJDBCRepository.insert(new Customer(UUID.randomUUID(), "고객3", false)); + customerJDBCRepository.insert(new Customer("고객1", false)); + customerJDBCRepository.insert(new Customer("고객2", false)); + customerJDBCRepository.insert(new Customer("고객3", false)); } } \ No newline at end of file diff --git a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java index f0d042c6d6..c0e998c8b2 100644 --- a/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepositoryTest.java @@ -53,7 +53,7 @@ void injectionTest() { @DisplayName("🆗 고객에게 바우처를 할당할 수 있다.") void save() { Voucher voucher = new Voucher("FIXED", 333); - Customer customer = new Customer(UUID.randomUUID(), "바우처 주인"); + Customer customer = new Customer("바우처 주인", false); voucherJDBCRepository.insert(voucher); customerJDBCRepository.insert(customer); @@ -66,13 +66,13 @@ void save() { @DisplayName("🚨 이미 할당된 바우처라면, 고객에게 바우처를 할당할 수 없다.") void saveAllocatedVoucher() { Voucher voucher = new Voucher("FIXED", 333); - Customer customer = new Customer(UUID.randomUUID(), "바우처를 가진 고객"); + Customer customer = new Customer("바우처를 가진 고객", false); voucherJDBCRepository.insert(voucher); customerJDBCRepository.insert(customer); walletJDBCRepository.insert(new Ownership(voucher.getId(), customer.getId())); - Customer customer2 = new Customer(UUID.randomUUID(), "바우처를 가지지 못하는 고객"); + Customer customer2 = new Customer("바우처를 가지지 못하는 고객", false); customerJDBCRepository.insert(customer2); assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(voucher.getId(), customer2.getId()))); @@ -90,7 +90,7 @@ void saveNonExistentCustomer() { @Test @DisplayName("🚨 바우처 id에 해당하는 바우처가 없다면, 바우처를 고객에게 할당할 수 없다.") void saveNonExistentVoucher() { - Customer customer = new Customer(UUID.randomUUID(), "바우처를 가지지 못한 고객"); + Customer customer = new Customer("바우처를 가지지 못한 고객", false); customerJDBCRepository.insert(customer); assertThrows(RuntimeException.class, () -> walletJDBCRepository.insert(new Ownership(NON_EXISTENT_VOUCHER_ID, customer.getId()))); @@ -105,7 +105,7 @@ void saveNonExistentBoth() { @Test @DisplayName("🆗 고객 id로 고객이 가진 바우처들을 가져올 수 있다.") void findAllVoucherByCustomerId() { - Customer customer = new Customer(UUID.randomUUID(), "조회하려는 바우처들의 주인"); + Customer customer = new Customer("조회하려는 바우처들의 주인", false); customerJDBCRepository.insert(customer); for (int i = 1; i < 6; i++) { @@ -128,7 +128,7 @@ void findAllVoucherByNonExistentCustomerId() { @DisplayName("🆗 바우처 id를 통해 할당 정보를 삭제할 수 있다. 단, 바우처 자체는 삭제되지 않는다.") void delete() { Voucher voucher = new Voucher("FIXED", 333); - Customer customer = new Customer(UUID.randomUUID(), "1개의 삭제될 바우처를 가진 주인"); + Customer customer = new Customer("1개의 삭제될 바우처를 가진 주인", false); voucherJDBCRepository.insert(voucher); customerJDBCRepository.insert(customer); @@ -153,7 +153,7 @@ void deleteNonAllocatedVoucher() { @DisplayName("🆗 바우처 id로 바우처를 가진 고객 정보를 가져올 수 있다.") void findCustomerByVoucherId() { Voucher voucher = new Voucher("FIXED", 555); - Customer customer = new Customer(UUID.randomUUID(), "조회될 고객"); + Customer customer = new Customer("조회될 고객", false); voucherJDBCRepository.insert(voucher); customerJDBCRepository.insert(customer); @@ -175,7 +175,7 @@ void findCustomerByNonExistentVoucherId() { @DisplayName("🆗 바우처 자체를 삭제하면, 바우처 소유 정보가 사라진다.") void autoDeleteAfterVoucherDelete() { Voucher voucher = new Voucher("FIXED", 555); - Customer customer = new Customer(UUID.randomUUID(), "삭제될 바우처를 가진 고객"); + Customer customer = new Customer("삭제될 바우처를 가진 고객", false); voucherJDBCRepository.insert(voucher); customerJDBCRepository.insert(customer); From 031a55b6013df80ea4d30ed3686e98995717fecc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 20:02:12 +0900 Subject: [PATCH 348/383] test: test Customer rest Controller --- .../controller/CustomerControllerTest.java | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerControllerTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerControllerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerControllerTest.java new file mode 100644 index 0000000000..97890f8651 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerControllerTest.java @@ -0,0 +1,102 @@ +package com.programmers.vouchermanagement.customer.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.service.CustomerService; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(CustomerController.class) +@ActiveProfiles("api") +class CustomerControllerTest { + static ObjectMapper objectMapper; + static List customers; + static List blacklist; + static Customer customer; + static CreateCustomerRequest createCustomerRequest; + static CustomerResponse customerResponse; + + @Autowired + MockMvc mockMvc; + @MockBean + CustomerService customerService; + + @BeforeAll + static void init() { + objectMapper = new ObjectMapper(); + + customers = List.of( + CustomerResponse.from(new Customer("customer1", false)), + CustomerResponse.from(new Customer("customer2", true)) + ); + blacklist = List.of( + CustomerResponse.from(new Customer("customer3", true)), + CustomerResponse.from(new Customer("customer4", true)) + ); + + createCustomerRequest = new CreateCustomerRequest("customer5", true); + customer = new Customer(createCustomerRequest.name(), createCustomerRequest.isBlack()); + customerResponse = CustomerResponse.from(customer); + } + + @Test + @DisplayName("고객 생성을 요청한다.") + void createCustomer() throws Exception { + when(customerService.create(createCustomerRequest)).thenReturn(customerResponse); + + String response = mockMvc.perform(post("/api/v1/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createCustomerRequest))) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(customerResponse)); + } + + @Test + @DisplayName("모든 고객 조회를 요청한다.") + void readAllCustomers() throws Exception { + when(customerService.readAll()).thenReturn(customers); + + String response = mockMvc.perform(get("/api/v1/customers")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(customers)); + } + + @Test + @DisplayName("모든 블랙리스트 고객 조회를 요청한다.") + void readAllBlacklist() throws Exception { + when(customerService.readAllBlackCustomer()).thenReturn(blacklist); + + String response = mockMvc.perform(get("/api/v1/customers/blacklist")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(blacklist)); + } +} \ No newline at end of file From 2f91647eb353d7925c681eb4ca9a03af37b9e227 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 7 Nov 2023 20:16:02 +0900 Subject: [PATCH 349/383] refactor: apply @Transactional --- .../customer/service/CustomerService.java | 4 ++++ .../voucher/service/VoucherService.java | 9 +++++++++ .../vouchermanagement/wallet/service/WalletService.java | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 23e2be3147..824ec11481 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -5,6 +5,7 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; @@ -17,12 +18,14 @@ public CustomerService(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } + @Transactional public CustomerResponse create(CreateCustomerRequest createCustomerRequest) { Customer customer = new Customer(createCustomerRequest.name(), createCustomerRequest.isBlack()); customerRepository.insert(customer); return CustomerResponse.from(customer); } + @Transactional(readOnly = true) public List readAll() { List customers = customerRepository.findAll(); if (customers.isEmpty()) { @@ -31,6 +34,7 @@ public List readAll() { return customers.stream().map(CustomerResponse::from).toList(); } + @Transactional(readOnly = true) public List readAllBlackCustomer() { List blacklist = customerRepository.findAllBlackCustomer(); if (blacklist.isEmpty()) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index a282266866..bb4a86fc83 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -7,6 +7,7 @@ import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherTypeManager; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.*; @@ -21,12 +22,14 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } + @Transactional public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { Voucher voucher = new Voucher(createVoucherRequest.typeName(), createVoucherRequest.discountValue()); voucherRepository.insert(voucher); return VoucherResponse.from(voucher); } + @Transactional(readOnly = true) public List readAll() { List vouchers = voucherRepository.findAll(); @@ -39,6 +42,7 @@ public List readAll() { .toList(); } + @Transactional(readOnly = true) public List readAllByCreatedAt(LocalDateTime from, LocalDateTime to) { List vouchers = voucherRepository.findAllByCreatedAt(from, to); @@ -51,6 +55,7 @@ public List readAllByCreatedAt(LocalDateTime from, LocalDateTim .toList(); } + @Transactional(readOnly = true) public VoucherResponse readById(UUID voucherId) { Optional voucherOptional = voucherRepository .findById(voucherId); @@ -58,16 +63,19 @@ public VoucherResponse readById(UUID voucherId) { return VoucherResponse.from(voucher); } + @Transactional public VoucherResponse delete(UUID voucherId) { VoucherResponse voucher = readById(voucherId); voucherRepository.delete(voucherId); return voucher; } + @Transactional public void deleteAll() { voucherRepository.deleteAll(); } + @Transactional public VoucherResponse update(UUID voucherId, CreateVoucherRequest createVoucherRequest) { // TODO: modify code format VoucherResponse voucherResponse = readById(voucherId); @@ -76,6 +84,7 @@ public VoucherResponse update(UUID voucherId, CreateVoucherRequest createVoucher return VoucherResponse.from(voucher); } + @Transactional(readOnly = true) public List readAllByType(String typeName) { VoucherType voucherType = VoucherTypeManager.get(typeName); return voucherRepository.findAllByType(voucherType).stream().map(VoucherResponse::from).toList(); diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index 2a39c447af..329c32c661 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -9,6 +9,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.*; @@ -27,6 +28,7 @@ public void allocate(Ownership ownership) { walletRepository.insert(ownership); } + @Transactional(readOnly = true) public CustomerResponse readCustomerByVoucherId(UUID voucherId) { Optional customerOptional = walletRepository.findCustomerByVoucherId(voucherId); Customer customer = customerOptional.orElseThrow(() -> { @@ -36,16 +38,19 @@ public CustomerResponse readCustomerByVoucherId(UUID voucherId) { return CustomerResponse.from(customer); } + @Transactional(readOnly = true) public List readAllVoucherByCustomerId(UUID customerId) { List vouchers = walletRepository.findAllVoucherByCustomerId(customerId); if (vouchers.isEmpty()) return Collections.emptyList(); return vouchers.stream().map(VoucherResponse::from).toList(); } + @Transactional public void deleteVoucherFromCustomer(UUID voucherId) { walletRepository.delete(voucherId); } + @Transactional public void deleteAllAllocation() { walletRepository.deleteAll(); } From 7978530d48a369ff510b9c7d683a950a2cd7f098 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 17:55:42 +0900 Subject: [PATCH 350/383] refactor: split CustomerController --- ...er.java => CustomerConsoleController.java} | 16 ++----- .../controller/CustomerRestController.java | 45 +++++++++++++++++++ 2 files changed, 49 insertions(+), 12 deletions(-) rename src/main/java/com/programmers/vouchermanagement/customer/controller/{CustomerController.java => CustomerConsoleController.java} (66%) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerConsoleController.java similarity index 66% rename from src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java rename to src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerConsoleController.java index 08ee53ada3..ee41d1709c 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerConsoleController.java @@ -5,34 +5,26 @@ import com.programmers.vouchermanagement.customer.service.CustomerService; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; import java.util.List; -@Profile({"api", "console"}) -@RequestMapping("/api/v1/customers") +@Profile("console") @Controller -public class CustomerController { +public class CustomerConsoleController { private final CustomerService customerService; - public CustomerController(CustomerService customerService) { + public CustomerConsoleController(CustomerService customerService) { this.customerService = customerService; } - @PostMapping - @ResponseBody - public CustomerResponse create(@RequestBody CreateCustomerRequest createCustomerRequest) { + public CustomerResponse create(CreateCustomerRequest createCustomerRequest) { return customerService.create(createCustomerRequest); } - @GetMapping - @ResponseBody public List readAll() { return customerService.readAll(); } - @GetMapping("/blacklist") - @ResponseBody public List readAllBlackCustomer() { return customerService.readAllBlackCustomer(); } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java new file mode 100644 index 0000000000..87ad5a335b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java @@ -0,0 +1,45 @@ +package com.programmers.vouchermanagement.customer.controller; + +import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.service.CustomerService; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Profile("api") +@RequestMapping("/api/v1/customers") +@RestController +public class CustomerRestController { + private final CustomerService customerService; + + public CustomerRestController(CustomerService customerService) { + this.customerService = customerService; + } + + @PostMapping + public ResponseEntity create( + @RequestBody + CreateCustomerRequest createCustomerRequest + ) { + return ResponseEntity.status(HttpStatus.CREATED) + .body(customerService.create(createCustomerRequest)); + } + + @GetMapping + public ResponseEntity> readAll( + @RequestParam(name = "type", required = false) + String type + ) { + if (type == null || type.equals("all")) + return ResponseEntity.status(HttpStatus.OK) + .body(customerService.readAll()); + + return ResponseEntity.status(HttpStatus.OK) + .body(customerService.readAllBlackCustomer()); + + } +} From fa0828336bdf55979c2768d28f7af1b33d6a412a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 17:55:56 +0900 Subject: [PATCH 351/383] test: test CustomerRestController --- ...t.java => CustomerRestControllerTest.java} | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) rename src/test/java/com/programmers/vouchermanagement/customer/controller/{CustomerControllerTest.java => CustomerRestControllerTest.java} (85%) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerControllerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerRestControllerTest.java similarity index 85% rename from src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerControllerTest.java rename to src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerRestControllerTest.java index 97890f8651..32fe0dd5cd 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerRestControllerTest.java @@ -23,9 +23,9 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@WebMvcTest(CustomerController.class) +@WebMvcTest(CustomerRestController.class) @ActiveProfiles("api") -class CustomerControllerTest { +class CustomerRestControllerTest { static ObjectMapper objectMapper; static List customers; static List blacklist; @@ -64,7 +64,7 @@ void createCustomer() throws Exception { String response = mockMvc.perform(post("/api/v1/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(createCustomerRequest))) - .andExpect(status().isOk()) + .andExpect(status().isCreated()) .andReturn() .getResponse() .getContentAsString(); @@ -74,7 +74,7 @@ void createCustomer() throws Exception { @Test @DisplayName("모든 고객 조회를 요청한다.") - void readAllCustomers() throws Exception { + void readAllCustomers1() throws Exception { when(customerService.readAll()).thenReturn(customers); String response = mockMvc.perform(get("/api/v1/customers")) @@ -86,12 +86,26 @@ void readAllCustomers() throws Exception { assertThat(response).isEqualTo(objectMapper.writeValueAsString(customers)); } + @Test + @DisplayName("모든 고객 조회를 요청한다. + 쿼리 스트링 사용(type=all)") + void readAllCustomers2() throws Exception { + when(customerService.readAll()).thenReturn(customers); + + String response = mockMvc.perform(get("/api/v1/customers?type=all")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(customers)); + } + @Test @DisplayName("모든 블랙리스트 고객 조회를 요청한다.") void readAllBlacklist() throws Exception { when(customerService.readAllBlackCustomer()).thenReturn(blacklist); - String response = mockMvc.perform(get("/api/v1/customers/blacklist")) + String response = mockMvc.perform(get("/api/v1/customers?type=blacklist")) .andExpect(status().isOk()) .andReturn() .getResponse() From acf8aa512ac2f0c7c3ee671de79a868c61db2ac1 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 17:56:23 +0900 Subject: [PATCH 352/383] refactor: apply CustomerConsoleController --- .../vouchermanagement/consoleapp/menu/MenuHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 95b79e9491..4b6a8b3b5c 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -1,7 +1,7 @@ package com.programmers.vouchermanagement.consoleapp.menu; import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; -import com.programmers.vouchermanagement.customer.controller.CustomerController; +import com.programmers.vouchermanagement.customer.controller.CustomerConsoleController; import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; import com.programmers.vouchermanagement.voucher.controller.VoucherController; import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; @@ -25,9 +25,9 @@ public class MenuHandler { private final ConsoleManager consoleManager; private final VoucherController voucherController; - private final CustomerController customerController; + private final CustomerConsoleController customerController; - public MenuHandler(ConsoleManager consoleManager, VoucherController voucherController, CustomerController customerController) { + public MenuHandler(ConsoleManager consoleManager, VoucherController voucherController, CustomerConsoleController customerController) { this.consoleManager = consoleManager; this.voucherController = voucherController; this.customerController = customerController; From 690261d9038351fa60c781c4316c307b08a5be47 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 18:18:19 +0900 Subject: [PATCH 353/383] refactor: apply VoucherConsoleController --- .../vouchermanagement/consoleapp/menu/MenuHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java index 4b6a8b3b5c..28aa4c5391 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandler.java @@ -3,7 +3,7 @@ import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; import com.programmers.vouchermanagement.customer.controller.CustomerConsoleController; import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; -import com.programmers.vouchermanagement.voucher.controller.VoucherController; +import com.programmers.vouchermanagement.voucher.controller.VoucherConsoleController; import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; import org.slf4j.Logger; @@ -24,10 +24,10 @@ public class MenuHandler { //--- private final ConsoleManager consoleManager; - private final VoucherController voucherController; + private final VoucherConsoleController voucherController; private final CustomerConsoleController customerController; - public MenuHandler(ConsoleManager consoleManager, VoucherController voucherController, CustomerConsoleController customerController) { + public MenuHandler(ConsoleManager consoleManager, VoucherConsoleController voucherController, CustomerConsoleController customerController) { this.consoleManager = consoleManager; this.voucherController = voucherController; this.customerController = customerController; From 500d557a5b06aa976b67083e1ff1c96a1f47f0c7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 18:18:35 +0900 Subject: [PATCH 354/383] refactor: change code format --- .../customer/controller/CustomerRestController.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java index 87ad5a335b..c907b782fe 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerRestController.java @@ -31,15 +31,14 @@ public ResponseEntity create( @GetMapping public ResponseEntity> readAll( - @RequestParam(name = "type", required = false) + @RequestParam(name = "type", defaultValue = "all") String type ) { - if (type == null || type.equals("all")) + if (type.equals("blacklist")) return ResponseEntity.status(HttpStatus.OK) - .body(customerService.readAll()); + .body(customerService.readAllBlackCustomer()); return ResponseEntity.status(HttpStatus.OK) - .body(customerService.readAllBlackCustomer()); - + .body(customerService.readAll()); } } From 056b40afa7428d1949cbd5babb2b900a91723d77 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 21:25:47 +0900 Subject: [PATCH 355/383] refactor: implement VoucherConsoleController(split from VoucherController) --- .../controller/VoucherConsoleController.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherConsoleController.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherConsoleController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherConsoleController.java new file mode 100644 index 0000000000..78b12e73ec --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherConsoleController.java @@ -0,0 +1,27 @@ +package com.programmers.vouchermanagement.voucher.controller; + +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.service.VoucherService; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Controller; + +import java.util.List; + +@Profile("console") +@Controller +public class VoucherConsoleController { + private final VoucherService voucherService; + + public VoucherConsoleController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + return voucherService.create(createVoucherRequest); + } + + public List readAll() { + return voucherService.readAll(); + } +} From 849524ac148a25991891b24f824d320aac49c384 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 22:05:03 +0900 Subject: [PATCH 356/383] refactor: implement VoucherRestController(split from VoucherController) --- .../voucher/controller/VoucherController.java | 75 ------------ .../controller/VoucherRestController.java | 108 ++++++++++++++++++ 2 files changed, 108 insertions(+), 75 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java deleted file mode 100644 index 343eab80fe..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.programmers.vouchermanagement.voucher.controller; - -import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; -import com.programmers.vouchermanagement.voucher.service.VoucherService; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.List; -import java.util.UUID; - -@Profile({"console", "api"}) -@RequestMapping("/api/v1/vouchers") -@Controller -public class VoucherController { - private final VoucherService voucherService; - - public VoucherController(VoucherService voucherService) { - this.voucherService = voucherService; - } - - @PostMapping - @ResponseBody - public VoucherResponse create(@RequestBody CreateVoucherRequest createVoucherRequest) { - return voucherService.create(createVoucherRequest); - } - - @GetMapping - @ResponseBody - public List readAll() { - return voucherService.readAll(); - } - - @GetMapping("/{voucherId}") - @ResponseBody - public VoucherResponse readById(@PathVariable("voucherId") UUID voucherId) { - return voucherService.readById(voucherId); - } - - @DeleteMapping("/{voucherId}") - @ResponseBody - public VoucherResponse delete(@PathVariable("voucherId") UUID voucherId) { - return voucherService.delete(voucherId); - } - - @DeleteMapping - @ResponseBody - public void deleteAll() { - voucherService.deleteAll(); - } - - @PutMapping("/{voucherId}") - @ResponseBody - public VoucherResponse update(@PathVariable("voucherId") UUID voucherId, @RequestBody CreateVoucherRequest createVoucherRequest) { - return voucherService.update(voucherId, createVoucherRequest); - } - - @GetMapping("/created-at") - @ResponseBody - public List readAllByCreatedAt(@RequestParam(name = "from") LocalDate from, @RequestParam(name = "to") LocalDate to) { - LocalDateTime fromDateTime = LocalDateTime.of(from, LocalTime.of(0, 0, 0)); - LocalDateTime toDateTime = LocalDateTime.of(to, LocalTime.of(23, 59, 59)); - return voucherService.readAllByCreatedAt(fromDateTime, toDateTime); - } - - @GetMapping("type/{type}") - @ResponseBody - public List readAllByType(@PathVariable("type") String typeName) { - return voucherService.readAllByType(typeName); - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java new file mode 100644 index 0000000000..6c10795eb3 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -0,0 +1,108 @@ +package com.programmers.vouchermanagement.voucher.controller; + +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.service.VoucherService; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +@Profile("api") +@RequestMapping("/api/v1/vouchers") +@RestController +public class VoucherRestController { + private final VoucherService voucherService; + + public VoucherRestController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + @PostMapping + public ResponseEntity create( + @RequestBody + CreateVoucherRequest createVoucherRequest + ) { + return ResponseEntity.status(HttpStatus.CREATED) + .body(voucherService.create(createVoucherRequest)); + } + + @GetMapping("/{voucherId}") + public ResponseEntity readById( + @PathVariable("voucherId") + UUID voucherId + ) { + return ResponseEntity.status(HttpStatus.OK) + .body(voucherService.readById(voucherId)); + } + + @DeleteMapping("/{voucherId}") + public ResponseEntity delete( + @PathVariable("voucherId") + UUID voucherId + ) { + return ResponseEntity.status(HttpStatus.OK) + .body(voucherService.delete(voucherId)); + } + + @DeleteMapping + public ResponseEntity deleteAll() { + voucherService.deleteAll(); + return ResponseEntity.noContent() + .build(); + } + + @PutMapping("/{voucherId}") + public ResponseEntity update( + @PathVariable("voucherId") + UUID voucherId, + @RequestBody + CreateVoucherRequest createVoucherRequest + ) { + return ResponseEntity.status(HttpStatus.OK) + .body(voucherService.update(voucherId, createVoucherRequest)); + } + + @GetMapping + public ResponseEntity> searchAll( //TODO: make Object + @RequestParam(name = "filter", defaultValue = "all") + String filter, + @RequestParam(name = "from", required = false) + LocalDate from, + @RequestParam(name = "to", required = false) + LocalDate to, + @RequestParam(name = "type-name", required = false) + String typeName + ) { + if (filter.equals("all")) + return ResponseEntity.status(HttpStatus.OK) + .body(voucherService.readAll()); + + if (filter.equals("created-at") && from != null) { //TODO: validate date + LocalDateTime fromDateTime = LocalDateTime.of( + from, + LocalTime.of(0, 0, 0)); + + LocalDateTime toDateTime = LocalDateTime.of( + to == null ? LocalDate.now() : to, + LocalTime.of(23, 59, 59)); + + return ResponseEntity.status(HttpStatus.OK) + .body(voucherService.readAllByCreatedAt(fromDateTime, toDateTime)); + } + + if (filter.equals("type") && typeName != null) + return ResponseEntity.status(HttpStatus.OK) + .body(voucherService.readAllByType(typeName)); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Collections.emptyList()); //TODO: apply ControllerAdvice + } +} From 41515a4f5c86c3c0fe3e07a276c5167c0007b89e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 22:05:58 +0900 Subject: [PATCH 357/383] test: test VoucherRestController --- ...st.java => VoucherRestControllerTest.java} | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) rename src/test/java/com/programmers/vouchermanagement/voucher/controller/{VoucherControllerTest.java => VoucherRestControllerTest.java} (90%) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java similarity index 90% rename from src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java rename to src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java index b12a3dbd1f..88b23ad446 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java @@ -25,9 +25,9 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@WebMvcTest(VoucherController.class) +@WebMvcTest(VoucherRestController.class) @ActiveProfiles("api") -class VoucherControllerTest { +class VoucherRestControllerTest { static ObjectMapper objectMapper; static List vouchers; static Voucher voucher; @@ -65,7 +65,7 @@ void createVoucher() throws Exception { String response = mockMvc.perform(post("/api/v1/vouchers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(createVoucherRequest))) - .andExpect(status().isOk()) + .andExpect(status().isCreated()) .andReturn() .getResponse() .getContentAsString(); @@ -87,6 +87,20 @@ void readAllVouchers() throws Exception { assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchers)); } + @Test + @DisplayName("모든 바우처 조회를 요청한다. + 쿼리 스트링(filter=all)") + void readAllVouchersWithRequestParam() throws Exception { + when(voucherService.readAll()).thenReturn(vouchers); + + String response = mockMvc.perform(get("/api/v1/vouchers?filter=all")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchers)); + } + @Test @DisplayName("바우처 id로 바우처 조회를 요청한다.") void readVoucherById() throws Exception { From ce813fdd8c8c0a6286e6a012eb196cac885dbdd3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 22:09:56 +0900 Subject: [PATCH 358/383] refactor: split validate method at customer --- .../vouchermanagement/customer/domain/Customer.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 82c629655d..5d2dac7295 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -15,13 +15,17 @@ public Customer(UUID id, String name, boolean black) { } public Customer(String name, boolean black) { - if (name == null || name.isBlank() || name.length() > 20) - throw new IllegalArgumentException("The name length should be between 0 to 20."); this.id = UUID.randomUUID(); + validateName(name); this.name = name; this.black = black; } + private void validateName(String name) { + if (name == null || name.isBlank() || name.length() > 20) + throw new IllegalArgumentException("The name length should be between 0 to 20."); + } + public UUID getId() { return id; } From 182493712bee9a1ef31e55ce6c8b2576e0d54ac3 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 22:41:18 +0900 Subject: [PATCH 359/383] style: set code format --- .../customer/repository/CustomerFileRepository.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index db0c7582d2..53778b26b7 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -32,6 +32,9 @@ public List findAll() { @Override public List findAllBlackCustomer() { - return customerFileManager.customers.values().stream().filter(Customer::isBlack).toList(); + return customerFileManager.customers.values() + .stream() + .filter(Customer::getIsBlack) + .toList(); } } \ No newline at end of file From 6e294d70f30d2771b198fedecc8b93478e1c68b8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 22:54:54 +0900 Subject: [PATCH 360/383] refactor: change field name at customer(isBlack) --- .../controller/dto/CustomerResponse.java | 2 +- .../customer/domain/Customer.java | 22 +++++++++---------- .../repository/util/CustomerDomainMapper.java | 4 ++-- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CustomerResponse.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CustomerResponse.java index a45ba27818..506ce1f6cc 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CustomerResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/dto/CustomerResponse.java @@ -6,6 +6,6 @@ public record CustomerResponse(UUID id, String name, boolean isBlack) { public static CustomerResponse from(Customer customer) { - return new CustomerResponse(customer.getId(), customer.getName(), customer.isBlack()); + return new CustomerResponse(customer.getId(), customer.getName(), customer.getIsBlack()); } } \ No newline at end of file diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 5d2dac7295..996f05336a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -6,19 +6,17 @@ public class Customer { private final UUID id; private final String name; - private final boolean black; + private final boolean isBlack; - public Customer(UUID id, String name, boolean black) { + public Customer(UUID id, String name, boolean isBlack) { + validateName(name); this.id = id; this.name = name; - this.black = black; + this.isBlack = isBlack; } - public Customer(String name, boolean black) { - this.id = UUID.randomUUID(); - validateName(name); - this.name = name; - this.black = black; + public Customer(String name, boolean isBlack) { + this(UUID.randomUUID(), name, isBlack); } private void validateName(String name) { @@ -30,8 +28,8 @@ public UUID getId() { return id; } - public boolean isBlack() { - return black; + public boolean getIsBlack() { + return isBlack; } public String getName() { @@ -43,12 +41,12 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Customer customer = (Customer) o; - return black == customer.black && Objects.equals(id, customer.id) && Objects.equals(name, customer.name); + return isBlack == customer.isBlack && Objects.equals(id, customer.id) && Objects.equals(name, customer.name); } @Override public int hashCode() { - return Objects.hash(id, name, black); + return Objects.hash(id, name, isBlack); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerDomainMapper.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerDomainMapper.java index f13fa32354..4a72f6ceb8 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerDomainMapper.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerDomainMapper.java @@ -28,7 +28,7 @@ public static Map customerToParamMap(Customer customer) { Map paramMap = new HashMap<>(); paramMap.put(ID_KEY, customer.getId().toString().getBytes()); paramMap.put(NAME_KEY, customer.getName()); - paramMap.put(BLACK_KEY, customer.isBlack()); + paramMap.put(BLACK_KEY, customer.getIsBlack()); return paramMap; } @@ -43,6 +43,6 @@ public static Customer stringToCustomer(String line) { public static String customerToString(Customer customer) { return customer.getId().toString() + COMMA_SEPARATOR + customer.getName() + COMMA_SEPARATOR - + customer.isBlack(); + + customer.getIsBlack(); } } From c8e7eaec471b2cbd6a19b02c0ac5c6a8150d0f73 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 8 Nov 2023 22:55:25 +0900 Subject: [PATCH 361/383] refactor: delete query class and apply directly --- .../repository/CustomerJDBCRepository.java | 13 +++++--- .../repository/util/CustomerQuery.java | 10 ------ .../repository/VoucherJDBCRepository.java | 33 ++++++++++++++----- .../voucher/repository/util/VoucherQuery.java | 14 -------- .../repository/WalletJDBCRepository.java | 19 +++++++---- .../wallet/repository/util/WalletQuery.java | 11 ------- 6 files changed, 46 insertions(+), 54 deletions(-) delete mode 100644 src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerQuery.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherQuery.java delete mode 100644 src/main/java/com/programmers/vouchermanagement/wallet/repository/util/WalletQuery.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java index 4241b33be5..881dbe7254 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerJDBCRepository.java @@ -12,7 +12,6 @@ import static com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper.customerRowMapper; import static com.programmers.vouchermanagement.customer.repository.util.CustomerDomainMapper.customerToParamMap; -import static com.programmers.vouchermanagement.customer.repository.util.CustomerQuery.*; import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Message.NOT_INSERTED; @@ -28,7 +27,9 @@ public CustomerJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { @Override public void insert(Customer customer) { - int update = jdbcTemplate.update(INSERT, customerToParamMap(customer)); + int update = jdbcTemplate.update( + "INSERT INTO customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)", + customerToParamMap(customer)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_INSERTED); throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); @@ -37,12 +38,16 @@ public void insert(Customer customer) { @Override public List findAllBlackCustomer() { - return jdbcTemplate.query(FIND_ALL_BLACK_CUSTOMER, customerRowMapper); + return jdbcTemplate.query( + "SELECT * FROM customers WHERE black = TRUE", + customerRowMapper); } @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL, customerRowMapper); + return jdbcTemplate.query( + "SELECT * FROM customers", + customerRowMapper); } } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerQuery.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerQuery.java deleted file mode 100644 index 942dad5fae..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerQuery.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.programmers.vouchermanagement.customer.repository.util; - -public class CustomerQuery { - public static final String FIND_ALL_BLACK_CUSTOMER = "SELECT * FROM customers WHERE black = TRUE"; - public static final String INSERT = "INSERT INTO customers(id, name, black) VALUES (UUID_TO_BIN(:id), :name, :black)"; - public static final String FIND_ALL = "SELECT * FROM customers"; - - private CustomerQuery() { - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java index 566d3fbee5..d6fdec1045 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherJDBCRepository.java @@ -15,7 +15,6 @@ import static com.programmers.vouchermanagement.util.Constant.UPDATE_ONE_FLAG; import static com.programmers.vouchermanagement.util.Message.*; import static com.programmers.vouchermanagement.voucher.repository.util.VoucherDomainMapper.*; -import static com.programmers.vouchermanagement.voucher.repository.util.VoucherQuery.*; @Profile("jdbc") @Repository @@ -29,7 +28,9 @@ public VoucherJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { @Override public void insert(Voucher voucher) { - int update = jdbcTemplate.update(INSERT, voucherToParamMap(voucher)); + int update = jdbcTemplate.update( + "INSERT INTO vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discount_value)", + voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); } @@ -37,13 +38,17 @@ public void insert(Voucher voucher) { @Override public List findAll() { - return jdbcTemplate.query(FIND_ALL, voucherRowMapper); + return jdbcTemplate.query( + "SELECT * FROM vouchers", + voucherRowMapper); } @Override public Optional findById(UUID id) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_BY_ID, Collections.singletonMap(ID_KEY, id.toString().getBytes()), voucherRowMapper)); + return Optional.ofNullable(jdbcTemplate.queryForObject( + "SELECT * FROM vouchers WHERE id = UUID_TO_BIN(:id)", + Collections.singletonMap(ID_KEY, id.toString().getBytes()), voucherRowMapper)); } catch (EmptyResultDataAccessException e) { logger.error(EMPTY_RESULT, e); return Optional.empty(); @@ -52,12 +57,16 @@ public Optional findById(UUID id) { @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { - return jdbcTemplate.query(FIND_ALL_BY_CREATED_AT, Map.of(FROM_KEY, from.toString(), TO_KEY, to.toString()), voucherRowMapper); + return jdbcTemplate.query( + "SELECT * FROM vouchers WHERE created_at BETWEEN DATE(:from) AND DATE(:to)", + Map.of(FROM_KEY, from.toString(), TO_KEY, to.toString()), voucherRowMapper); } @Override public void delete(UUID id) { - int update = jdbcTemplate.update(DELETE_VOUCHER, Collections.singletonMap(ID_KEY, id.toString().getBytes())); + int update = jdbcTemplate.update( + "DELETE FROM vouchers WHERE id = UUID_TO_BIN(:id)", + Collections.singletonMap(ID_KEY, id.toString().getBytes())); if (update != UPDATE_ONE_FLAG) { throw new NoSuchElementException(NOT_DELETED); } @@ -65,12 +74,16 @@ public void delete(UUID id) { @Override public void deleteAll() { - jdbcTemplate.update(DELETE_ALL, Collections.emptyMap()); + jdbcTemplate.update( + "DELETE FROM vouchers", + Collections.emptyMap()); } @Override public void update(Voucher voucher) { - int update = jdbcTemplate.update(UPDATE_VOUCHER, voucherToParamMap(voucher)); + int update = jdbcTemplate.update( + "UPDATE vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)", + voucherToParamMap(voucher)); if (update != UPDATE_ONE_FLAG) { throw new NoSuchElementException(NOT_UPDATED); } @@ -78,6 +91,8 @@ public void update(Voucher voucher) { @Override public List findAllByType(VoucherType type) { - return jdbcTemplate.query(FIND_ALL_BY_TYPE, Map.of(TYPE_KEY, type.getName()), voucherRowMapper); + return jdbcTemplate.query( + "SELECT * FROM vouchers WHERE type = :type", + Map.of(TYPE_KEY, type.getName()), voucherRowMapper); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherQuery.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherQuery.java deleted file mode 100644 index 1e12a3eefd..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherQuery.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.programmers.vouchermanagement.voucher.repository.util; - -public class VoucherQuery { - public static final String INSERT = "INSERT INTO vouchers(id, type, discount_value) VALUES (UUID_TO_BIN(:id), :type, :discount_value)"; - public static final String FIND_BY_ID = "SELECT * FROM vouchers WHERE id = UUID_TO_BIN(:id)"; - public static final String FIND_ALL = "SELECT * FROM vouchers"; - public static final String FIND_ALL_BY_CREATED_AT = "SELECT * FROM vouchers WHERE created_at BETWEEN DATE(:from) AND DATE(:to)"; - public static final String FIND_ALL_BY_TYPE = "SELECT * FROM vouchers WHERE type = :type"; - public static final String DELETE_VOUCHER = "DELETE FROM vouchers WHERE id = UUID_TO_BIN(:id)"; - public static final String DELETE_ALL = "DELETE FROM vouchers"; - public static final String UPDATE_VOUCHER = "UPDATE vouchers SET type = :type, discount_value = :discount_value WHERE id = UUID_TO_BIN(:id)"; - private VoucherQuery() { - } -} diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 9e047d9565..2f76eb2193 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -19,7 +19,6 @@ import static com.programmers.vouchermanagement.voucher.repository.util.VoucherDomainMapper.voucherRowMapper; import static com.programmers.vouchermanagement.wallet.repository.util.OwnershipDomainMapper.ownershipToParamMap; import static com.programmers.vouchermanagement.wallet.repository.util.OwnershipDomainMapper.uuidToParamMap; -import static com.programmers.vouchermanagement.wallet.repository.util.WalletQuery.*; @Repository public class WalletJDBCRepository implements WalletRepository { @@ -32,7 +31,9 @@ public WalletJDBCRepository(NamedParameterJdbcTemplate jdbcTemplate) { @Override public void insert(Ownership ownership) { - int update = jdbcTemplate.update(INSERT, ownershipToParamMap(ownership)); + int update = jdbcTemplate.update( + "INSERT INTO ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucher_id), UUID_TO_BIN(:customer_id))", + ownershipToParamMap(ownership)); if (update != UPDATE_ONE_FLAG) { logger.error(CAN_NOT_INSERT_OWNERSHIP); throw new EmptyResultDataAccessException(UPDATE_ONE_FLAG); @@ -42,7 +43,8 @@ public void insert(Ownership ownership) { @Override public Optional findCustomerByVoucherId(UUID voucherId) { try { - return Optional.ofNullable(jdbcTemplate.queryForObject(FIND_CUSTOMER_BY_VOUCHER_ID, + return Optional.ofNullable(jdbcTemplate.queryForObject( + "SELECT c.* FROM ownership as o JOIN customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)", Collections.singletonMap(ID_KEY, voucherId.toString().getBytes()), customerRowMapper)); } catch (EmptyResultDataAccessException e) { @@ -52,14 +54,17 @@ public Optional findCustomerByVoucherId(UUID voucherId) { @Override public List findAllVoucherByCustomerId(UUID customerId) { - return jdbcTemplate.query(FIND_ALL_VOUCHER_BY_CUSTOMER_ID, + return jdbcTemplate.query( + "SELECT v.* FROM ownership as o JOIN vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)", Collections.singletonMap(ID_KEY, customerId.toString().getBytes()), voucherRowMapper); } @Override public void delete(UUID voucherId) { - int update = jdbcTemplate.update(DELETE_OWNERSHIP, uuidToParamMap(voucherId)); + int update = jdbcTemplate.update( + "DELETE FROM ownership WHERE voucher_id = UUID_TO_BIN(:id)", + uuidToParamMap(voucherId)); if (update != UPDATE_ONE_FLAG) { logger.error(NOT_FOUND_VOUCHER_ALLOCATION); throw new NoSuchElementException(NOT_FOUND_VOUCHER_ALLOCATION); @@ -68,7 +73,9 @@ public void delete(UUID voucherId) { @Override public void deleteAll() { - int update = jdbcTemplate.update(DELETE_ALL, Collections.emptyMap()); + int update = jdbcTemplate.update( + "TRUNCATE TABLE ownership", + Collections.emptyMap()); if (update == UPDATE_ZERO_FLAG) { logger.warn(ALREADY_EMPTY_TABLE); } diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/util/WalletQuery.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/util/WalletQuery.java deleted file mode 100644 index ed366f41b1..0000000000 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/util/WalletQuery.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.programmers.vouchermanagement.wallet.repository.util; - -public class WalletQuery { - public static final String INSERT = "INSERT INTO ownership(voucher_id, customer_id) VALUES (UUID_TO_BIN(:voucher_id), UUID_TO_BIN(:customer_id))"; - public static final String DELETE_OWNERSHIP = "DELETE FROM ownership WHERE voucher_id = UUID_TO_BIN(:id)"; - public static final String DELETE_ALL = "TRUNCATE TABLE ownership"; - public static final String FIND_CUSTOMER_BY_VOUCHER_ID = "SELECT c.* FROM ownership as o JOIN customers as c ON o.customer_id = c.id WHERE o.voucher_id = uuid_to_bin(:id)"; - public static final String FIND_ALL_VOUCHER_BY_CUSTOMER_ID = "SELECT v.* FROM ownership as o JOIN vouchers as v ON o.voucher_id = v.id WHERE o.customer_id = uuid_to_bin(:id)"; - private WalletQuery() { - } -} From d6e8faa3d9377610b7ff3c86e683498a2f31eded Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 00:37:22 +0900 Subject: [PATCH 362/383] style: set code format at sql file --- src/main/resources/schema.sql | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index d8b8a7e402..7ca92265aa 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,19 +1,19 @@ -drop DATABASE if exists prod; +DROP DATABASE IF EXISTS prod; CREATE DATABASE prod; -use prod; +USE prod; CREATE TABLE customers ( id BINARY(16) PRIMARY KEY, - name varchar(20) NOT NULL, - black boolean not null, + name VARCHAR(20) NOT NULL, + black BOOLEAN NOT NULL, CONSTRAINT name UNIQUE (name) ); CREATE TABLE vouchers ( id BINARY(16) PRIMARY KEY, - type enum ('FIXED', 'PERCENT') NOT NULL, - discount_value varchar(50) NOT NULL, - created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) + type ENUM ('FIXED', 'PERCENT') NOT NULL, + discount_value VARCHAR(50) NOT NULL, + created_at DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ); CREATE TABLE ownership @@ -25,22 +25,22 @@ CREATE TABLE ownership ); -drop DATABASE if exists test; +DROP DATABASE IF EXISTS test; CREATE DATABASE test; -use test; +USE test; CREATE TABLE customers ( id BINARY(16) PRIMARY KEY, - name varchar(20) NOT NULL, - black boolean not null, + name VARCHAR(20) NOT NULL, + black BOOLEAN NOT NULL, CONSTRAINT name UNIQUE (name) ); CREATE TABLE vouchers ( id BINARY(16) PRIMARY KEY, - type enum ('FIXED', 'PERCENT') NOT NULL, - discount_value varchar(50) NOT NULL, - created_at datetime(6) DEFAULT CURRENT_TIMESTAMP(6) + type ENUM ('FIXED', 'PERCENT') NOT NULL, + discount_value VARCHAR(50) NOT NULL, + created_at DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ); CREATE TABLE ownership From 7d379d85ed0572eaa6e125b9192f78d48b2cb016 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 01:52:50 +0900 Subject: [PATCH 363/383] refactor: refactor code and write TODO --- .../voucher/controller/VoucherRestController.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 6c10795eb3..bd3009c8a7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -71,7 +71,7 @@ public ResponseEntity update( } @GetMapping - public ResponseEntity> searchAll( //TODO: make Object + public ResponseEntity> searchAll( //TODO: make Object and Validate! @RequestParam(name = "filter", defaultValue = "all") String filter, @RequestParam(name = "from", required = false) @@ -86,13 +86,14 @@ public ResponseEntity> searchAll( //TODO: make Object .body(voucherService.readAll()); if (filter.equals("created-at") && from != null) { //TODO: validate date + LocalTime localTime = LocalTime.of(0, 0, 0); LocalDateTime fromDateTime = LocalDateTime.of( from, - LocalTime.of(0, 0, 0)); + localTime); LocalDateTime toDateTime = LocalDateTime.of( - to == null ? LocalDate.now() : to, - LocalTime.of(23, 59, 59)); + to == null ? LocalDate.now() : to.plusDays(1), + localTime); return ResponseEntity.status(HttpStatus.OK) .body(voucherService.readAllByCreatedAt(fromDateTime, toDateTime)); From 8d77597134872a1d46cd11621c1a176a2e4b709d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 01:53:52 +0900 Subject: [PATCH 364/383] test: test VoucherRestController readAllByCreatedAt, readAllByType --- .../controller/VoucherRestControllerTest.java | 63 +++++++++++++++---- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java index 88b23ad446..b323430309 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java @@ -17,10 +17,13 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -48,7 +51,9 @@ static void init() { vouchers = List.of( VoucherResponse.from(new Voucher("FIXED", 100)), - VoucherResponse.from(new Voucher("PERCENT", 50)) + VoucherResponse.from(new Voucher("FIXED", 200)), + VoucherResponse.from(new Voucher("PERCENT", 50)), + VoucherResponse.from(new Voucher("PERCENT", 60)) ); createVoucherRequest = new CreateVoucherRequest("PERCENT", 50); @@ -75,7 +80,7 @@ void createVoucher() throws Exception { @Test @DisplayName("모든 바우처 조회를 요청한다.") - void readAllVouchers() throws Exception { + void readAllVouchers1() throws Exception { when(voucherService.readAll()).thenReturn(vouchers); String response = mockMvc.perform(get("/api/v1/vouchers")) @@ -89,10 +94,11 @@ void readAllVouchers() throws Exception { @Test @DisplayName("모든 바우처 조회를 요청한다. + 쿼리 스트링(filter=all)") - void readAllVouchersWithRequestParam() throws Exception { + void readAllVouchers2() throws Exception { when(voucherService.readAll()).thenReturn(vouchers); - String response = mockMvc.perform(get("/api/v1/vouchers?filter=all")) + String response = mockMvc.perform(get("/api/v1/vouchers") + .param("filter", "all")) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -101,6 +107,47 @@ void readAllVouchersWithRequestParam() throws Exception { assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchers)); } + @Test + @DisplayName("입력 기간 안에 있는 모든 바우처 조회를 요청한다. + 쿼리 스트링(filter=created-at...)") + void readAllByCreatedAt() throws Exception { + LocalDate from = LocalDate.of(2022, 12, 25); + LocalDate to = LocalDate.now(); + List vouchersCreatedBeforeNow = vouchers; + when(voucherService.readAllByCreatedAt(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(vouchersCreatedBeforeNow); + + String response = mockMvc.perform(get("/api/v1/vouchers") + .param("filter", "created-at") + .param("from", from.toString()) + .param("to", to.toString())) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchersCreatedBeforeNow)); + } + + @Test + @DisplayName("입력 타입에 해당하는 모든 바우처 조회를 요청한다. + 쿼리 스트링(filter=type...)") + void readAllByType() throws Exception { + String typeName = "FIXED"; + List vouchersCreatedAsPercent = vouchers.stream() + .filter((voucher) -> voucher.typeName().equals(typeName)) + .toList(); + when(voucherService.readAllByType(typeName)).thenReturn(vouchersCreatedAsPercent); + + String response = mockMvc.perform(get("/api/v1/vouchers") + .param("filter", "type") + .param("type-name", typeName)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchersCreatedAsPercent)); + } + @Test @DisplayName("바우처 id로 바우처 조회를 요청한다.") void readVoucherById() throws Exception { @@ -146,12 +193,4 @@ void update() throws Exception { assertThat(response).isEqualTo(objectMapper.writeValueAsString(updatedVoucherResponse)); } - -// @Test -// void readAllByCreatedAt() { -// } -// -// @Test -// void readAllByType() { -// } } \ No newline at end of file From 3da3110b4e925ae4c88ab031157f787e64ce1041 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 01:54:35 +0900 Subject: [PATCH 365/383] refactor: change method name --- .../voucher/controller/VoucherRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index bd3009c8a7..796208daf3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -71,7 +71,7 @@ public ResponseEntity update( } @GetMapping - public ResponseEntity> searchAll( //TODO: make Object and Validate! + public ResponseEntity> readAll( //TODO: make Object and Validate! @RequestParam(name = "filter", defaultValue = "all") String filter, @RequestParam(name = "from", required = false) From 09a684b258b8bd12b17c4c8082ac974d21d9f16b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 01:57:15 +0900 Subject: [PATCH 366/383] refactor: delete useless method --- .../voucher/controller/VoucherRestController.java | 7 ------- .../voucher/controller/VoucherThymeleafController.java | 6 ------ 2 files changed, 13 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 796208daf3..93ba0adc90 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -52,13 +52,6 @@ public ResponseEntity delete( .body(voucherService.delete(voucherId)); } - @DeleteMapping - public ResponseEntity deleteAll() { - voucherService.deleteAll(); - return ResponseEntity.noContent() - .build(); - } - @PutMapping("/{voucherId}") public ResponseEntity update( @PathVariable("voucherId") diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java index 06564caa73..c091707711 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafController.java @@ -56,12 +56,6 @@ public String delete(@PathVariable("voucherId") UUID voucherId) { return "redirect:/vouchers"; } - @DeleteMapping - public String deleteAll() { - voucherService.deleteAll(); - return "redirect:/vouchers"; - } - @PutMapping("/update/{voucherId}") public String update(@PathVariable("voucherId") UUID voucherId, CreateVoucherRequest createVoucherRequest) { voucherService.update(voucherId, createVoucherRequest); From 0be97c64268c973689b5c950c62d64145029079a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 02:52:12 +0900 Subject: [PATCH 367/383] refactor: exclude autoconfigure datasource when file profile active --- .../configuration/JdbcConfig.java | 1 - src/main/resources/application.yaml | 22 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java index 3a06ffe94a..2d233cb4f0 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/JdbcConfig.java @@ -1,6 +1,5 @@ package com.programmers.vouchermanagement.configuration; -import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 06f3665344..3a496bde22 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,21 +1,31 @@ spring: - datasource: - url: jdbc:mysql://localhost:3306/prod - username: ${USER} - password: ${PASSWORD} + config: + activate: + on-profile: api, thyme mvc: hidden-method: filter: enabled: true --- +spring: + config: + activate: + on-profile: jdbc + datasource: + url: jdbc:mysql://localhost:3306/prod + username: ${USER} + password: ${PASSWORD} +--- spring: config: activate: on-profile: file + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration file: resources: path: src/main/resources/ - domains: customer: file-name: blacklist.csv @@ -34,10 +44,8 @@ spring: file: resources: path: src/test/resources/ - domains: customer: file-name: blacklist.csv - voucher: file-name: voucher.json From 2ea4072134c75f31e280be4a5acde7a1b6f302da Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 02:55:34 +0900 Subject: [PATCH 368/383] refactor: refactor FileRepository --- .../repository/CustomerFileRepository.java | 15 +++--- .../repository/util/CustomerFileManager.java | 9 ++-- .../repository/VoucherFileRepository.java | 51 ++++++++++--------- .../repository/util/VoucherFileManager.java | 17 +++---- 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java index 53778b26b7..05c7340a02 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/CustomerFileRepository.java @@ -2,37 +2,38 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.util.CustomerFileManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Map; +import java.util.UUID; @Repository @Profile({"file", "memory"}) public class CustomerFileRepository implements CustomerRepository { - private static final Logger logger = LoggerFactory.getLogger(CustomerFileRepository.class); + public final Map customers; private final CustomerFileManager customerFileManager; public CustomerFileRepository(CustomerFileManager customerFileManager) { this.customerFileManager = customerFileManager; + customers = customerFileManager.loadFile(); } @Override public void insert(Customer customer) { - customerFileManager.customers.put(customer.getId(), customer); - customerFileManager.saveFile(); + customers.put(customer.getId(), customer); + customerFileManager.saveFile(customers); } @Override public List findAll() { - return customerFileManager.customers.values().stream().toList(); + return customers.values().stream().toList(); } @Override public List findAllBlackCustomer() { - return customerFileManager.customers.values() + return customers.values() .stream() .filter(Customer::getIsBlack) .toList(); diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java index 1ea6ea1e80..9f68ca592b 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java @@ -21,16 +21,14 @@ @Profile("file") public class CustomerFileManager { private static final Logger logger = LoggerFactory.getLogger(CustomerFileManager.class); - public final Map customers; private final String filePath; public CustomerFileManager(AppProperties appProperties) { this.filePath = appProperties.resources().path() + appProperties.domains().get("customer").fileName(); - this.customers = new HashMap<>(); - loadFile(); } - private void loadFile() { + public Map loadFile() { + Map customers = new HashMap<>(); try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { br.readLine(); // skip the first line String str; @@ -42,10 +40,11 @@ private void loadFile() { logger.warn(IO_EXCEPTION); throw new UncheckedIOException(e); } + return customers; } - public void saveFile() { + public void saveFile(Map customers) { File csvOutputFile = new File(filePath); try (PrintWriter pw = new PrintWriter(csvOutputFile)) { customers.values().forEach((customer) -> pw.println(customerToString(customer))); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 31a97d3cdf..93e96c60b0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -3,16 +3,11 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.vouchertype.VoucherType; import com.programmers.vouchermanagement.voucher.repository.util.VoucherFileManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; import java.time.LocalDateTime; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import static com.programmers.vouchermanagement.util.Message.NOT_DELETED; import static com.programmers.vouchermanagement.util.Message.NOT_UPDATED; @@ -20,59 +15,67 @@ @Repository @Profile("file") public class VoucherFileRepository implements VoucherRepository { - private static final Logger logger = LoggerFactory.getLogger(VoucherFileRepository.class); - + public final Map vouchers; private final VoucherFileManager voucherFileManager; public VoucherFileRepository(VoucherFileManager voucherFileManager) { this.voucherFileManager = voucherFileManager; + vouchers = voucherFileManager.loadFile(); } @Override public void insert(Voucher voucher) { - voucherFileManager.vouchers.put(voucher.getId(), voucher); - voucherFileManager.saveFile(); + vouchers.put(voucher.getId(), voucher); + voucherFileManager.saveFile(vouchers); } @Override public List findAll() { - return voucherFileManager.vouchers.values().stream().toList(); + return vouchers.values().stream().toList(); } @Override public Optional findById(UUID id) { - return Optional.ofNullable(voucherFileManager.vouchers.get(id)); + return Optional.ofNullable(vouchers.get(id)); } @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { - return voucherFileManager.vouchers.values().stream().filter(voucher -> { - LocalDateTime createdAt = voucher.getCreatedAt(); - return createdAt.isAfter(from) && createdAt.isBefore(to); - }).toList(); + return vouchers.values() + .stream() + .filter(voucher -> { + LocalDateTime createdAt = voucher.getCreatedAt(); + return createdAt.isAfter(from) && createdAt.isBefore(to); + }) + .toList(); } @Override public void delete(UUID id) { - Optional.ofNullable(voucherFileManager.vouchers.remove(id)).orElseThrow(() -> new NoSuchElementException(NOT_DELETED)); - voucherFileManager.saveFile(); + Optional.ofNullable(vouchers.remove(id)) + .orElseThrow(() -> new NoSuchElementException(NOT_DELETED)); + voucherFileManager.saveFile(vouchers); } @Override public void deleteAll() { - if (!voucherFileManager.vouchers.isEmpty()) voucherFileManager.vouchers.clear(); - voucherFileManager.saveFile(); + if (!vouchers.isEmpty()) vouchers.clear(); + voucherFileManager.saveFile(vouchers); } @Override public void update(Voucher voucher) { - Optional.ofNullable(voucherFileManager.vouchers.get(voucher.getId())).orElseThrow(() -> new NoSuchElementException(NOT_UPDATED)); - voucherFileManager.vouchers.put(voucher.getId(), voucher); - voucherFileManager.saveFile(); + Optional.ofNullable(vouchers.get(voucher.getId())) + .orElseThrow(() -> new NoSuchElementException(NOT_UPDATED)); + vouchers.put(voucher.getId(), voucher); + voucherFileManager.saveFile(vouchers); } @Override public List findAllByType(VoucherType voucherType) { - return voucherFileManager.vouchers.values().stream().filter(voucher -> voucher.getTypeName().equals(voucherType.getName())).toList(); + return vouchers.values() + .stream() + .filter(voucher -> voucher.getTypeName().equals(voucherType.getName())) + .toList(); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java index 0a77a893d8..dcd7de373a 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java @@ -23,36 +23,36 @@ @Profile("file") public class VoucherFileManager { private static final Logger logger = LoggerFactory.getLogger(VoucherFileManager.class); - public final Map vouchers; private final ObjectMapper objectMapper; private final String filePath; public VoucherFileManager(AppProperties appProperties, ObjectMapper objectMapper) { - this.filePath = appProperties.resources().path() + appProperties.domains().get("voucher").fileName(); + this.filePath = appProperties.resources().path() + + appProperties.domains().get("voucher").fileName(); this.objectMapper = objectMapper; - vouchers = new HashMap<>(); - loadFile(); } - public void loadFile() { + public Map loadFile() { try { File file = new File(filePath); Map[] voucherObjects = objectMapper.readValue(file, Map[].class); - loadVouchers(voucherObjects); + return loadVouchers(voucherObjects); } catch (IOException e) { logger.error(IO_EXCEPTION); throw new UncheckedIOException(e); } } - public void loadVouchers(Map[] voucherObjects) { + private Map loadVouchers(Map[] voucherObjects) { + Map vouchers = new HashMap<>(); Arrays.stream(voucherObjects).forEach(voucherObject -> { Voucher voucher = objectToVoucher(voucherObject); vouchers.put(voucher.getId(), voucher); }); + return vouchers; } - public void saveFile() { + public void saveFile(Map vouchers) { try (FileWriter fileWriter = new FileWriter(filePath)) { List> voucherObjects = new ArrayList<>(); if (!vouchers.isEmpty()) { @@ -68,5 +68,4 @@ public void saveFile() { throw new RuntimeException(FILE_EXCEPTION); } } - } From 452e2e811de112e732232d24575e9dfbaddc27c7 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 02:55:53 +0900 Subject: [PATCH 369/383] refactor: refactor wallet profile --- .../vouchermanagement/wallet/controller/WalletController.java | 2 +- .../wallet/controller/WalletThymeleafController.java | 2 +- .../wallet/repository/WalletJDBCRepository.java | 2 ++ .../vouchermanagement/wallet/service/WalletService.java | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java index 750108d911..4349d7f7f1 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletController.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.UUID; -@Profile({"console", "api"}) +@Profile({"console & jdbc"}) @Controller public class WalletController { private final WalletService walletService; diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java index 81fb1803b1..9891935163 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/controller/WalletThymeleafController.java @@ -12,7 +12,7 @@ import java.util.List; import java.util.UUID; -@Profile("thyme") +@Profile({"thyme & jdbc"}) @RequestMapping("/wallets") @Controller public class WalletThymeleafController { diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java index 2f76eb2193..d805a05667 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/repository/WalletJDBCRepository.java @@ -5,6 +5,7 @@ import com.programmers.vouchermanagement.wallet.domain.Ownership; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -20,6 +21,7 @@ import static com.programmers.vouchermanagement.wallet.repository.util.OwnershipDomainMapper.ownershipToParamMap; import static com.programmers.vouchermanagement.wallet.repository.util.OwnershipDomainMapper.uuidToParamMap; +@Profile("jdbc") @Repository public class WalletJDBCRepository implements WalletRepository { private static final Logger logger = LoggerFactory.getLogger(WalletJDBCRepository.class); diff --git a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java index 329c32c661..59e4cd7ef7 100644 --- a/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java +++ b/src/main/java/com/programmers/vouchermanagement/wallet/service/WalletService.java @@ -8,13 +8,14 @@ import com.programmers.vouchermanagement.wallet.repository.WalletRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import static com.programmers.vouchermanagement.util.Message.NOT_FOUND_VOUCHER_ALLOCATION; - +@Profile("jdbc") @Service public class WalletService { private static final Logger logger = LoggerFactory.getLogger(WalletService.class); From c233f1b30547f0a532b6fe957a8b9a630fc427e6 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 03:22:00 +0900 Subject: [PATCH 370/383] refactor: formatting code to 1 depth --- .../repository/util/CustomerFileManager.java | 16 ++++++++++------ .../repository/VoucherFileRepository.java | 6 +++++- .../repository/VoucherInMemoryRepository.java | 10 ++++++---- .../repository/util/VoucherFileManager.java | 17 ++++++++++------- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java index 9f68ca592b..f41bdff32a 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/util/CustomerFileManager.java @@ -28,18 +28,22 @@ public CustomerFileManager(AppProperties appProperties) { } public Map loadFile() { - Map customers = new HashMap<>(); try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { br.readLine(); // skip the first line - String str; - while ((str = br.readLine()) != null) { - Customer customer = stringToCustomer(str); - customers.put(customer.getId(), customer); - } + return loadCustomer(br); } catch (IOException e) { logger.warn(IO_EXCEPTION); throw new UncheckedIOException(e); } + } + + private Map loadCustomer(BufferedReader br) throws IOException { + Map customers = new HashMap<>(); + String str; + while ((str = br.readLine()) != null) { + Customer customer = stringToCustomer(str); + customers.put(customer.getId(), customer); + } return customers; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java index 93e96c60b0..3c71cd38bc 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherFileRepository.java @@ -75,7 +75,11 @@ public void update(Voucher voucher) { public List findAllByType(VoucherType voucherType) { return vouchers.values() .stream() - .filter(voucher -> voucher.getTypeName().equals(voucherType.getName())) + .filter(voucher -> isEqualName(voucher, voucherType)) .toList(); } + + private boolean isEqualName(Voucher voucher, VoucherType voucherType) { + return voucher.getTypeName().equals(voucherType.getName()); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java index 74941c2dae..f23d842d4b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherInMemoryRepository.java @@ -37,10 +37,12 @@ public Optional findById(UUID id) { @Override public List findAllByCreatedAt(LocalDateTime from, LocalDateTime to) { - return vouchers.values().stream().filter(voucher -> { - LocalDateTime createdAt = voucher.getCreatedAt(); - return createdAt.isAfter(from) && createdAt.isBefore(to); - }).toList(); + return vouchers.values().stream().filter(voucher -> isCreatedBetweenPeriod(voucher, from, to)).toList(); + } + + private boolean isCreatedBetweenPeriod(Voucher voucher, LocalDateTime from, LocalDateTime to) { + LocalDateTime createdAt = voucher.getCreatedAt(); + return createdAt.isAfter(from) && createdAt.isBefore(to); } @Override diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java index dcd7de373a..0bd0b74503 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/util/VoucherFileManager.java @@ -54,13 +54,7 @@ private Map loadVouchers(Map[] voucherObjects) { public void saveFile(Map vouchers) { try (FileWriter fileWriter = new FileWriter(filePath)) { - List> voucherObjects = new ArrayList<>(); - if (!vouchers.isEmpty()) { - vouchers.values().forEach(voucher -> { - HashMap voucherObject = voucherToObject(voucher); - voucherObjects.add(voucherObject); - }); - } + List> voucherObjects = toVoucherObjects(vouchers); String jsonStr = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(voucherObjects); fileWriter.write(jsonStr); fileWriter.flush(); @@ -68,4 +62,13 @@ public void saveFile(Map vouchers) { throw new RuntimeException(FILE_EXCEPTION); } } + + private List> toVoucherObjects(Map vouchers) { + List> voucherObjects = new ArrayList<>(); + vouchers.values().forEach(voucher -> { + HashMap voucherObject = voucherToObject(voucher); + voucherObjects.add(voucherObject); + }); + return voucherObjects; + } } From 7e7f91b526be863cae0e165782c7361f22c5bfa8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 03:30:40 +0900 Subject: [PATCH 371/383] refactor: refactor voucher constructor --- .../vouchermanagement/voucher/domain/Voucher.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 53637b30c3..2959874626 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -13,15 +13,6 @@ public class Voucher { private VoucherType type; private long discountValue; - public Voucher(String typeName, long discountValue) { - id = UUID.randomUUID(); - createdAt = LocalDateTime.now(); - - this.type = VoucherTypeManager.get(typeName); - type.validateDiscountValue(discountValue); - this.discountValue = discountValue; - } - public Voucher(UUID id, LocalDateTime createdAt, String typeName, long discountValue) { this.id = id; this.createdAt = createdAt; @@ -30,6 +21,11 @@ public Voucher(UUID id, LocalDateTime createdAt, String typeName, long discountV this.discountValue = discountValue; } + public Voucher(String typeName, long discountValue) { + this(UUID.randomUUID(), LocalDateTime.now(), typeName, discountValue); + } + + public String getTypeName() { return type.getName(); } From 22710b4e6aff4fa0f065de8d63b41279a2d0ba3f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 13:18:20 +0900 Subject: [PATCH 372/383] refactor: change html language --- src/main/resources/templates/customer/customer-new.html | 2 +- src/main/resources/templates/customer/customers.html | 2 +- src/main/resources/templates/voucher/voucher-detail.html | 2 +- src/main/resources/templates/voucher/voucher-new.html | 2 +- src/main/resources/templates/voucher/voucher-update.html | 2 +- src/main/resources/templates/voucher/vouchers.html | 2 +- src/main/resources/templates/wallet/wallets.html | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/resources/templates/customer/customer-new.html b/src/main/resources/templates/customer/customer-new.html index 37ff0ab04d..b69f9a2c53 100644 --- a/src/main/resources/templates/customer/customer-new.html +++ b/src/main/resources/templates/customer/customer-new.html @@ -1,5 +1,5 @@ - + - + - + - + - + - + - + Date: Thu, 9 Nov 2023 14:20:29 +0900 Subject: [PATCH 373/383] refactor: refactor create method by writing created resource url at VoucherRestController --- .../controller/VoucherRestController.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 93ba0adc90..8ad2ff19cc 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -8,6 +8,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.net.URI; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -30,8 +31,9 @@ public ResponseEntity create( @RequestBody CreateVoucherRequest createVoucherRequest ) { - return ResponseEntity.status(HttpStatus.CREATED) - .body(voucherService.create(createVoucherRequest)); + VoucherResponse voucherResponse = voucherService.create(createVoucherRequest); + return ResponseEntity.created(URI.create("/customers/" + voucherResponse.id())) + .body(voucherResponse); } @GetMapping("/{voucherId}") @@ -65,14 +67,14 @@ public ResponseEntity update( @GetMapping public ResponseEntity> readAll( //TODO: make Object and Validate! - @RequestParam(name = "filter", defaultValue = "all") - String filter, - @RequestParam(name = "from", required = false) - LocalDate from, - @RequestParam(name = "to", required = false) - LocalDate to, - @RequestParam(name = "type-name", required = false) - String typeName + @RequestParam(name = "filter", defaultValue = "all") + String filter, + @RequestParam(name = "from", required = false) + LocalDate from, + @RequestParam(name = "to", required = false) + LocalDate to, + @RequestParam(name = "type-name", required = false) + String typeName ) { if (filter.equals("all")) return ResponseEntity.status(HttpStatus.OK) From ea48f3ff104d65aae2ee7a5fd2fd8bf744d82565 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 16:04:01 +0900 Subject: [PATCH 374/383] refactor: apply param method at CustomerRestControllerTest --- .../CustomerRestControllerTest.java | 57 +++++-------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerRestControllerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerRestControllerTest.java index 32fe0dd5cd..9986be578a 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerRestControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerRestControllerTest.java @@ -1,11 +1,6 @@ package com.programmers.vouchermanagement.customer.controller; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; -import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; -import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.service.CustomerService; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -15,8 +10,7 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; -import java.util.List; - +import static com.programmers.vouchermanagement.customer.controller.MvcControllerResource.*; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -26,56 +20,31 @@ @WebMvcTest(CustomerRestController.class) @ActiveProfiles("api") class CustomerRestControllerTest { - static ObjectMapper objectMapper; - static List customers; - static List blacklist; - static Customer customer; - static CreateCustomerRequest createCustomerRequest; - static CustomerResponse customerResponse; - @Autowired MockMvc mockMvc; @MockBean CustomerService customerService; - @BeforeAll - static void init() { - objectMapper = new ObjectMapper(); - - customers = List.of( - CustomerResponse.from(new Customer("customer1", false)), - CustomerResponse.from(new Customer("customer2", true)) - ); - blacklist = List.of( - CustomerResponse.from(new Customer("customer3", true)), - CustomerResponse.from(new Customer("customer4", true)) - ); - - createCustomerRequest = new CreateCustomerRequest("customer5", true); - customer = new Customer(createCustomerRequest.name(), createCustomerRequest.isBlack()); - customerResponse = CustomerResponse.from(customer); - } - @Test @DisplayName("고객 생성을 요청한다.") void createCustomer() throws Exception { - when(customerService.create(createCustomerRequest)).thenReturn(customerResponse); + when(customerService.create(CREATE_CUSTOMER_REQUEST)).thenReturn(CUSTOMER_RESPONSE); String response = mockMvc.perform(post("/api/v1/customers") .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(createCustomerRequest))) + .content(OBJECT_MAPPER.writeValueAsString(CREATE_CUSTOMER_REQUEST))) .andExpect(status().isCreated()) .andReturn() .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(customerResponse)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(CUSTOMER_RESPONSE)); } @Test @DisplayName("모든 고객 조회를 요청한다.") void readAllCustomers1() throws Exception { - when(customerService.readAll()).thenReturn(customers); + when(customerService.readAll()).thenReturn(CUSTOMERS); String response = mockMvc.perform(get("/api/v1/customers")) .andExpect(status().isOk()) @@ -83,34 +52,36 @@ void readAllCustomers1() throws Exception { .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(customers)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(CUSTOMERS)); } @Test @DisplayName("모든 고객 조회를 요청한다. + 쿼리 스트링 사용(type=all)") void readAllCustomers2() throws Exception { - when(customerService.readAll()).thenReturn(customers); + when(customerService.readAll()).thenReturn(CUSTOMERS); - String response = mockMvc.perform(get("/api/v1/customers?type=all")) + String response = mockMvc.perform(get("/api/v1/customers") + .param("type", "all")) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(customers)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(CUSTOMERS)); } @Test @DisplayName("모든 블랙리스트 고객 조회를 요청한다.") void readAllBlacklist() throws Exception { - when(customerService.readAllBlackCustomer()).thenReturn(blacklist); + when(customerService.readAllBlackCustomer()).thenReturn(BLACKLIST); - String response = mockMvc.perform(get("/api/v1/customers?type=blacklist")) + String response = mockMvc.perform(get("/api/v1/customers") + .param("type","blacklist")) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(blacklist)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(BLACKLIST)); } } \ No newline at end of file From 21fc4ece4e7caee2de7fab30ec0b43b152fff767 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 16:17:15 +0900 Subject: [PATCH 375/383] feat: implement MvcControllerResource for MvcControllerTest --- .../controller/MvcControllerResource.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/customer/controller/MvcControllerResource.java diff --git a/src/test/java/com/programmers/vouchermanagement/customer/controller/MvcControllerResource.java b/src/test/java/com/programmers/vouchermanagement/customer/controller/MvcControllerResource.java new file mode 100644 index 0000000000..a8e2985815 --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/customer/controller/MvcControllerResource.java @@ -0,0 +1,24 @@ +package com.programmers.vouchermanagement.customer.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.programmers.vouchermanagement.customer.controller.dto.CreateCustomerRequest; +import com.programmers.vouchermanagement.customer.controller.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.domain.Customer; + +import java.util.List; + +public class MvcControllerResource { + public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + public static final List CUSTOMERS = List.of( + CustomerResponse.from(new Customer("customer1", false)), + CustomerResponse.from(new Customer("customer2", true)) + ); + public static final List BLACKLIST = List.of( + CustomerResponse.from(new Customer("customer3", true)), + CustomerResponse.from(new Customer("customer4", true)) + ); + public static final CreateCustomerRequest CREATE_CUSTOMER_REQUEST = new CreateCustomerRequest("customer5", true); + + public static final Customer CUSTOMER = new Customer(CREATE_CUSTOMER_REQUEST.name(), CREATE_CUSTOMER_REQUEST.isBlack()); + public static final CustomerResponse CUSTOMER_RESPONSE = CustomerResponse.from(CUSTOMER); +} From d4a48d2d06bd39cb577b875346d9929751e39215 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 16:17:28 +0900 Subject: [PATCH 376/383] test: test CustomerThymeleafController --- .../CustomerThymeleafControllerTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java new file mode 100644 index 0000000000..1a9e26c9ca --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java @@ -0,0 +1,67 @@ +package com.programmers.vouchermanagement.customer.controller; + +import com.programmers.vouchermanagement.customer.service.CustomerService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import static com.programmers.vouchermanagement.customer.controller.MvcControllerResource.*; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(CustomerThymeleafController.class) +@ActiveProfiles("thyme") +class CustomerThymeleafControllerTest { + @Autowired + MockMvc mockMvc; + @MockBean + CustomerService customerService; + + @Test + @DisplayName("고객 생성을 요청한다. 그리고 customers 페이지도 이동한다.") + void createCustomer() throws Exception { + when(customerService.create(CREATE_CUSTOMER_REQUEST)).thenReturn(CUSTOMER_RESPONSE); + + mockMvc.perform(post("/customers/new") + .param("name", "customer") + .param("isBlack", "true")) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/customers")); + } + + @Test + @DisplayName("고객 생성 페이지를 요청한다.") + void viewCreatePage() throws Exception { + mockMvc.perform(get("/customers/new")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/customer-new")); + } + + @Test + @DisplayName("모든 고객 조회 페이지를 요청한다.") + void readAll1() throws Exception { + when(customerService.readAll()).thenReturn(CUSTOMERS); + + mockMvc.perform(get("/customers")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/customers")) + .andExpect(model().attribute("customers", CUSTOMERS)); + } + + @Test + @DisplayName("블랙리스트 조회 페이지를 요청한다.") + void readAllBlackCustomer() throws Exception { + when(customerService.readAllBlackCustomer()).thenReturn(BLACKLIST); + + mockMvc.perform(get("/customers/blacklist")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/customers")) + .andExpect(model().attribute("customers", BLACKLIST)); + } +} \ No newline at end of file From da3a9c1465531cf2dcf82d81bca8a420d9125d4c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 16:23:58 +0900 Subject: [PATCH 377/383] refactor: apply query param filtering at CustomerThymeleafController --- .../controller/CustomerThymeleafController.java | 15 +++++++-------- .../CustomerThymeleafControllerTest.java | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java index a11db1c230..56acc31182 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafController.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; @Profile("thyme") @RequestMapping("/customers") @@ -31,16 +32,14 @@ public String viewCreatePage() { } @GetMapping - public String readAll(Model model) { + public String readAll(@RequestParam(required = false, defaultValue = "all") String type, Model model) { + if (type.equals("blacklist")) { + model.addAttribute("mode", "blacklist"); + model.addAttribute("customers", customerService.readAllBlackCustomer()); + return "customer/customers"; + } model.addAttribute("mode", "all"); model.addAttribute("customers", customerService.readAll()); return "customer/customers"; } - - @GetMapping("/blacklist") - public String readAllBlackCustomer(Model model) { - model.addAttribute("mode", "blacklist"); - model.addAttribute("customers", customerService.readAllBlackCustomer()); - return "customer/customers"; - } } diff --git a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java index 1a9e26c9ca..94425deea1 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java @@ -54,12 +54,25 @@ void readAll1() throws Exception { .andExpect(model().attribute("customers", CUSTOMERS)); } + @Test + @DisplayName("모든 고객 조회 페이지를 요청한다. + 쿼리 스트링(type=all)") + void readAll2() throws Exception { + when(customerService.readAll()).thenReturn(CUSTOMERS); + + mockMvc.perform(get("/customers") + .param("type", "all")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/customers")) + .andExpect(model().attribute("customers", CUSTOMERS)); + } + @Test @DisplayName("블랙리스트 조회 페이지를 요청한다.") void readAllBlackCustomer() throws Exception { when(customerService.readAllBlackCustomer()).thenReturn(BLACKLIST); - mockMvc.perform(get("/customers/blacklist")) + mockMvc.perform(get("/customers") + .param("type", "blacklist")) .andExpect(status().isOk()) .andExpect(view().name("customer/customers")) .andExpect(model().attribute("customers", BLACKLIST)); From 455451d697d2be8bcac2a94e9d1757a2a3933b85 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 16:45:55 +0900 Subject: [PATCH 378/383] style: change code format at VoucherRestController --- .../controller/VoucherRestController.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 8ad2ff19cc..f14c8182cf 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -66,15 +66,16 @@ public ResponseEntity update( } @GetMapping - public ResponseEntity> readAll( //TODO: make Object and Validate! - @RequestParam(name = "filter", defaultValue = "all") - String filter, - @RequestParam(name = "from", required = false) - LocalDate from, - @RequestParam(name = "to", required = false) - LocalDate to, - @RequestParam(name = "type-name", required = false) - String typeName + public ResponseEntity> readAll( + //TODO: make Object and Validate! + @RequestParam(name = "filter", defaultValue = "all") + String filter, + @RequestParam(name = "from", required = false) + LocalDate from, + @RequestParam(name = "to", required = false) + LocalDate to, + @RequestParam(name = "type-name", required = false) + String typeName ) { if (filter.equals("all")) return ResponseEntity.status(HttpStatus.OK) From ea485145ad926eaf55d8cba3b67c80e017092237 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 16:46:48 +0900 Subject: [PATCH 379/383] refactor: split test resources from VoucherRestControllerTest --- .../controller/MvcControllerResource.java | 36 ++++++++ .../controller/VoucherRestControllerTest.java | 82 ++++++------------- 2 files changed, 59 insertions(+), 59 deletions(-) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/controller/MvcControllerResource.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/MvcControllerResource.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/MvcControllerResource.java new file mode 100644 index 0000000000..be94edf81d --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/MvcControllerResource.java @@ -0,0 +1,36 @@ +package com.programmers.vouchermanagement.voucher.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.domain.Voucher; + +import java.util.List; +import java.util.UUID; + +public class MvcControllerResource { + public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + public static final List VOUCHERS = List.of( + VoucherResponse.from(new Voucher("FIXED", 3000)), + VoucherResponse.from(new Voucher("PERCENT", 10)) + ); + public static final List FIXED_AMOUNT_VOUCHERS = List.of( + VoucherResponse.from(new Voucher("FIXED", 3000)), + VoucherResponse.from(new Voucher("FIXED", 3000)) + ); + public static final List VOUCHERS_CREATED_NOW = List.of( + VoucherResponse.from(new Voucher("FIXED", 3000)), + VoucherResponse.from(new Voucher("PERCENT", 50)) + ); + public static final CreateVoucherRequest CREATE_VOUCHER_REQUEST = new CreateVoucherRequest("FIXED", 5000); + + public static final Voucher VOUCHER = new Voucher(CREATE_VOUCHER_REQUEST.typeName(), CREATE_VOUCHER_REQUEST.discountValue()); + + public static final UUID VOUCHER_ID = VOUCHER.getId(); + public static final VoucherResponse VOUCHER_RESPONSE = VoucherResponse.from(VOUCHER); +} diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java index b323430309..306c33cdcf 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestControllerTest.java @@ -1,13 +1,8 @@ package com.programmers.vouchermanagement.voucher.controller; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.programmers.vouchermanagement.voucher.controller.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.controller.dto.VoucherResponse; -import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.service.VoucherService; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -19,9 +14,8 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.List; -import java.util.UUID; +import static com.programmers.vouchermanagement.voucher.controller.MvcControllerResource.*; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -31,57 +25,31 @@ @WebMvcTest(VoucherRestController.class) @ActiveProfiles("api") class VoucherRestControllerTest { - static ObjectMapper objectMapper; - static List vouchers; - static Voucher voucher; - static UUID voucherId; - static CreateVoucherRequest createVoucherRequest; - static VoucherResponse voucherResponse; - @Autowired MockMvc mockMvc; @MockBean VoucherService voucherService; - @BeforeAll - static void init() { - objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - - vouchers = List.of( - VoucherResponse.from(new Voucher("FIXED", 100)), - VoucherResponse.from(new Voucher("FIXED", 200)), - VoucherResponse.from(new Voucher("PERCENT", 50)), - VoucherResponse.from(new Voucher("PERCENT", 60)) - ); - - createVoucherRequest = new CreateVoucherRequest("PERCENT", 50); - voucher = new Voucher(createVoucherRequest.typeName(), createVoucherRequest.discountValue()); - voucherId = voucher.getId(); - voucherResponse = VoucherResponse.from(voucher); - } - @Test @DisplayName("바우처 생성을 요청한다.") void createVoucher() throws Exception { - when(voucherService.create(createVoucherRequest)).thenReturn(voucherResponse); + when(voucherService.create(CREATE_VOUCHER_REQUEST)).thenReturn(VOUCHER_RESPONSE); String response = mockMvc.perform(post("/api/v1/vouchers") .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(createVoucherRequest))) + .content(OBJECT_MAPPER.writeValueAsString(CREATE_VOUCHER_REQUEST))) .andExpect(status().isCreated()) .andReturn() .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(voucherResponse)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(VOUCHER_RESPONSE)); } @Test @DisplayName("모든 바우처 조회를 요청한다.") void readAllVouchers1() throws Exception { - when(voucherService.readAll()).thenReturn(vouchers); + when(voucherService.readAll()).thenReturn(VOUCHERS); String response = mockMvc.perform(get("/api/v1/vouchers")) .andExpect(status().isOk()) @@ -89,13 +57,13 @@ void readAllVouchers1() throws Exception { .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchers)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(VOUCHERS)); } @Test @DisplayName("모든 바우처 조회를 요청한다. + 쿼리 스트링(filter=all)") void readAllVouchers2() throws Exception { - when(voucherService.readAll()).thenReturn(vouchers); + when(voucherService.readAll()).thenReturn(VOUCHERS); String response = mockMvc.perform(get("/api/v1/vouchers") .param("filter", "all")) @@ -104,7 +72,7 @@ void readAllVouchers2() throws Exception { .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchers)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(VOUCHERS)); } @Test @@ -112,9 +80,8 @@ void readAllVouchers2() throws Exception { void readAllByCreatedAt() throws Exception { LocalDate from = LocalDate.of(2022, 12, 25); LocalDate to = LocalDate.now(); - List vouchersCreatedBeforeNow = vouchers; when(voucherService.readAllByCreatedAt(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(vouchersCreatedBeforeNow); + .thenReturn(VOUCHERS_CREATED_NOW); String response = mockMvc.perform(get("/api/v1/vouchers") .param("filter", "created-at") @@ -125,17 +92,14 @@ void readAllByCreatedAt() throws Exception { .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchersCreatedBeforeNow)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(VOUCHERS_CREATED_NOW)); } @Test @DisplayName("입력 타입에 해당하는 모든 바우처 조회를 요청한다. + 쿼리 스트링(filter=type...)") void readAllByType() throws Exception { String typeName = "FIXED"; - List vouchersCreatedAsPercent = vouchers.stream() - .filter((voucher) -> voucher.typeName().equals(typeName)) - .toList(); - when(voucherService.readAllByType(typeName)).thenReturn(vouchersCreatedAsPercent); + when(voucherService.readAllByType(typeName)).thenReturn(FIXED_AMOUNT_VOUCHERS); String response = mockMvc.perform(get("/api/v1/vouchers") .param("filter", "type") @@ -145,52 +109,52 @@ void readAllByType() throws Exception { .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(vouchersCreatedAsPercent)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(FIXED_AMOUNT_VOUCHERS)); } @Test @DisplayName("바우처 id로 바우처 조회를 요청한다.") void readVoucherById() throws Exception { - when(voucherService.readById(voucherId)).thenReturn(voucherResponse); + when(voucherService.readById(VOUCHER_ID)).thenReturn(VOUCHER_RESPONSE); - String response = mockMvc.perform(get("/api/v1/vouchers/" + voucherId.toString())) + String response = mockMvc.perform(get("/api/v1/vouchers/" + VOUCHER_ID.toString())) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(voucherResponse)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(VOUCHER_RESPONSE)); } @Test @DisplayName("바우처 id로 바우처를 삭제한다.") void deleteVoucher() throws Exception { - when(voucherService.delete(voucherId)).thenReturn(voucherResponse); + when(voucherService.delete(VOUCHER_ID)).thenReturn(VOUCHER_RESPONSE); - String response = mockMvc.perform(delete("/api/v1/vouchers/" + voucherId.toString())) + String response = mockMvc.perform(delete("/api/v1/vouchers/" + VOUCHER_ID.toString())) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(voucherResponse)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(VOUCHER_RESPONSE)); } @Test @DisplayName("바우처 id로 바우처를 업데이트한다.") void update() throws Exception { CreateVoucherRequest updateVoucherRequest = new CreateVoucherRequest("FIXED", 100000); - VoucherResponse updatedVoucherResponse = new VoucherResponse(voucherId, voucher.getCreatedAt(), createVoucherRequest.typeName(), createVoucherRequest.discountValue()); - when(voucherService.update(voucherId, updateVoucherRequest)).thenReturn(updatedVoucherResponse); + VoucherResponse updatedVoucherResponse = new VoucherResponse(VOUCHER_ID, VOUCHER.getCreatedAt(), CREATE_VOUCHER_REQUEST.typeName(), CREATE_VOUCHER_REQUEST.discountValue()); + when(voucherService.update(VOUCHER_ID, updateVoucherRequest)).thenReturn(updatedVoucherResponse); - String response = mockMvc.perform(put("/api/v1/vouchers/" + voucherId.toString()) + String response = mockMvc.perform(put("/api/v1/vouchers/" + VOUCHER_ID.toString()) .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(updateVoucherRequest))) + .content(OBJECT_MAPPER.writeValueAsString(updateVoucherRequest))) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(); - assertThat(response).isEqualTo(objectMapper.writeValueAsString(updatedVoucherResponse)); + assertThat(response).isEqualTo(OBJECT_MAPPER.writeValueAsString(updatedVoucherResponse)); } } \ No newline at end of file From d0221287be972d0bc308f5dbfa53bd828598e01a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 17:04:44 +0900 Subject: [PATCH 380/383] refactor: fix word mistake --- .../customer/controller/CustomerThymeleafControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java index 94425deea1..7e2e836c3d 100644 --- a/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/customer/controller/CustomerThymeleafControllerTest.java @@ -24,7 +24,7 @@ class CustomerThymeleafControllerTest { CustomerService customerService; @Test - @DisplayName("고객 생성을 요청한다. 그리고 customers 페이지도 이동한다.") + @DisplayName("고객 생성을 요청한다. 그리고 customers 페이지로 이동한다.") void createCustomer() throws Exception { when(customerService.create(CREATE_CUSTOMER_REQUEST)).thenReturn(CUSTOMER_RESPONSE); From 729cc06093e2f5da8fa08578437eeb9775a7b6a1 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 17:04:55 +0900 Subject: [PATCH 381/383] test: test VoucherThymeleafController --- .../VoucherThymeleafControllerTest.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java new file mode 100644 index 0000000000..eab131a2aa --- /dev/null +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java @@ -0,0 +1,95 @@ +package com.programmers.vouchermanagement.voucher.controller; + +import com.programmers.vouchermanagement.voucher.service.VoucherService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static com.programmers.vouchermanagement.voucher.controller.MvcControllerResource.*; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(VoucherThymeleafController.class) +@ActiveProfiles("thyme") +class VoucherThymeleafControllerTest { + @Autowired + MockMvc mockMvc; + @MockBean + VoucherService voucherService; + + @Test + @DisplayName("바우처 생성을 요청한다. 그리고 vouchers 페이지로 이동한다.") + void createVoucher() throws Exception { + when(voucherService.create(CREATE_VOUCHER_REQUEST)).thenReturn(VOUCHER_RESPONSE); + + mockMvc.perform(post("/vouchers/new") + .param("typeName", CREATE_VOUCHER_REQUEST.typeName()) + .param("discountValue", Long.toString(CREATE_VOUCHER_REQUEST.discountValue()))) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/vouchers")); + } + + @Test + @DisplayName("바우처 생성 페이지를 요청한다.") + void viewCreatePage() throws Exception { + mockMvc.perform(get("/vouchers/new")) + .andExpect(status().isOk()) + .andExpect(view().name("vouchers/voucher-new")); + } + + @Test + @DisplayName("모든 바우처 조회 페이지를 요청한다.") + void viewVouchersPage() throws Exception { + when(voucherService.readAll()).thenReturn(VOUCHERS); + + mockMvc.perform(get("/vouchers")) + .andExpect(status().isOk()) + .andExpect(view().name("voucher/vouchers")) + .andExpect(model().attribute("vouchers", VOUCHERS)); + } + + @Test + @DisplayName("id별 바우처 상세 페이지를 요청한다.") + void viewVoucherByIdPage() throws Exception { + when(voucherService.readById(VOUCHER_ID)).thenReturn(VOUCHER_RESPONSE); + + mockMvc.perform(get("/vouchers/" + VOUCHER_ID.toString())) + .andExpect(status().isOk()) + .andExpect(view().name("voucher/voucher-detail")) + .andExpect(model().attribute("voucher", VOUCHER_RESPONSE)); + } + + @Test + @DisplayName("바우처 삭제를 요청한다.") + void deleteVoucher() throws Exception { + mockMvc.perform(delete("/vouchers/" + VOUCHER_ID.toString())) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/vouchers")); + } + + @Test + @DisplayName("바우처 업데이트를 요청한다.") + void update() throws Exception { + mockMvc.perform(put("/vouchers/update/" + VOUCHER_ID.toString()) + .param("typeName", CREATE_VOUCHER_REQUEST.typeName()) + .param("discountValue", Long.toString(CREATE_VOUCHER_REQUEST.discountValue()))) .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/vouchers")); + } + + @Test + @DisplayName("바우처 업데이트 페이지를 요청한다.") + void viewUpdatePage() throws Exception { + when(voucherService.readById(VOUCHER_ID)).thenReturn(VOUCHER_RESPONSE); + + mockMvc.perform(get("/vouchers/update/" + VOUCHER_ID.toString())) + .andExpect(status().isOk()) + .andExpect(view().name("voucher/voucher-update")) + .andExpect(model().attribute("voucher", VOUCHER_RESPONSE)); + } +} \ No newline at end of file From 986d8075537ceeaa4e3cfb1017272fe0aa0c5ddb Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 9 Nov 2023 17:13:16 +0900 Subject: [PATCH 382/383] refactor: delete returning emptyList(Constant) --- .../customer/service/CustomerService.java | 4 +--- .../vouchermanagement/voucher/service/VoucherService.java | 8 -------- .../controller/VoucherThymeleafControllerTest.java | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 824ec11481..810cb1fee2 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -28,9 +28,7 @@ public CustomerResponse create(CreateCustomerRequest createCustomerRequest) { @Transactional(readOnly = true) public List readAll() { List customers = customerRepository.findAll(); - if (customers.isEmpty()) { - return Collections.emptyList(); - } + return customers.stream().map(CustomerResponse::from).toList(); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index bb4a86fc83..b55909159f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -33,10 +33,6 @@ public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { public List readAll() { List vouchers = voucherRepository.findAll(); - if (vouchers.isEmpty()) { - return Collections.emptyList(); - } - return vouchers.stream() .map(VoucherResponse::from) .toList(); @@ -46,10 +42,6 @@ public List readAll() { public List readAllByCreatedAt(LocalDateTime from, LocalDateTime to) { List vouchers = voucherRepository.findAllByCreatedAt(from, to); - if (vouchers.isEmpty()) { - return Collections.emptyList(); - } - return vouchers.stream() .map(VoucherResponse::from) .toList(); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java index eab131a2aa..c998d7f2bd 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherThymeleafControllerTest.java @@ -40,7 +40,7 @@ void createVoucher() throws Exception { void viewCreatePage() throws Exception { mockMvc.perform(get("/vouchers/new")) .andExpect(status().isOk()) - .andExpect(view().name("vouchers/voucher-new")); + .andExpect(view().name("voucher/voucher-new")); } @Test From 1c76fea43001d552cc489d3ee934129a3893d8ca Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Sun, 12 Nov 2023 16:43:03 +0900 Subject: [PATCH 383/383] fix: change return url when voucher created --- .../voucher/controller/VoucherRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index f14c8182cf..c49872ed4c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -32,7 +32,7 @@ public ResponseEntity create( CreateVoucherRequest createVoucherRequest ) { VoucherResponse voucherResponse = voucherService.create(createVoucherRequest); - return ResponseEntity.created(URI.create("/customers/" + voucherResponse.id())) + return ResponseEntity.created(URI.create("/api/v1/vouchers/" + voucherResponse.id())) .body(voucherResponse); }