diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..63d9a9aa9f --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +application_log diff --git a/application_log/application.log b/application_log/application.log new file mode 100644 index 0000000000..3c43a8b3bd --- /dev/null +++ b/application_log/application.log @@ -0,0 +1,30 @@ +20231015 17:36:45.137 [main] ERROR [SpringApplication:827] - Application run failed +java.lang.IllegalStateException: Failed to execute CommandLineRunner + at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:777) + at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:758) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) + at org.prgrms.vouchermanagement.VoucherManagementApplication.main(VoucherManagementApplication.java:9) +Caused by: org.prgrms.vouchermanagement.exception.InvalidInputException: 잘못된 command 입력입니다. + at org.prgrms.vouchermanagement.view.ConsoleInput.validateAndConvertToCommand(ConsoleInput.java:35) + at org.prgrms.vouchermanagement.view.ConsoleInput.commandInput(ConsoleInput.java:17) + at org.prgrms.vouchermanagement.controller.Controller.run(Controller.java:32) + at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:774) + ... 5 common frames omitted +20231024 13:43:37.391 [main] ERROR [SpringApplication:827] - Application run failed +java.lang.IllegalStateException: Failed to execute CommandLineRunner + at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:777) + at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:758) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) + at org.prgrms.vouchermanagement.VoucherManagementApplication.main(VoucherManagementApplication.java:9) +Caused by: org.prgrms.vouchermanagement.exception.InvalidRangeException: PercentDiscountPolicy는 0~100 사이의 값을 가져야 합니다. + at org.prgrms.vouchermanagement.voucher.PercentDiscountVoucher.(PercentDiscountVoucher.java:14) + at org.prgrms.vouchermanagement.service.VoucherService.getDiscountPolicy(VoucherService.java:36) + at org.prgrms.vouchermanagement.service.VoucherService.createVoucher(VoucherService.java:22) + at org.prgrms.vouchermanagement.controller.Controller.createVoucher(Controller.java:50) + at org.prgrms.vouchermanagement.controller.Controller.run(Controller.java:39) + at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:774) + ... 5 common frames omitted diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..0874d6727a --- /dev/null +++ b/build.gradle @@ -0,0 +1,28 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' +} + +group = 'org.prgrms' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + + implementation 'org.springframework.boot:spring-boot-starter-data-jdbc:' + implementation 'mysql:mysql-connector-java:8.0.28' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..7f93135c49 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ 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 100755 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..2f01e7d093 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'voucher-management' diff --git a/src/main/java/org/prgrms/vouchermanagement/VoucherManagementApplication.java b/src/main/java/org/prgrms/vouchermanagement/VoucherManagementApplication.java new file mode 100644 index 0000000000..099b1b047a --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/VoucherManagementApplication.java @@ -0,0 +1,12 @@ +package org.prgrms.vouchermanagement; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class VoucherManagementApplication { + public static void main(String[] args) { + SpringApplication.run(VoucherManagementApplication.class, args); + } + +} diff --git a/src/main/java/org/prgrms/vouchermanagement/consoleController/Controller.java b/src/main/java/org/prgrms/vouchermanagement/consoleController/Controller.java new file mode 100644 index 0000000000..6a26d68222 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/consoleController/Controller.java @@ -0,0 +1,61 @@ +package org.prgrms.vouchermanagement.consoleController; + +import org.prgrms.vouchermanagement.view.Command; +import org.prgrms.vouchermanagement.view.ConsoleInput; +import org.prgrms.vouchermanagement.view.ConsoleOutput; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +@Component +@Profile("console") +public class Controller implements CommandLineRunner { + + private final ConsoleInput consoleInput = new ConsoleInput(); + private final ConsoleOutput consoleOutput = new ConsoleOutput(); + + private final VoucherController voucherController; + private final CustomerController customerController; + private final WalletController walletController; + + + public Controller(VoucherController voucherController, CustomerController customerController, WalletController walletController) { + this.voucherController = voucherController; + this.customerController = customerController; + this.walletController = walletController; + } + + @Override + public void run(String... args) { + boolean notExitCommand = true; + + while (notExitCommand) { + consoleOutput.printWelcomeMessage(); + Command command = consoleInput.commandInput(); + + switch (command) { + case VOUCHER -> voucher(); + case CUSTOMER -> customer(); + case WALLET -> wallet(); + case EXIT -> notExitCommand = exit(); + } + } + } + + private void voucher() { + voucherController.voucher(); + } + + private void customer() { + customerController.customer(); + } + + private void wallet() { + walletController.wallet(); + } + + private boolean exit() { + consoleOutput.printExitMessage(); + return false; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/consoleController/CustomerController.java b/src/main/java/org/prgrms/vouchermanagement/consoleController/CustomerController.java new file mode 100644 index 0000000000..4ea487fdc4 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/consoleController/CustomerController.java @@ -0,0 +1,55 @@ +package org.prgrms.vouchermanagement.consoleController; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.customer.service.CustomerService; +import org.prgrms.vouchermanagement.view.Command; +import org.prgrms.vouchermanagement.view.ConsoleInput; +import org.prgrms.vouchermanagement.view.ConsoleOutput; +import org.springframework.stereotype.Controller; + +import java.util.List; + +@Controller +public class CustomerController { + + private final ConsoleOutput consoleOutput; + private final ConsoleInput consoleInput; + private final CustomerService customerService; + + public CustomerController(ConsoleOutput consoleOutput, ConsoleInput consoleInput, CustomerService customerService) { + this.consoleOutput = consoleOutput; + this.consoleInput = consoleInput; + this.customerService = customerService; + } + + public void customer() { + boolean notExitCommand = true; + + while (notExitCommand) { + consoleOutput.printCustomerOptionMessage(); + Command command = consoleInput.commandInput(); + + switch (command) { + case LIST -> showList(); + case BLACKLIST -> showBlackList(); + case EXIT -> notExitCommand = exit(); + } + } + } + + private void showList() { + List customers = customerService.showCustomerList(); + consoleOutput.printCustomerList(customers); + } + + private void showBlackList() { + List customers = customerService.showBlackCustomerList(); + consoleOutput.printBlackList(customers); + } + + + private boolean exit() { + consoleOutput.printExitMessage(); + return false; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/consoleController/VoucherController.java b/src/main/java/org/prgrms/vouchermanagement/consoleController/VoucherController.java new file mode 100644 index 0000000000..f427121415 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/consoleController/VoucherController.java @@ -0,0 +1,74 @@ +package org.prgrms.vouchermanagement.consoleController; + +import org.prgrms.vouchermanagement.dto.VoucherCreateInfo; +import org.prgrms.vouchermanagement.dto.VoucherUpdateInfo; +import org.prgrms.vouchermanagement.view.Command; +import org.prgrms.vouchermanagement.view.ConsoleInput; +import org.prgrms.vouchermanagement.view.ConsoleOutput; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.service.VoucherService; +import org.springframework.stereotype.Controller; + +import java.util.List; +import java.util.UUID; + +@Controller +public class VoucherController { + private final ConsoleOutput consoleOutput; + private final ConsoleInput consoleInput; + private final VoucherService voucherService; + + public VoucherController(ConsoleOutput consoleOutput, ConsoleInput consoleInput, VoucherService voucherService) { + this.consoleOutput = consoleOutput; + this.consoleInput = consoleInput; + this.voucherService = voucherService; + } + + public void voucher() { + boolean notExitCommand = true; + + while (notExitCommand) { + consoleOutput.printVoucherOptionMessage(); + Command command = consoleInput.commandInput(); + + switch (command) { + case CREATE -> createVoucher(); + case LIST -> voucherLists(); + case UPDATE -> updateVoucher(); + case DELETE -> deleteVoucher(); + case EXIT -> notExitCommand = exit(); + } + } + } + + private void createVoucher() { + consoleOutput.printCreateVoucherMessage(); + VoucherCreateInfo voucherInput = consoleInput.createVoucherInput(); + voucherService.createVoucher(voucherInput.policy(), voucherInput.amountOrPercent()); + consoleOutput.printCreateVoucherCompleteMessage(); + } + + private void voucherLists() { + List vouchers = voucherService.voucherLists(); + consoleOutput.printVouchers(vouchers); + } + + private void updateVoucher() { + consoleOutput.printUpdateVoucherMessage(); + VoucherUpdateInfo voucherUpdateInfo = consoleInput.updateVoucherInput(); + voucherService.updateVoucher(voucherUpdateInfo.voucherId(), voucherUpdateInfo.amountOrPercent()); + consoleOutput.printUpdateVoucherCompleteMessage(); + } + + private void deleteVoucher() { + consoleOutput.printDeleteVoucherMessage(); + UUID voucherId = consoleInput.deleteVoucherInput(); + voucherService.deleteVoucher(voucherId); + } + + + private boolean exit() { + consoleOutput.printExitMessage(); + return false; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/consoleController/WalletController.java b/src/main/java/org/prgrms/vouchermanagement/consoleController/WalletController.java new file mode 100644 index 0000000000..9ebbaf59e3 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/consoleController/WalletController.java @@ -0,0 +1,73 @@ +package org.prgrms.vouchermanagement.consoleController; + +import org.prgrms.vouchermanagement.dto.WalletCreateInfo; +import org.prgrms.vouchermanagement.view.Command; +import org.prgrms.vouchermanagement.view.ConsoleInput; +import org.prgrms.vouchermanagement.view.ConsoleOutput; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.wallet.service.WalletMapperService; +import org.springframework.stereotype.Controller; + +import java.util.List; +import java.util.UUID; + +@Controller +public class WalletController { + private final ConsoleOutput consoleOutput; + private final ConsoleInput consoleInput; + private final WalletMapperService walletMapperService; + + public WalletController(ConsoleOutput consoleOutput, ConsoleInput consoleInput, WalletMapperService walletMapperService) { + this.consoleOutput = consoleOutput; + this.consoleInput = consoleInput; + this.walletMapperService = walletMapperService; + } + + public void wallet() { + boolean notExitCommand = true; + + while (notExitCommand) { + consoleOutput.printWalletOptionMessage(); + Command command = consoleInput.commandInput(); + + switch (command) { + case CREATE -> createWallet(); + case LIST -> findVouchersByCustomerId(); + case DELETE -> deleteVoucherByCustomerId(); + case FIND -> findCustomerByVoucherId(); + case EXIT -> notExitCommand = exit(); + } + } + } + + private void createWallet() { + consoleOutput.printCreateWalletMessage(); + WalletCreateInfo walletCreateInfo = consoleInput.createWalletInput(); + walletMapperService.create(walletCreateInfo); + } + + private void findVouchersByCustomerId() { + consoleOutput.printAllVouchersByCustomerId(); + UUID customerId = consoleInput.findAllVouchersByCustomerId(); + List voucherList = walletMapperService.findVouchers(customerId); + consoleOutput.printVouchers(voucherList); + } + + private void deleteVoucherByCustomerId() { + consoleOutput.printDeleteVoucherByCustomerId(); + UUID customerId = consoleInput.deleteVoucherByCustomerId(); + walletMapperService.delete(customerId); + } + + private void findCustomerByVoucherId() { + consoleOutput.printCustomerByVoucherId(); + UUID voucherId = consoleInput.findCustomerByVoucherId(); + consoleOutput.printCustomer(walletMapperService.findCustomer(voucherId)); + } + + + private boolean exit() { + consoleOutput.printExitMessage(); + return false; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/customer/domain/Customer.java b/src/main/java/org/prgrms/vouchermanagement/customer/domain/Customer.java new file mode 100644 index 0000000000..a64395d9bf --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/customer/domain/Customer.java @@ -0,0 +1,33 @@ +package org.prgrms.vouchermanagement.customer.domain; + +import java.util.UUID; + +public class Customer { + private final UUID userId; + private final String userName; + private final int userAge; + private final boolean isBlacked; + + public Customer(UUID userId, String userName, int userAge) { + this.userId = userId; + this.userName = userName; + this.userAge = userAge; + this.isBlacked = false; + } + + public UUID getUserId() { + return userId; + } + + public String getUserName() { + return userName; + } + + public int getUserAge() { + return userAge; + } + + public boolean isBlacked() { + return isBlacked; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/customer/repository/CustomerJdbcRepository.java b/src/main/java/org/prgrms/vouchermanagement/customer/repository/CustomerJdbcRepository.java new file mode 100644 index 0000000000..45ecf281d9 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/customer/repository/CustomerJdbcRepository.java @@ -0,0 +1,52 @@ +package org.prgrms.vouchermanagement.customer.repository; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import java.nio.ByteBuffer; +import java.sql.*; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Repository +public class CustomerJdbcRepository implements CustomerRepository{ + + private static final String LOAD = "SELECT customer_id, customer_name, customer_age FROM customer"; + private static final String BLACKLIST = "SELECT customer_id, customer_name, customer_age FROM customer WHERE black = true"; + + private final JdbcTemplate jdbcTemplate; + + public CustomerJdbcRepository(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public List showCustomerList() { + return jdbcTemplate.query(LOAD, new CustomerRowMapper()); + } + + @Override + public List showBlackCustomerList() { + return jdbcTemplate.query(BLACKLIST, new CustomerRowMapper()); + } + + private class CustomerRowMapper implements RowMapper { + @Override + public Customer mapRow(ResultSet resultSet, int rowNum) throws SQLException { + UUID customerId = toUUID(resultSet.getBytes("customer_id")); + String customerName = resultSet.getString("customer_name"); + int customerAge = resultSet.getInt("customer_age"); + + return new Customer(customerId, customerName, customerAge); + } + } + + private UUID toUUID(byte[] bytes) { + ByteBuffer wrap = ByteBuffer.wrap(bytes); + return new UUID(wrap.getLong(), wrap.getLong()); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/customer/repository/CustomerRepository.java b/src/main/java/org/prgrms/vouchermanagement/customer/repository/CustomerRepository.java new file mode 100644 index 0000000000..3d91eb5b5e --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/customer/repository/CustomerRepository.java @@ -0,0 +1,13 @@ +package org.prgrms.vouchermanagement.customer.repository; + +import org.prgrms.vouchermanagement.customer.domain.Customer; + +import java.util.List; + +public interface CustomerRepository { + + List showCustomerList(); + + List showBlackCustomerList(); + +} diff --git a/src/main/java/org/prgrms/vouchermanagement/customer/service/CustomerService.java b/src/main/java/org/prgrms/vouchermanagement/customer/service/CustomerService.java new file mode 100644 index 0000000000..2c492aaf47 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/customer/service/CustomerService.java @@ -0,0 +1,25 @@ +package org.prgrms.vouchermanagement.customer.service; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.customer.repository.CustomerRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class CustomerService { + + private final CustomerRepository customerRepository; + + public CustomerService(CustomerRepository customerRepository) { + this.customerRepository = customerRepository; + } + + public List showCustomerList() { + return customerRepository.showCustomerList(); + } + + public List showBlackCustomerList() { + return customerRepository.showBlackCustomerList(); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/dto/VoucherCreateInfo.java b/src/main/java/org/prgrms/vouchermanagement/dto/VoucherCreateInfo.java new file mode 100644 index 0000000000..bc8dfecbe2 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/dto/VoucherCreateInfo.java @@ -0,0 +1,8 @@ +package org.prgrms.vouchermanagement.dto; + +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; + +public record VoucherCreateInfo( + PolicyStatus policy, + long amountOrPercent +) { } diff --git a/src/main/java/org/prgrms/vouchermanagement/dto/VoucherResponseDto.java b/src/main/java/org/prgrms/vouchermanagement/dto/VoucherResponseDto.java new file mode 100644 index 0000000000..200534e880 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/dto/VoucherResponseDto.java @@ -0,0 +1,10 @@ +package org.prgrms.vouchermanagement.dto; + +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; + +import java.util.UUID; + +public record VoucherResponseDto( + UUID voucherId, + DiscountPolicy discountPolicy +) { } diff --git a/src/main/java/org/prgrms/vouchermanagement/dto/VoucherUpdateInfo.java b/src/main/java/org/prgrms/vouchermanagement/dto/VoucherUpdateInfo.java new file mode 100644 index 0000000000..2e71792414 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/dto/VoucherUpdateInfo.java @@ -0,0 +1,8 @@ +package org.prgrms.vouchermanagement.dto; + +import java.util.UUID; + +public record VoucherUpdateInfo ( + UUID voucherId, + long amountOrPercent +) { } diff --git a/src/main/java/org/prgrms/vouchermanagement/dto/WalletCreateInfo.java b/src/main/java/org/prgrms/vouchermanagement/dto/WalletCreateInfo.java new file mode 100644 index 0000000000..4783fa3b4b --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/dto/WalletCreateInfo.java @@ -0,0 +1,8 @@ +package org.prgrms.vouchermanagement.dto; + +import java.util.UUID; + +public record WalletCreateInfo ( + UUID customerId, + UUID voucherId +) {} diff --git a/src/main/java/org/prgrms/vouchermanagement/exception/InsertFailException.java b/src/main/java/org/prgrms/vouchermanagement/exception/InsertFailException.java new file mode 100644 index 0000000000..e1cf8deb61 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/exception/InsertFailException.java @@ -0,0 +1,7 @@ +package org.prgrms.vouchermanagement.exception; + +public class InsertFailException extends RuntimeException { + public InsertFailException(String message) { + super(message); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/exception/InvalidInputException.java b/src/main/java/org/prgrms/vouchermanagement/exception/InvalidInputException.java new file mode 100644 index 0000000000..9cf662fd6d --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/exception/InvalidInputException.java @@ -0,0 +1,7 @@ +package org.prgrms.vouchermanagement.exception; + +public class InvalidInputException extends RuntimeException{ + public InvalidInputException(String message) { + super(message); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/exception/InvalidRangeException.java b/src/main/java/org/prgrms/vouchermanagement/exception/InvalidRangeException.java new file mode 100644 index 0000000000..0bae4d5960 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/exception/InvalidRangeException.java @@ -0,0 +1,7 @@ +package org.prgrms.vouchermanagement.exception; + +public class InvalidRangeException extends RuntimeException{ + public InvalidRangeException(String message) { + super(message); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/exception/LoadFailException.java b/src/main/java/org/prgrms/vouchermanagement/exception/LoadFailException.java new file mode 100644 index 0000000000..e2465786e9 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/exception/LoadFailException.java @@ -0,0 +1,7 @@ +package org.prgrms.vouchermanagement.exception; + +public class LoadFailException extends RuntimeException { + public LoadFailException(String message) { + super(message); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/view/Command.java b/src/main/java/org/prgrms/vouchermanagement/view/Command.java new file mode 100644 index 0000000000..52fcb0cda4 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/view/Command.java @@ -0,0 +1,15 @@ +package org.prgrms.vouchermanagement.view; + +public enum Command { + VOUCHER, // VOUCHER 메뉴 + CUSTOMER, // CUSTOMER 메뉴 이동 + WALLET, // WALLET 메뉴로 이동 + EXIT, // 종료 + + CREATE, // 바우처 생성, 지갑 생성 + LIST, // 바우처 리스트, 고객 리스트 + BLACKLIST, // 고객 블랙 리스트 + UPDATE, //바우처 업데이트 + DELETE, //바우처 전부 삭제, 지갑 삭제 + FIND // 바우처 id로 고객 찾기 +} diff --git a/src/main/java/org/prgrms/vouchermanagement/view/ConsoleInput.java b/src/main/java/org/prgrms/vouchermanagement/view/ConsoleInput.java new file mode 100644 index 0000000000..f61a3b53bd --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/view/ConsoleInput.java @@ -0,0 +1,107 @@ +package org.prgrms.vouchermanagement.view; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.dto.VoucherCreateInfo; +import org.prgrms.vouchermanagement.dto.VoucherUpdateInfo; +import org.prgrms.vouchermanagement.dto.WalletCreateInfo; +import org.prgrms.vouchermanagement.exception.InvalidInputException; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.springframework.stereotype.Component; + +import java.util.Scanner; +import java.util.UUID; + +@Component +public class ConsoleInput { + + private final Scanner scanner = new Scanner(System.in); + private final ConsoleOutput consoleOutput = new ConsoleOutput(); + + public Command commandInput() { + consoleOutput.getInput(); + String inputCommand = scanner.nextLine(); + return validateAndConvertToCommand(inputCommand); + } + + public VoucherCreateInfo createVoucherInput() { + consoleOutput.getInput(); + String inputPolicy = scanner.nextLine(); + PolicyStatus policy = validateAndConvertPolicy(inputPolicy); + + consoleOutput.getInput(); + String inputAmountOrPercent = scanner.nextLine(); + long amountOrPercent = validateAndConvertAmountOrPercent(inputAmountOrPercent); + return new VoucherCreateInfo(policy, amountOrPercent); + } + + public UUID deleteVoucherInput() { + consoleOutput.getInput(); + return UUID.fromString(scanner.nextLine()); + } + + public VoucherUpdateInfo updateVoucherInput() { + consoleOutput.getInput(); + UUID voucherId = UUID.fromString(scanner.nextLine()); + + consoleOutput.getInput(); + String inputAmountOrPercent = scanner.nextLine(); + long amountOrPercent = validateAndConvertAmountOrPercent(inputAmountOrPercent); + return new VoucherUpdateInfo(voucherId, amountOrPercent); + } + + public WalletCreateInfo createWalletInput() { + consoleOutput.getInput(); + UUID customerId = UUID.fromString(scanner.nextLine()); + + consoleOutput.getInput(); + UUID voucherId = UUID.fromString(scanner.nextLine()); + return new WalletCreateInfo(customerId, voucherId); + } + + public UUID findAllVouchersByCustomerId() { + consoleOutput.getInput(); + return UUID.fromString(scanner.nextLine()); + } + + public UUID deleteVoucherByCustomerId() { + consoleOutput.getInput(); + return UUID.fromString(scanner.nextLine()); + } + + public UUID findCustomerByVoucherId() { + consoleOutput.getInput(); + return UUID.fromString(scanner.nextLine()); + } + + private Command validateAndConvertToCommand(String inputCommand) { + try { + return Command.valueOf(inputCommand.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new InvalidInputException("잘못된 command 입력입니다."); + } + } + + private PolicyStatus validateAndConvertPolicy(String inputPolicy) { + try { + return PolicyStatus.valueOf(inputPolicy.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new InvalidInputException("잘못된 policy 입력입니다."); + } + } + + private int validateAndConvertAge(String age) { + try { + return Integer.parseInt(age); + } catch (NumberFormatException e) { + throw new InvalidInputException("잘못된 age 입력입니다."); + } + } + + private long validateAndConvertAmountOrPercent(String inputAmountOrPercent) { + try { + return Long.parseLong(inputAmountOrPercent); + } catch (NumberFormatException e) { + throw new InvalidInputException("잘못된 amountOrPercent 입력입니다."); + } + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/view/ConsoleOutput.java b/src/main/java/org/prgrms/vouchermanagement/view/ConsoleOutput.java new file mode 100644 index 0000000000..43f6e8f2f5 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/view/ConsoleOutput.java @@ -0,0 +1,234 @@ +package org.prgrms.vouchermanagement.view; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class ConsoleOutput { + + private static final String welcome = """ + + === Voucher Program === + Type voucher to view voucher option. + Type customer to view customer option. + Type wallet to view wallet option. + Type exit to exit the program. + """; + + private static final String customerOption = """ + + Type list to list all customers. + Type blacklist to list all black customers. + Type exit to exit customer option + """; + + private static final String voucherOption = """ + + Type create to create new voucher. + Type list to list all vouchers. + Type update to update voucher by voucherId. + Type delete to delete voucher by voucherId. + Type exit to exit customer option + """; + + private static final String walletOption = """ + + Type create to create new wallet. + Type list to list all wallet. + Type delete to delete wallet by customerId. + Type find to find customer by voucherId. + Type exit to exit customer option + """; + + private static final String createVoucher = """ + + === CREATE VOUCHER === + select policy(fixed, percent) + input amount or percent + """; + + private static final String createVoucherComplete = """ + + === COMPLETE CREATE VOUCHER === + """; + + private static final String showVoucherLists = """ + + === VOUCHER LISTS === + """; + + private static final String showCustomerList = """ + + === CUSTOMER LISTS === + """; + + private static final String showBlackList = """ + + === CUSTOMER BLACKLIST === + """; + + private static final String updateVoucher = """ + + === VOUCHER UPDATE === + update amount or percent by voucherId + + input voucherId(UUID) + input amount or percent + """; + + private static final String updateVoucherComplete = """ + + === COMPLETE UPDATE VOUCHER === + """; + + private static final String deleteVoucher = """ + + === VOUCHER DELETE === + """; + + private static final String wallet = """ + + === WALLET PAGE === + Type create to create a new wallet + Type list to find all vouchers by customerId + Type delete to delete voucher by customerId + Type find to find customer by voucherId + Type exit to exit the program. + """; + + private static final String createWallet = """ + + == CREATE WALLET == + + input customerId(UUID) + input voucherId(UUID) + """; + + private static final String findVoucherWallet = """ + + == FIND ALL VOUCHERS BY CUSTOMER ID == + + input customerId(UUID) + """; + + private static final String deleteVoucherWallet = """ + + == DELETE VOUCHER BY CUSTOMER ID == + + input customerId(UUID) + """; + + private static final String findCustomerWallet = """ + + == FIND CUSTOMER BY VOUCHER ID + + input voucherId(UUID) + """; + + + private static final String exit = """ + + === Bye Bye === + """; + + public void printMessage(String message) { + System.out.print(message); + } + + public void printlnMessage(String message) { + System.out.println(message); + } + + public void getInput() { + System.out.print("> "); + } + + public void printWelcomeMessage() { + printMessage(welcome); + } + + public void printCustomerOptionMessage() { + printMessage(customerOption); + } + + public void printVoucherOptionMessage() { + printMessage(voucherOption); + } + + public void printWalletOptionMessage() { + printMessage(walletOption); + } + + public void printCreateVoucherMessage() { + printMessage(createVoucher); + } + + public void printCreateVoucherCompleteMessage() { + printMessage(createVoucherComplete); + } + + public void printUpdateVoucherMessage() { + printMessage(updateVoucher); + } + + public void printUpdateVoucherCompleteMessage() { + printMessage(updateVoucherComplete); + } + + public void printDeleteVoucherMessage() { + printMessage(deleteVoucher); + } + + public void printWalletMessage() { + printMessage(wallet); + } + + public void printCreateWalletMessage() { + printMessage(createWallet); + } + + public void printAllVouchersByCustomerId() { + printMessage(findVoucherWallet); + } + + public void printDeleteVoucherByCustomerId() { + printMessage(deleteVoucherWallet); + } + + public void printCustomerByVoucherId() { + printMessage(findCustomerWallet); + } + + public void printCustomerList(List customerList) { + printMessage(showCustomerList); + for (Customer customer : customerList) { + printlnMessage("customerId : " + customer.getUserId() + ", name : " + customer.getUserName() + ", age : " + customer.getUserAge()); + } + } + + public void printCustomer(Customer customer) { + printlnMessage("customerId : " + customer.getUserId() + ", name : " + customer.getUserName() + ", age : " + customer.getUserAge()); + } + + public void printBlackList(List blackList) { + printMessage(showBlackList); + for(Customer blackCustomer : blackList) { + printlnMessage("customerId : " + blackCustomer.getUserId() + ", name : " + blackCustomer.getUserName() + ", age : " + blackCustomer.getUserAge()); + } + } + + public void printVouchers(List vouchers) { + printMessage(showVoucherLists); + for(Voucher voucher : vouchers) { + printlnMessage("voucherId : " + voucher.getVoucherId() + ", policy : " + voucher.getDiscountPolicy().getPolicyStatus() + ", amountOrPercent : " + voucher.getDiscountPolicy().getAmountOrPercent()); + } + } + + public void printExitMessage() { + printMessage(exit); + } + +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/org/prgrms/vouchermanagement/voucher/domain/Voucher.java new file mode 100644 index 0000000000..8cb4b2531a --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/domain/Voucher.java @@ -0,0 +1,23 @@ +package org.prgrms.vouchermanagement.voucher.domain; + +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; + +import java.util.UUID; + +public class Voucher { + private final UUID voucherId; + private final DiscountPolicy discountPolicy; + + public Voucher(UUID voucherId, DiscountPolicy discountPolicy) { + this.voucherId = voucherId; + this.discountPolicy = discountPolicy; + } + + public UUID getVoucherId() { + return voucherId; + } + + public DiscountPolicy getDiscountPolicy() { + return discountPolicy; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/policy/DiscountPolicy.java b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/DiscountPolicy.java new file mode 100644 index 0000000000..6e7b6960a4 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/DiscountPolicy.java @@ -0,0 +1,9 @@ +package org.prgrms.vouchermanagement.voucher.policy; + +public interface DiscountPolicy { + long getAmountOrPercent(); + + PolicyStatus getPolicyStatus(); + + long discount(long price); +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/policy/FixedAmountVoucher.java b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/FixedAmountVoucher.java new file mode 100644 index 0000000000..50b79cefc1 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/FixedAmountVoucher.java @@ -0,0 +1,26 @@ +package org.prgrms.vouchermanagement.voucher.policy; + +public class FixedAmountVoucher implements DiscountPolicy { + + private final long amount; + private final PolicyStatus policyStatus = PolicyStatus.FIXED; + + public FixedAmountVoucher(long amount) { + this.amount = amount; + } + + @Override + public long getAmountOrPercent() { + return amount; + } + + @Override + public PolicyStatus getPolicyStatus() { + return policyStatus; + } + + @Override + public long discount(long price) { + return price - amount; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/policy/PercentDiscountVoucher.java b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/PercentDiscountVoucher.java new file mode 100644 index 0000000000..83bdd445e0 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/PercentDiscountVoucher.java @@ -0,0 +1,32 @@ +package org.prgrms.vouchermanagement.voucher.policy; + +import org.prgrms.vouchermanagement.exception.InvalidRangeException; + +public class PercentDiscountVoucher implements DiscountPolicy { + + private final long percent; + private final PolicyStatus policyStatus = PolicyStatus.PERCENT; + + public PercentDiscountVoucher(long percent) { + this.percent = percent; + + if (percent < 0 || percent > 100) { + throw new InvalidRangeException("PercentDiscountPolicy는 0~100 사이의 값을 가져야 합니다."); + } + } + + @Override + public long getAmountOrPercent() { + return percent; + } + + @Override + public PolicyStatus getPolicyStatus() { + return policyStatus; + } + + @Override + public long discount(long price) { + return (price - (price/percent)); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/policy/PolicyStatus.java b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/PolicyStatus.java new file mode 100644 index 0000000000..7ae75ecdc8 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/policy/PolicyStatus.java @@ -0,0 +1,6 @@ +package org.prgrms.vouchermanagement.voucher.policy; + +public enum PolicyStatus { + FIXED, //고정 + PERCENT //퍼센트 +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/repository/DatabaseRepository.java b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/DatabaseRepository.java new file mode 100644 index 0000000000..c63e5419ec --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/DatabaseRepository.java @@ -0,0 +1,111 @@ +package org.prgrms.vouchermanagement.voucher.repository; + +import org.prgrms.vouchermanagement.exception.LoadFailException; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; +import org.prgrms.vouchermanagement.voucher.policy.FixedAmountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PercentDiscountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.prgrms.vouchermanagement.wallet.repository.WalletMapperJdbcMapperRepository; +import org.springframework.context.annotation.Profile; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import java.nio.ByteBuffer; +import java.sql.*; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Repository +@Profile("database") +public class DatabaseRepository implements VoucherRepository { + private static final String LOAD = "SELECT voucher_id, discount_policy, amount FROM voucher"; + private static final String CREATE = "INSERT INTO voucher(voucher_id, discount_policy, amount) VALUES(UUID_TO_BIN(?), (?), (?))"; + private static final String FIND_BY_ID = "SELECT voucher_id, discount_policy, amount FROM voucher WHERE voucher_id = UUID_TO_BIN(?)"; + private static final String UPDATE_AMOUNT_BY_ID = "UPDATE voucher SET amount = ? WHERE voucher_id = UUID_TO_BIN(?)"; + private static final String DELETE_BY_ID = "DELETE FROM voucher WHERE voucher_id = UUID_TO_BIN(?)"; + private static final String FIND_BY_POLICY = "SELECT voucher_id, discount_policy, amount FROM voucher WHERE discount_policy = ?"; + + private final JdbcTemplate jdbcTemplate; + + public DatabaseRepository(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + //create + @Override + public int create(UUID voucherId, DiscountPolicy discountPolicy) { + String policy = String.valueOf(discountPolicy.getPolicyStatus()); + long amount = discountPolicy.getAmountOrPercent(); + + return jdbcTemplate.update(CREATE, voucherId.toString().getBytes(), policy, amount); + } + + //read + @Override + public List voucherLists() { + return jdbcTemplate.query(LOAD, new VoucherRowMapper()); + } + + //update + public void update(UUID voucherId, long amountOrPercent) { + jdbcTemplate.update(UPDATE_AMOUNT_BY_ID, amountOrPercent, voucherId.toString().getBytes()); + } + + //delete + @Override + public int delete(UUID voucherId) { + return jdbcTemplate.update(DELETE_BY_ID, voucherId.toString().getBytes()); + } + + //find + @Override + public Voucher findById(UUID voucherId) { + try { + return jdbcTemplate.queryForObject(FIND_BY_ID, new Object[]{voucherId.toString().getBytes()}, new VoucherRowMapper()); + } catch (EmptyResultDataAccessException e) { + throw new LoadFailException("찾을 수 없습니다."); + } + } + + @Override + public List findVoucherByPolicy(PolicyStatus policy) { + return jdbcTemplate.query(FIND_BY_POLICY, new VoucherRowMapper(), policy.name()); + } + + //load 역할 + //static -> toUUID때문에 x + private class VoucherRowMapper implements RowMapper { + @Override + public Voucher mapRow(ResultSet resultSet, int rowNum) throws SQLException { + UUID voucherId = toUUID(resultSet.getBytes("voucher_id")); + PolicyStatus policy = PolicyStatus.valueOf(resultSet.getString("discount_policy").toUpperCase()); + long amountOrPercent = resultSet.getLong("amount"); + + DiscountPolicy discountPolicy = getPolicy(policy, amountOrPercent); + + return new Voucher(voucherId, discountPolicy); + } + } + + private DiscountPolicy getPolicy(PolicyStatus policy, long amountOrPercent) { + DiscountPolicy discountPolicy = null; + + if (policy == PolicyStatus.FIXED) { + discountPolicy = new FixedAmountVoucher(amountOrPercent); + } else if (policy == PolicyStatus.PERCENT) { + discountPolicy = new PercentDiscountVoucher(amountOrPercent); + } + + return discountPolicy; + } + + private UUID toUUID(byte[] bytes) { + ByteBuffer wrap = ByteBuffer.wrap(bytes); + return new UUID(wrap.getLong(), wrap.getLong()); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/repository/FileRepository.java b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/FileRepository.java new file mode 100644 index 0000000000..a7e75ccf5d --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/FileRepository.java @@ -0,0 +1,96 @@ +package org.prgrms.vouchermanagement.voucher.repository; + +import org.prgrms.vouchermanagement.exception.InsertFailException; +import org.prgrms.vouchermanagement.exception.LoadFailException; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; +import org.prgrms.vouchermanagement.voucher.policy.FixedAmountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PercentDiscountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.io.*; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Repository +@Profile("dev") +public class FileRepository implements VoucherRepository{ + + private static final String path = "./voucherFile/voucherFile"; + private final Map storage = new ConcurrentHashMap<>(); + + public FileRepository() { + if(storage.isEmpty()) { + try (BufferedReader reader = new BufferedReader(new FileReader(path))) { + String line; + while ((line = reader.readLine()) != null) { + String[] parts = line.split(","); + + UUID voucherId = UUID.fromString(parts[0]); + PolicyStatus policy = PolicyStatus.valueOf(parts[1]); + long amountOrPercent = Long.parseLong(parts[2]); + + DiscountPolicy discountPolicy = null; + if (policy == PolicyStatus.FIXED) { + discountPolicy = new FixedAmountVoucher(amountOrPercent); + } else if (policy == PolicyStatus.PERCENT) { + discountPolicy = new PercentDiscountVoucher(amountOrPercent); + } + + storage.put(voucherId, new Voucher(voucherId, discountPolicy)); + } + } catch (IOException e) { + throw new LoadFailException("파일로부터 읽어올 수 없습니다."); + } + } + } + + @Override + public int create(UUID voucherId, DiscountPolicy discountPolicy) { + + long amountOrPercent = discountPolicy.getAmountOrPercent(); + PolicyStatus policy = discountPolicy.getPolicyStatus(); + + try (BufferedWriter writer = new BufferedWriter(new FileWriter(path, true))) { + writer.write(voucherId + "," + policy + "," + amountOrPercent); + writer.newLine(); // 새로운 줄 추가 + } catch (IOException e) { + throw new InsertFailException("데이터 삽입에 실패하였습니다."); + } + + Voucher voucher = new Voucher(voucherId, discountPolicy); + storage.put(voucherId, voucher); + + return 0; + } + + @Override + public List voucherLists() { + return storage.values().stream() + .toList(); + } + + @Override + public void update(UUID voucherId, long amount) { + } + + @Override + public int delete(UUID voucherId) { + + return 0; + } + + @Override + public Voucher findById(UUID voucherId) { + return storage.get(voucherId); + } + + @Override + public List findVoucherByPolicy(PolicyStatus policy) { + return null; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/repository/MemoryRepository.java b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/MemoryRepository.java new file mode 100644 index 0000000000..c6a4ce678c --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/MemoryRepository.java @@ -0,0 +1,53 @@ +package org.prgrms.vouchermanagement.voucher.repository; + +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Repository +@Profile("local") +public class MemoryRepository implements VoucherRepository{ + + private final Map storage = new ConcurrentHashMap<>(); + + @Override + public int create(UUID voucherId, DiscountPolicy discountPolicy) { + Voucher voucher = new Voucher(voucherId, discountPolicy); + storage.put(voucherId, voucher); + + return 0; + } + + @Override + public List voucherLists() { + return storage.values().stream() + .toList(); + } + + @Override + public void update(UUID voucherId, long amount) { + } + + @Override + public int delete(UUID voucherId) { + + return 0; + } + + @Override + public Voucher findById(UUID voucherId) { + return storage.get(voucherId); + } + + @Override + public List findVoucherByPolicy(PolicyStatus policy) { + return null; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/VoucherRepository.java new file mode 100644 index 0000000000..b8b97235e9 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/repository/VoucherRepository.java @@ -0,0 +1,22 @@ +package org.prgrms.vouchermanagement.voucher.repository; + +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; + +import java.util.List; +import java.util.UUID; + +public interface VoucherRepository { + int create(UUID voucherId, DiscountPolicy discountPolicy); + + List voucherLists(); + + void update(UUID voucherId, long amount); + + int delete(UUID voucherId); + + Voucher findById(UUID voucherId); + + List findVoucherByPolicy(PolicyStatus policy); +} diff --git a/src/main/java/org/prgrms/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/org/prgrms/vouchermanagement/voucher/service/VoucherService.java new file mode 100644 index 0000000000..bf6866fb70 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/voucher/service/VoucherService.java @@ -0,0 +1,70 @@ +package org.prgrms.vouchermanagement.voucher.service; + +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; +import org.prgrms.vouchermanagement.voucher.policy.FixedAmountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PercentDiscountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.prgrms.vouchermanagement.voucher.repository.VoucherRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@Service +public class VoucherService { + + private final VoucherRepository voucherRepository; + + /* + pr + model 비즈니스 로직 + view 뿌리기 + controller 전달 + */ + + public VoucherService(VoucherRepository voucherRepository) { + this.voucherRepository = voucherRepository; + } + + public Voucher createVoucher(PolicyStatus policy, long amountOrPercent) { + UUID voucherId = UUID.randomUUID(); + DiscountPolicy discountPolicy = getDiscountPolicy(policy, amountOrPercent); + voucherRepository.create(voucherId, discountPolicy); + return new Voucher(voucherId, discountPolicy); + } + + public Voucher findVoucher(UUID voucherId) { + return voucherRepository.findById(voucherId); + } + + public List voucherLists() { + return voucherRepository.voucherLists(); + } + + public Voucher updateVoucher(UUID voucherId, long amountOrPercent) { + voucherRepository.update(voucherId, amountOrPercent); + DiscountPolicy discountPolicy = getDiscountPolicy(findVoucher(voucherId).getDiscountPolicy().getPolicyStatus(), amountOrPercent); + return new Voucher(voucherId, discountPolicy); + } + + public Voucher deleteVoucher(UUID voucherId) { + Voucher voucher = voucherRepository.findById(voucherId); + voucherRepository.delete(voucherId); + return voucher; + } + + public List findVouchersByPolicy(PolicyStatus policy) { + return voucherRepository.findVoucherByPolicy(policy); + } + + private DiscountPolicy getDiscountPolicy(PolicyStatus policy, long amountOrPercent) { + DiscountPolicy discountPolicy = null; + if (policy == PolicyStatus.FIXED) { + discountPolicy = new FixedAmountVoucher(amountOrPercent); + } else if (policy == PolicyStatus.PERCENT) { + discountPolicy = new PercentDiscountVoucher(amountOrPercent); + } + return discountPolicy; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/wallet/domain/WalletMapper.java b/src/main/java/org/prgrms/vouchermanagement/wallet/domain/WalletMapper.java new file mode 100644 index 0000000000..876c62f399 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/wallet/domain/WalletMapper.java @@ -0,0 +1,21 @@ +package org.prgrms.vouchermanagement.wallet.domain; + +import java.util.UUID; + +public class WalletMapper { + private final UUID customerId; + private final UUID voucherId; + + public WalletMapper(UUID customerId, UUID voucherId) { + this.customerId = customerId; + this.voucherId = voucherId; + } + + public UUID getCustomerId() { + return customerId; + } + + public UUID getVoucherId() { + return voucherId; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/wallet/repository/WalletMapperJdbcMapperRepository.java b/src/main/java/org/prgrms/vouchermanagement/wallet/repository/WalletMapperJdbcMapperRepository.java new file mode 100644 index 0000000000..a59b6c72fc --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/wallet/repository/WalletMapperJdbcMapperRepository.java @@ -0,0 +1,114 @@ +package org.prgrms.vouchermanagement.wallet.repository; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.dto.WalletCreateInfo; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.DiscountPolicy; +import org.prgrms.vouchermanagement.voucher.policy.FixedAmountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PercentDiscountVoucher; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.prgrms.vouchermanagement.wallet.domain.WalletMapper; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import java.nio.ByteBuffer; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Repository +public class WalletMapperJdbcMapperRepository implements WalletMapperRepository { + + private static final String CREATE = "INSERT INTO wallet(customer_id, voucher_id) VALUES(UUID_TO_BIN(?), UUID_TO_BIN(?))"; + private static final String FINDVOUCHERS = "select v.voucher_id, v.discount_policy, v.amount FROM voucher v JOIN wallet w ON v.voucher_id = w.voucher_id WHERE w.customer_id = UUID_TO_BIN(?)"; + private static final String DELETE = "DELETE FROM wallet WHERE customer_id = UUID_TO_BIN(?)"; + private static final String FINDCUSTOMER = "SELECT c.customer_id, c.customer_name, c.customer_age FROM wallet w, customer c WHERE w.customer_id = c.customer_id AND w.voucher_id = UUID_TO_BIN(?)"; + private static final String FINDALL = "SELECT customer_id, voucher_id FROM wallet"; + + private final JdbcTemplate jdbcTemplate; + + public WalletMapperJdbcMapperRepository(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public int create(WalletCreateInfo walletCreateInfo) { + UUID customerId = walletCreateInfo.customerId(); + UUID voucherId = walletCreateInfo.voucherId(); + + return jdbcTemplate.update(CREATE, customerId.toString().getBytes(), voucherId.toString().getBytes()); + } + + @Override + public List findVouchers(UUID customerId) { + return jdbcTemplate.query(FINDVOUCHERS, new Object[]{customerId.toString().getBytes()}, new VoucherRowMapper()); + } + + public List findAll() { + return jdbcTemplate.query(FINDALL, new WalletRowMapper()); + } + + @Override + public int delete(UUID customerId) { + return jdbcTemplate.update(DELETE, customerId.toString().getBytes()); + } + + public Optional findCustomer(UUID voucherId) { + List customers = jdbcTemplate.query(FINDCUSTOMER, new Object[]{voucherId.toString().getBytes()}, new CustomerRowMapper()); + return customers.stream().findFirst(); + } + + private class WalletRowMapper implements RowMapper { + @Override + public WalletMapper mapRow(ResultSet resultSet, int rowNum) throws SQLException { + UUID customerId = toUUID(resultSet.getBytes("customer_id")); + UUID voucherId = toUUID(resultSet.getBytes("voucher_id")); + + return new WalletMapper(customerId, voucherId); + } + } + + private class VoucherRowMapper implements RowMapper { + @Override + public Voucher mapRow(ResultSet resultSet, int rowNum) throws SQLException { + UUID voucherId = toUUID(resultSet.getBytes("voucher_id")); + PolicyStatus policy = PolicyStatus.valueOf(resultSet.getString("discount_policy").toUpperCase()); + long amountOrPercent = resultSet.getLong("amount"); + + DiscountPolicy discountPolicy = getPolicy(policy, amountOrPercent); + + return new Voucher(voucherId, discountPolicy); + } + } + + private class CustomerRowMapper implements RowMapper { + @Override + public Customer mapRow(ResultSet resultSet, int rowNum) throws SQLException { + UUID customerId = toUUID(resultSet.getBytes("customer_id")); + String customerName = resultSet.getString("customer_name"); + int customerAge = resultSet.getInt("customer_age"); + + return new Customer(customerId, customerName, customerAge); + } + } + + private DiscountPolicy getPolicy(PolicyStatus policy, long amountOrPercent) { + DiscountPolicy discountPolicy = null; + + if (policy == PolicyStatus.FIXED) { + discountPolicy = new FixedAmountVoucher(amountOrPercent); + } else if (policy == PolicyStatus.PERCENT) { + discountPolicy = new PercentDiscountVoucher(amountOrPercent); + } + + return discountPolicy; + } + + private UUID toUUID(byte[] bytes) { + ByteBuffer wrap = ByteBuffer.wrap(bytes); + return new UUID(wrap.getLong(), wrap.getLong()); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/wallet/repository/WalletMapperRepository.java b/src/main/java/org/prgrms/vouchermanagement/wallet/repository/WalletMapperRepository.java new file mode 100644 index 0000000000..0bf336469e --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/wallet/repository/WalletMapperRepository.java @@ -0,0 +1,23 @@ +package org.prgrms.vouchermanagement.wallet.repository; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.dto.WalletCreateInfo; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.wallet.domain.WalletMapper; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface WalletMapperRepository { + + int create(WalletCreateInfo walletCreateInfo); + + List findVouchers(UUID customerId); + + int delete(UUID customerId); + + List findAll(); + + Optional findCustomer(UUID voucherId); +} diff --git a/src/main/java/org/prgrms/vouchermanagement/wallet/service/WalletMapperService.java b/src/main/java/org/prgrms/vouchermanagement/wallet/service/WalletMapperService.java new file mode 100644 index 0000000000..416a233b5a --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/wallet/service/WalletMapperService.java @@ -0,0 +1,46 @@ +package org.prgrms.vouchermanagement.wallet.service; + +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.dto.WalletCreateInfo; +import org.prgrms.vouchermanagement.exception.LoadFailException; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.wallet.domain.WalletMapper; +import org.prgrms.vouchermanagement.wallet.repository.WalletMapperRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@Service +public class WalletMapperService { + + private final WalletMapperRepository walletMapperRepository; + + public WalletMapperService(WalletMapperRepository walletMapperRepository) { + this.walletMapperRepository = walletMapperRepository; + } + + public WalletCreateInfo create(WalletCreateInfo walletCreateInfo) { + walletMapperRepository.create(walletCreateInfo); + return walletCreateInfo; + } + + public List findVouchers(UUID customerId) { + return walletMapperRepository.findVouchers(customerId); + } + + public UUID delete(UUID customerId) { + walletMapperRepository.delete(customerId); + return customerId; + } + + public Customer findCustomer(UUID voucherId) { + return walletMapperRepository + .findCustomer(voucherId) + .orElseThrow(() -> new LoadFailException("찾을 수 없습니다.")); + } + + public List findAll() { + return walletMapperRepository.findAll(); + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/webController/HomeController.java b/src/main/java/org/prgrms/vouchermanagement/webController/HomeController.java new file mode 100644 index 0000000000..557c401c5b --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/webController/HomeController.java @@ -0,0 +1,12 @@ +package org.prgrms.vouchermanagement.webController; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class HomeController { + @GetMapping("/") + public String home() { + return "home"; + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/webController/VoucherApiController.java b/src/main/java/org/prgrms/vouchermanagement/webController/VoucherApiController.java new file mode 100644 index 0000000000..92239b9873 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/webController/VoucherApiController.java @@ -0,0 +1,105 @@ +package org.prgrms.vouchermanagement.webController; + +import org.prgrms.vouchermanagement.dto.VoucherCreateInfo; +import org.prgrms.vouchermanagement.dto.VoucherResponseDto; +import org.prgrms.vouchermanagement.exception.InvalidInputException; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.prgrms.vouchermanagement.voucher.service.VoucherService; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/api/v1/voucher") +public class VoucherApiController { + + private final VoucherService voucherService; + + public VoucherApiController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + + @PostMapping + public VoucherResponseDto createVoucher(@RequestBody VoucherCreateInfo voucherCreateInfo) { + PolicyStatus policy = validateAndConvertPolicy(voucherCreateInfo.policy().toString()); + long amountOrPercent = validateAndConvertAmountOrPercent(String.valueOf(voucherCreateInfo.amountOrPercent())); + + Voucher voucher = voucherService.createVoucher(policy, amountOrPercent); + + return new VoucherResponseDto(voucher.getVoucherId(), voucher.getDiscountPolicy()); + } + + @GetMapping + public List findVouchers( + @RequestParam(name = "voucherId", required = false) String voucherId, + @RequestParam(name = "policy", required = false) String policy + ) { + + List vouchers = new ArrayList<>(); + + if (voucherId != null && policy != null) { + // voucherId와 policy 모두 제공된 경우 + UUID getVoucherId = UUID.fromString(voucherId); + Voucher findVoucher = voucherService.findVoucher(getVoucherId); + vouchers.add(new VoucherResponseDto(findVoucher.getVoucherId(), findVoucher.getDiscountPolicy())); + } else if (voucherId != null) { + // voucherId만 제공된 경우 + UUID getVoucherId = UUID.fromString(voucherId); + Voucher findVoucher = voucherService.findVoucher(getVoucherId); + vouchers.add(new VoucherResponseDto(findVoucher.getVoucherId(), findVoucher.getDiscountPolicy())); + } else if (policy != null) { + // policy만 제공된 경우 + PolicyStatus getPolicy = validateAndConvertPolicy(policy); + List vouchersByPolicy = voucherService.findVouchersByPolicy(getPolicy); + for (Voucher voucher : vouchersByPolicy) { + vouchers.add(new VoucherResponseDto(voucher.getVoucherId(), voucher.getDiscountPolicy())); + } + } else { + //검색 조건이 없는 경우 -> 전체 조회 + List getVouchers = voucherService.voucherLists(); + for (Voucher voucher : getVouchers) { + vouchers.add(new VoucherResponseDto(voucher.getVoucherId(), voucher.getDiscountPolicy())); + } + } + return vouchers; + } + + @PatchMapping + public VoucherResponseDto updateVoucher( + @RequestParam(name = "voucherId") String voucherId, + @RequestParam(name = "amount") long amount + ) { + + Voucher voucher = voucherService.updateVoucher(UUID.fromString(voucherId), amount); + + return new VoucherResponseDto(voucher.getVoucherId(), voucher.getDiscountPolicy()); + } + + @DeleteMapping("{voucherId}") + public VoucherResponseDto deleteVoucher(@PathVariable UUID voucherId) { + Voucher voucher = voucherService.deleteVoucher(voucherId); + + return new VoucherResponseDto(voucher.getVoucherId(), voucher.getDiscountPolicy()); + } + + private PolicyStatus validateAndConvertPolicy(String inputPolicy) { + try { + return PolicyStatus.valueOf(inputPolicy.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new InvalidInputException("잘못된 policy 입력입니다."); + } + } + + private long validateAndConvertAmountOrPercent(String inputAmountOrPercent) { + try { + return Long.parseLong(inputAmountOrPercent); + } catch (NumberFormatException e) { + throw new InvalidInputException("잘못된 amountOrPercent 입력입니다."); + } + } + +} diff --git a/src/main/java/org/prgrms/vouchermanagement/webController/VoucherWebController.java b/src/main/java/org/prgrms/vouchermanagement/webController/VoucherWebController.java new file mode 100644 index 0000000000..2fec9aef7e --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/webController/VoucherWebController.java @@ -0,0 +1,98 @@ +package org.prgrms.vouchermanagement.webController; + +import org.prgrms.vouchermanagement.exception.InvalidInputException; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.PolicyStatus; +import org.prgrms.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; + +@Controller +@Profile("web") +@RequestMapping("/voucher") +public class VoucherWebController { + + //api path + + private final VoucherService voucherService; + + public VoucherWebController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + @GetMapping("/voucher-home") + public String voucherHome() { + return "voucher/voucher-home"; + } + + @GetMapping("/create") + public String createVoucher() { + return "voucher/create"; + } + + @PostMapping("/create") + public String createVoucher(@RequestParam("policy") String policy, @RequestParam("amount") long amount) { + voucherService.createVoucher(validateAndConvertPolicy(policy), validateAndConvertAmountOrPercent(String.valueOf(amount))); + + return "redirect:/voucher/create"; + } + + @GetMapping("/find") + public String findVoucher() { + return "voucher/find"; + } + + //Request Param + //추가해야 할 부분 -> update 한 번 고민해보기, 유효성 검사, Rest 알아보자 + @PostMapping("/find") + public String findVoucher(@RequestParam("voucherId") String uuid, Model model) { + UUID voucherId = UUID.fromString(uuid); + Voucher voucher = voucherService.findVoucher(voucherId); + + model.addAttribute("voucher", voucher); + + return "/voucher/find-voucher"; + } + + @GetMapping("/list") + public String voucherList(Model model) { + List vouchers = voucherService.voucherLists(); + model.addAttribute("vouchers", vouchers); + return "voucher/list"; + } + + @GetMapping("/delete") + public String deleteVoucher() { + return "voucher/delete"; + } + + @PostMapping("/delete") + public String deleteVoucher(@RequestParam("voucherId") String uuid) { + UUID voucherId = UUID.fromString(uuid); + voucherService.deleteVoucher(voucherId); + return "redirect:/voucher/delete"; + } + + //유효성 검사(null check) + + private PolicyStatus validateAndConvertPolicy(String inputPolicy) { + try { + return PolicyStatus.valueOf(inputPolicy.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new InvalidInputException("잘못된 policy 입력입니다."); + } + } + + private long validateAndConvertAmountOrPercent(String inputAmountOrPercent) { + try { + return Long.parseLong(inputAmountOrPercent); + } catch (NumberFormatException e) { + throw new InvalidInputException("잘못된 amountOrPercent 입력입니다."); + } + } +} diff --git a/src/main/java/org/prgrms/vouchermanagement/webController/WalletWebController.java b/src/main/java/org/prgrms/vouchermanagement/webController/WalletWebController.java new file mode 100644 index 0000000000..b474305f32 --- /dev/null +++ b/src/main/java/org/prgrms/vouchermanagement/webController/WalletWebController.java @@ -0,0 +1,62 @@ +package org.prgrms.vouchermanagement.webController; + +import org.prgrms.vouchermanagement.dto.WalletCreateInfo; +import org.prgrms.vouchermanagement.wallet.domain.WalletMapper; +import org.prgrms.vouchermanagement.wallet.service.WalletMapperService; +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; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; +import java.util.UUID; + +@Controller +@RequestMapping("/wallet") +public class WalletWebController { + + private final WalletMapperService walletMapperService; + + public WalletWebController(WalletMapperService walletMapperService) { + this.walletMapperService = walletMapperService; + } + + @GetMapping("/wallet-home") + public String walletHome() { + return "/wallet/wallet-home"; + } + + @GetMapping("/create") + public String createWallet() { + return "wallet/create"; + } + + @PostMapping("/create") + public String createWallet(@RequestParam("customerId") String customerId, @RequestParam("voucherId") String voucherId) { + walletMapperService.create(new WalletCreateInfo(UUID.fromString(customerId), UUID.fromString(voucherId))); + + return "redirect:/wallet/create"; + } + + @GetMapping("/list") + public String voucherList(Model model) { + List wallets = walletMapperService.findAll(); + model.addAttribute("wallets", wallets); + return "wallet/list"; + } + + @GetMapping("/delete") + public String deleteWallet() { + return "wallet/delete"; + } + + @PostMapping("/delete") + public String createWallet(@RequestParam("customerId") String customerId) { + walletMapperService.delete(UUID.fromString(customerId)); + + return "redirect:/wallet/delete"; + } + +} 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/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000000..a687c66ea2 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,11 @@ +spring: + profiles: + active: database, web + +--- +spring: + datasource: + url: jdbc:mysql://localhost/voucher_management + username: root + password: root1234! + driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000000..8dce9fe8b2 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,27 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + ./application_log/application.log + + %d{yyyyMMdd HH:mm:ss.SSS} [%thread] %-5level [%logger{0}:%line] - %msg %n + + + application.log.%d{yyyy-MM-dd}.gz + 30 + 1GB + + + + + + + + + + + diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html new file mode 100644 index 0000000000..68b2d841ef --- /dev/null +++ b/src/main/resources/templates/home.html @@ -0,0 +1,29 @@ + + + + + SpringBoot Basic + + + + +
+

SpringBoot Basic

+

Voucher Management Options

+
+ +
+ + + + + + + diff --git a/src/main/resources/templates/voucher/create.html b/src/main/resources/templates/voucher/create.html new file mode 100644 index 0000000000..49b61d52cf --- /dev/null +++ b/src/main/resources/templates/voucher/create.html @@ -0,0 +1,31 @@ + + + + + Create Voucher + + + +

Create Voucher

+ +
+ + +
+ + + +
+ + + + +
+ + + + + diff --git a/src/main/resources/templates/voucher/delete.html b/src/main/resources/templates/voucher/delete.html new file mode 100644 index 0000000000..b4dea51907 --- /dev/null +++ b/src/main/resources/templates/voucher/delete.html @@ -0,0 +1,25 @@ + + + + + Delete Voucher + + + +

Delete Voucher

+ +
+ + +
+ + + + + +
+ + + + + diff --git a/src/main/resources/templates/voucher/find-voucher.html b/src/main/resources/templates/voucher/find-voucher.html new file mode 100644 index 0000000000..5ba46a4fe5 --- /dev/null +++ b/src/main/resources/templates/voucher/find-voucher.html @@ -0,0 +1,24 @@ + + + + Voucher Details + + + +

Voucher Details

+

Voucher ID:

+

Discount Amount: + + +

+

Policy Status:

+ + + + + + + + + + diff --git a/src/main/resources/templates/voucher/find.html b/src/main/resources/templates/voucher/find.html new file mode 100644 index 0000000000..dd18b70293 --- /dev/null +++ b/src/main/resources/templates/voucher/find.html @@ -0,0 +1,27 @@ + + + + + View Voucher + + + +

View Voucher

+ +
+ + +
+ + + + + + +
+ + + + + + diff --git a/src/main/resources/templates/voucher/list.html b/src/main/resources/templates/voucher/list.html new file mode 100644 index 0000000000..0ec7f9a368 --- /dev/null +++ b/src/main/resources/templates/voucher/list.html @@ -0,0 +1,39 @@ + + + + + Voucher List + + + +

Voucher List

+ + + + + + + + + + + + + + + + +
Voucher IDDiscount PolicyAmount
+ + +
+ + + + + + + + + + diff --git a/src/main/resources/templates/voucher/voucher-home.html b/src/main/resources/templates/voucher/voucher-home.html new file mode 100644 index 0000000000..f012ff5808 --- /dev/null +++ b/src/main/resources/templates/voucher/voucher-home.html @@ -0,0 +1,39 @@ + + + + + SpringBoot Basic + + + + +
+

SpringBoot Basic

+

Voucher Options

+
+ +
+ + + +
+ + + + + + + diff --git a/src/main/resources/templates/wallet/create.html b/src/main/resources/templates/wallet/create.html new file mode 100644 index 0000000000..5887521d5e --- /dev/null +++ b/src/main/resources/templates/wallet/create.html @@ -0,0 +1,29 @@ + + + + + Create Wallet + + + +

Create Wallet

+ +
+ + +
+ + + +
+ + + + + +
+ + + + + diff --git a/src/main/resources/templates/wallet/delete.html b/src/main/resources/templates/wallet/delete.html new file mode 100644 index 0000000000..eb9a9bd470 --- /dev/null +++ b/src/main/resources/templates/wallet/delete.html @@ -0,0 +1,26 @@ + + + + + Delete Wallet + + + +

Delete Wallet

+ +
+ + +
+ + + + + +
+ + + + + + diff --git a/src/main/resources/templates/wallet/list.html b/src/main/resources/templates/wallet/list.html new file mode 100644 index 0000000000..18a4e7209c --- /dev/null +++ b/src/main/resources/templates/wallet/list.html @@ -0,0 +1,34 @@ + + + + + Wallet List + + + +

Wallet List

+ + + + + + + + + + + + + + +
Customer IdVoucher Id
+ + + + + + + + + + diff --git a/src/main/resources/templates/wallet/wallet-home.html b/src/main/resources/templates/wallet/wallet-home.html new file mode 100644 index 0000000000..45f4b5b24b --- /dev/null +++ b/src/main/resources/templates/wallet/wallet-home.html @@ -0,0 +1,36 @@ + + + + + Wallet Home + + + + +
+

SpringBoot Basic

+

Wallet Options

+
+ +
+ + + +
+ + + + + + + diff --git a/src/test/java/org/prgrms/vouchermanagement/VoucherManagementApplicationTests.java b/src/test/java/org/prgrms/vouchermanagement/VoucherManagementApplicationTests.java new file mode 100644 index 0000000000..6a5ee73f6e --- /dev/null +++ b/src/test/java/org/prgrms/vouchermanagement/VoucherManagementApplicationTests.java @@ -0,0 +1,13 @@ +package org.prgrms.vouchermanagement; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class VoucherManagementApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/src/test/java/org/prgrms/vouchermanagement/wallet/service/WalletMapperServiceTest.java b/src/test/java/org/prgrms/vouchermanagement/wallet/service/WalletMapperServiceTest.java new file mode 100644 index 0000000000..71a38407c0 --- /dev/null +++ b/src/test/java/org/prgrms/vouchermanagement/wallet/service/WalletMapperServiceTest.java @@ -0,0 +1,57 @@ +package org.prgrms.vouchermanagement.wallet.service; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.prgrms.vouchermanagement.customer.domain.Customer; +import org.prgrms.vouchermanagement.dto.WalletCreateInfo; +import org.prgrms.vouchermanagement.voucher.domain.Voucher; +import org.prgrms.vouchermanagement.voucher.policy.FixedAmountVoucher; +import org.prgrms.vouchermanagement.wallet.repository.WalletMapperRepository; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.*; + +@SpringBootTest +public class WalletMapperServiceTest { + + WalletMapperService walletMapperService; + WalletMapperRepository walletMapperRepository; + + @BeforeEach + void setUp() { + walletMapperService = new WalletMapperService(walletMapperRepository); + } + + @Test + @DisplayName("wallet 생성 테스트") + void create() { + Customer customer = new Customer(UUID.randomUUID(), "김남규", 23); + Voucher voucher = new Voucher(UUID.randomUUID(), new FixedAmountVoucher(3000)); + + UUID userId = customer.getUserId(); + UUID voucherId = voucher.getVoucherId(); + + WalletCreateInfo walletCreateInfo = walletMapperService.create(new WalletCreateInfo(userId, voucherId)); + + Optional customer1 = walletMapperRepository.findCustomer(voucherId); + + assertThat(customer1.get()).isNotNull(); + } + + @Test + void findVouchers() { + } + + @Test + void delete() { + } + + @Test + void findCustomer() { + } +} diff --git a/voucherFile/voucherFile b/voucherFile/voucherFile new file mode 100644 index 0000000000..75d7e04bb5 --- /dev/null +++ b/voucherFile/voucherFile @@ -0,0 +1,2 @@ +2905aeba-eb09-4d9e-bbec-7104c7dfca8a,FIXED,10000 +64eaa00c-8e11-45d2-917d-433387830976,PERCENT,50