diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..c2065bc262 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +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/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..b9f8a1baff --- /dev/null +++ b/build.gradle @@ -0,0 +1,36 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' +} + +group = 'com.prgms' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.projectlombok:lombok:1.18.22' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.mockito:mockito-core:4.8.0' + + annotationProcessor 'org.projectlombok:lombok' + + implementation 'com.mysql:mysql-connector-j:8.1.0' + + +} + +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..6689b85bee --- /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..fcbc3bb79c --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'vouchermanager' diff --git a/src/main/java/com/prgms/vouchermanager/VouchermanagerApplication.java b/src/main/java/com/prgms/vouchermanager/VouchermanagerApplication.java new file mode 100644 index 0000000000..e653e1e01a --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/VouchermanagerApplication.java @@ -0,0 +1,40 @@ +package com.prgms.vouchermanager; + +import com.prgms.vouchermanager.contorller.front.FrontController; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; + +@SpringBootApplication +public class VouchermanagerApplication { + + private static ApplicationContext ac; + + + public VouchermanagerApplication(ConfigurableApplicationContext applicationContext) { + this.ac = applicationContext; + } + + public static void main(String[] args) { + SpringApplication.run(VouchermanagerApplication.class, args); + } + + @Profile(value = "tomcat") + @Bean + public ServletWebServerFactory servletTomcatServerContainer() { + return new TomcatServletWebServerFactory(); + } + + @Profile("console") + @Bean + public void init() { + FrontController frontController = ac.getBean(FrontController.class); + frontController.run(); + } + +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/customer/CustomerController.java b/src/main/java/com/prgms/vouchermanager/contorller/customer/CustomerController.java new file mode 100644 index 0000000000..20e3342e60 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/customer/CustomerController.java @@ -0,0 +1,111 @@ +package com.prgms.vouchermanager.contorller.customer; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.dto.CreateCustomerDto; +import com.prgms.vouchermanager.dto.UpdateCustomerDto; +import com.prgms.vouchermanager.service.customer.CustomerService; +import com.prgms.vouchermanager.util.io.ConsoleInput; +import com.prgms.vouchermanager.util.io.ConsoleOutput; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; + +import java.util.List; + +@Controller +@Slf4j +public class CustomerController { + + private final CustomerService customerService; + private final ConsoleInput consoleInput; + + private final ConsoleOutput consoleOutput; + public CustomerController(CustomerService customerService, ConsoleInput consoleInput, ConsoleOutput consoleOutput) { + this.customerService = customerService; + this.consoleInput = consoleInput; + this.consoleOutput = consoleOutput; + } + + public void create() { + Customer customer = null; + try { + + consoleOutput.printCustomerName(); + String name = consoleInput.inputCustomerName(); + consoleOutput.printCustomerEmail(); + String email = consoleInput.inputCustomerEmail(); + consoleOutput.printBlackList(); + int blackList = consoleInput.inputBlackList(); + customer = customerService.create(new CreateCustomerDto(name,email, blackList)); + log.info(customer.toString()); + + } catch (RuntimeException e) { + System.out.println(e.getMessage()); + log.warn(e.getMessage()); + } + + } + + public void update() { + try { + consoleOutput.printCustomerId(); + Long id = consoleInput.inputCustomerId(); + consoleOutput.printCustomerName(); + String name = consoleInput.inputCustomerName(); + consoleOutput.printCustomerEmail(); + String email = consoleInput.inputCustomerEmail(); + consoleOutput.printBlackList(); + int blackList = consoleInput.inputBlackList(); + customerService.update(id,new UpdateCustomerDto(name,email,blackList)); + consoleOutput.printSuccessUpdate(); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + } + + public void getList() { + + List customers = customerService.findAll(); + + customers.forEach(consoleOutput::printCustomer); + + } + + public void findById() { + consoleOutput.printCustomerId(); + + try { + Long id = consoleInput.inputCustomerId(); + Customer customer = customerService.findById(id); + log.info(customer.toString()); + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } + + public void deleteById() { + consoleOutput.printCustomerId(); + try { + long id = consoleInput.inputCustomerId(); + customerService.deleteById(id); + consoleOutput.printSuccessDelete(); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } + + public void deleteAll() { + + customerService.deleteAll(); + consoleOutput.printSuccessDelete(); + } + public void findBlackList() { + List blackList = customerService.findBlackList(); + + blackList.forEach(customer -> System.out.println(customer.toString())); + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/customer/CustomerMenuType.java b/src/main/java/com/prgms/vouchermanager/contorller/customer/CustomerMenuType.java new file mode 100644 index 0000000000..ef23a5de4f --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/customer/CustomerMenuType.java @@ -0,0 +1,27 @@ +package com.prgms.vouchermanager.contorller.customer; + +import java.util.Arrays; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_CUSTOMER_MENU; + +public enum CustomerMenuType { + CREATE(1), UPDATE(2), FIND_ALL(3), FIND_ONE(4), DELETE_ONE(5), DELETE_ALL(6), BLACK_LIST(7); + + private final int number; + + CustomerMenuType(int number) { + this.number = number; + } + + public static CustomerMenuType fromValue(int menu) { + + return Arrays.stream(CustomerMenuType.values()) + .filter(customerMenuType -> customerMenuType.getNumber() == menu) + .findFirst() + .orElseThrow(() -> new RuntimeException(INVALID_CUSTOMER_MENU.getMessage())); + } + + public int getNumber() { + return number; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/front/FrontController.java b/src/main/java/com/prgms/vouchermanager/contorller/front/FrontController.java new file mode 100644 index 0000000000..792e3b9eb0 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/front/FrontController.java @@ -0,0 +1,141 @@ +package com.prgms.vouchermanager.contorller.front; + + +import com.prgms.vouchermanager.contorller.customer.CustomerController; +import com.prgms.vouchermanager.contorller.customer.CustomerMenuType; +import com.prgms.vouchermanager.contorller.voucher.VoucherController; +import com.prgms.vouchermanager.contorller.voucher.VoucherMenuType; +import com.prgms.vouchermanager.contorller.wallet.WalletController; +import com.prgms.vouchermanager.contorller.wallet.WalletMenuType; +import com.prgms.vouchermanager.util.io.ConsoleInput; +import com.prgms.vouchermanager.util.io.ConsoleOutput; +import com.prgms.vouchermanager.validation.InputValidation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_FRONT_MENU; +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_WALLET_MENU; + +@Slf4j +@Controller +public class FrontController { + + private final ConsoleInput consoleInput; + private final ConsoleOutput consoleOutput; + private final VoucherController voucherController; + private final CustomerController customerController; + private final WalletController walletController; + + private final InputValidation inputValidation; + + public FrontController(ConsoleInput consoleInput, ConsoleOutput consoleOutput, VoucherController voucherController, CustomerController customerController, WalletController walletController, InputValidation inputValidation) { + + this.consoleInput = consoleInput; + this.consoleOutput = consoleOutput; + this.voucherController = voucherController; + this.customerController = customerController; + this.walletController = walletController; + this.inputValidation = inputValidation; + } + + public void run() { + + boolean end = false; + int menu = 0; + + while (!end) { + + try { + consoleOutput.printFrontMenu(); + menu = consoleInput.inputFrontMenu(); + if (!inputValidation.validFrontMenu(menu)) { + throw new RuntimeException(INVALID_FRONT_MENU.getMessage()); + } + switch (FrontMenuType.fromValue(menu)) { + case VOUCHER -> runVoucherController(); + case CUSTOMER -> runCustomerContoller(); + case WALLET -> runWalletController(); + case END -> end = true; + } + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } + } + + private void runVoucherController() { + + consoleOutput.printVoucherMenu(); + int menu; + try { + menu = consoleInput.inputVoucherMenu(); + + switch (VoucherMenuType.fromValue(menu)) { + case CREATE -> voucherController.create(); + case UPDATE -> voucherController.update(); + case LIST -> voucherController.getList(); + case ONE -> voucherController.findById(); + case DELETE_ONE -> voucherController.deleteById(); + case DELETE_ALL -> voucherController.deleteAll(); + + } + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + + } + + private void runCustomerContoller() { + + consoleOutput.printCustomerMenu(); + int menu = 0; + try { + menu = consoleInput.inputCustomerMenu(); + + switch (CustomerMenuType.fromValue(menu)) { + case CREATE -> customerController.create(); + case UPDATE -> customerController.update(); + case FIND_ALL -> customerController.getList(); + case FIND_ONE -> customerController.findById(); + case DELETE_ONE -> customerController.deleteById(); + case DELETE_ALL -> customerController.deleteAll(); + case BLACK_LIST -> customerController.findBlackList(); + + } + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + + } + + private void runWalletController() { + + consoleOutput.printWalletMenu(); + int menu = 0; + try { + menu = consoleInput.inputVoucherMenu(); + + if (!inputValidation.validWalletMenu(menu)) { + throw new RuntimeException(INVALID_WALLET_MENU.getMessage()); + } + + switch (WalletMenuType.fromValue(menu)) { + + case CREATE -> walletController.create(); + case FIND_BY_CUSTOMER_ID -> walletController.findByCustomerId(); + case FIND_BY_VOUCHER_ID -> walletController.findByVoucherId(); + case DELETE_BY_CUSTOMER_ID -> walletController.deleteByCustomerId(); + + } + + } catch (RuntimeException e) { + + log.warn(e.getMessage()); + } + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/front/FrontMenuType.java b/src/main/java/com/prgms/vouchermanager/contorller/front/FrontMenuType.java new file mode 100644 index 0000000000..ca6ba77508 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/front/FrontMenuType.java @@ -0,0 +1,24 @@ +package com.prgms.vouchermanager.contorller.front; + +import java.util.Arrays; + +public enum FrontMenuType { + VOUCHER(1),CUSTOMER(2),WALLET(3),END(4); + + private final int number; + FrontMenuType(int number) { + this.number = number; + } + + public int getNumber() { + return number; + } + + public static FrontMenuType fromValue(int menu) { + + return Arrays.stream(FrontMenuType.values()) + .filter(frontMenuType -> frontMenuType.getNumber() == menu) + .findFirst() + .get(); + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/voucher/ApiVoucherController.java b/src/main/java/com/prgms/vouchermanager/contorller/voucher/ApiVoucherController.java new file mode 100644 index 0000000000..0673b64e11 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/voucher/ApiVoucherController.java @@ -0,0 +1,96 @@ +package com.prgms.vouchermanager.contorller.voucher; + +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.voucher.VoucherType; +import com.prgms.vouchermanager.dto.CreateVoucherDto; +import com.prgms.vouchermanager.dto.UpdateVoucherDto; +import com.prgms.vouchermanager.service.voucher.VoucherService; +import lombok.RequiredArgsConstructor; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.InputMismatchException; +import java.util.List; +import java.util.UUID; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_VOUCHER_INFO; +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_VOUCHER_PERCENT; + +@RestController +@RequestMapping("/api/vouchers") +@RequiredArgsConstructor +public class ApiVoucherController { + + private final VoucherService voucherService; + + @GetMapping("/{id}") + ResponseEntity findById(@PathVariable String id) { + return ResponseEntity.ok(voucherService.findById(UUID.fromString(id))); + } + + @GetMapping("/date") + ResponseEntity> findByDate(@RequestParam String startTime, @RequestParam String endTime) { + LocalDateTime startDate = LocalDateTime.parse(startTime); + LocalDateTime endDate = LocalDateTime.parse(endTime); + return ResponseEntity.ok(voucherService.findByDate(startDate, endDate)); + } + + @GetMapping("/type") + ResponseEntity> findByType(@RequestParam String type) { + VoucherType voucherType = VoucherType.valueOf(type); + return ResponseEntity.ok(voucherService.findByType(voucherType)); + } + + @GetMapping("") + ResponseEntity> findAll() { + return ResponseEntity.ok(voucherService.findAll()); + } + + @PostMapping("/create") + ResponseEntity create(@RequestBody CreateVoucherDto dto) { + if (dto.getVoucherType() == 2 && dto.getValue() > 100) { + throw new InputMismatchException(INVALID_VOUCHER_PERCENT.getMessage()); + } + return ResponseEntity + .status(HttpStatus.CREATED) + .body(voucherService.create(dto)); + } + + + @PutMapping("/{id}/edit") + ResponseEntity update(@PathVariable String id, @RequestBody UpdateVoucherDto dto) { + voucherService.update(UUID.fromString(id), dto); + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/{id}") + ResponseEntity delete(@PathVariable String id) { + voucherService.deleteById(UUID.fromString(id)); + return ResponseEntity.ok().build(); + } + + @ExceptionHandler + String ArgumentTypeMistMatch(HttpMessageNotReadableException e) { + return INVALID_VOUCHER_INFO.getMessage(); + } + + @ExceptionHandler + String DuplicatedId(DuplicateKeyException e) { + return e.getMessage(); + } + + @ExceptionHandler + String ExceedVoucherPercent(InputMismatchException e) { + return e.getMessage(); + } + + @ExceptionHandler + String EmptyResult(EmptyResultDataAccessException e) { + return e.getMessage(); + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/voucher/VoucherController.java b/src/main/java/com/prgms/vouchermanager/contorller/voucher/VoucherController.java new file mode 100644 index 0000000000..201b653fb5 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/voucher/VoucherController.java @@ -0,0 +1,112 @@ +package com.prgms.vouchermanager.contorller.voucher; + +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.dto.CreateVoucherDto; +import com.prgms.vouchermanager.dto.UpdateVoucherDto; +import com.prgms.vouchermanager.service.voucher.VoucherService; +import com.prgms.vouchermanager.util.io.ConsoleInput; +import com.prgms.vouchermanager.util.io.ConsoleOutput; +import com.prgms.vouchermanager.validation.InputValidation; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.stereotype.Controller; + +import java.util.List; +import java.util.UUID; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_VOUCHER_PERCENT; + +@Slf4j +@Controller +public class VoucherController { + + private final VoucherService voucherService; + + private final ConsoleInput consoleInput; + + private final ConsoleOutput consoleOutput; + + private final InputValidation inputValidation; + + public VoucherController(VoucherService voucherService, ConsoleInput consoleInput, ConsoleOutput consoleOutput, InputValidation inputValidation) { + this.voucherService = voucherService; + this.consoleInput = consoleInput; + this.consoleOutput = consoleOutput; + this.inputValidation = inputValidation; + } + + public void create() { + try { + consoleOutput.printVoucherType(); + int voucherType = consoleInput.inputVoucherType(); + consoleOutput.printVoucherAmount(); + long value = consoleInput.inputVoucherValue(); + if (voucherType == 2 && !inputValidation.validVoucherPercent(value)) { + throw new RuntimeException(INVALID_VOUCHER_PERCENT.getMessage()); + } + Voucher voucher = voucherService.create(new CreateVoucherDto(value, voucherType)); + log.info(voucher.toString()); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } + + public void update() { + try { + consoleOutput.printVoucherId(); + UUID id = consoleInput.inputVoucherId(); + consoleOutput.printVoucherType(); + int voucherType = consoleInput.inputVoucherType(); + consoleOutput.printVoucherAmount(); + long value = consoleInput.inputVoucherValue(); + if (voucherType == 2 && !inputValidation.validVoucherPercent(value)) { + throw new RuntimeException(INVALID_VOUCHER_PERCENT.getMessage()); + } + voucherService.update(id, new UpdateVoucherDto(value, voucherType)); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + } + + public void getList() { + + List voucherList = voucherService.findAll(); + + voucherList.forEach(voucher -> System.out.println(voucher.toString())); + + } + + public void findById() { + + consoleOutput.printVoucherId(); + + try { + UUID id = consoleInput.inputVoucherId(); + Voucher voucher = voucherService.findById(id); + log.info(voucher.toString()); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } + + public void deleteById() { + consoleOutput.printVoucherId(); + try { + UUID id = consoleInput.inputVoucherId(); + voucherService.deleteById(id); + consoleOutput.printSuccessDelete(); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + } + + public void deleteAll() { + voucherService.deleteAll(); + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/voucher/VoucherMenuType.java b/src/main/java/com/prgms/vouchermanager/contorller/voucher/VoucherMenuType.java new file mode 100644 index 0000000000..cce108b1f2 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/voucher/VoucherMenuType.java @@ -0,0 +1,27 @@ +package com.prgms.vouchermanager.contorller.voucher; + +import java.util.Arrays; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_VOUCHER_MENU; + +public enum VoucherMenuType { + CREATE(1), UPDATE(2), LIST(3), ONE(4), DELETE_ONE(5), DELETE_ALL(6); + private final int number; + + VoucherMenuType(int number) { + this.number = number; + } + + public static VoucherMenuType fromValue(int menu) { + + return Arrays.stream(VoucherMenuType.values()) + .filter(voucherMenuType -> voucherMenuType.getNumber() == menu) + .findFirst() + .orElseThrow(() -> new RuntimeException(INVALID_VOUCHER_MENU.getMessage())); + } + + public int getNumber() { + return number; + } +} + diff --git a/src/main/java/com/prgms/vouchermanager/contorller/voucher/WebVoucherController.java b/src/main/java/com/prgms/vouchermanager/contorller/voucher/WebVoucherController.java new file mode 100644 index 0000000000..69bbae1b77 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/voucher/WebVoucherController.java @@ -0,0 +1,104 @@ +package com.prgms.vouchermanager.contorller.voucher; + +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.dto.CreateVoucherDto; +import com.prgms.vouchermanager.dto.UpdateVoucherDto; +import com.prgms.vouchermanager.service.voucher.VoucherService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.util.InputMismatchException; +import java.util.List; +import java.util.UUID; + + +@Controller +@Slf4j +@RequestMapping("/admin/vouchers") +@RequiredArgsConstructor +public class WebVoucherController { + + private final VoucherService voucherService; + + @GetMapping("/{id}") + String findById(@PathVariable String id, Model model) { + Voucher voucher = voucherService.findById(UUID.fromString(id)); + model.addAttribute("voucher", voucher); + + return "voucher_one.html"; + } + + @GetMapping("") + String findAll(Model model) { + List vouchers = voucherService.findAll(); + model.addAttribute("vouchers", vouchers); + + return "voucher_list.html"; + } + + @GetMapping("/create") + String getCreateForm() { + return "voucher_create.html"; + } + + @PostMapping("/create") + String create(@ModelAttribute CreateVoucherDto dto, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { + if (bindingResult.hasErrors()) { + model.addAttribute("code", "바우처 입력 정보가 잘못되었습니다."); + return "voucher_exception.html"; + } + if (dto.getVoucherType() == 2 && dto.getValue() > 100) { + model.addAttribute("code", "percent는 100%를 넘어갈 수 없습니다."); + return "voucher_exception.html"; + } + Voucher voucher = voucherService.create(dto); + redirectAttributes.addAttribute("id", voucher.getId()); + return "redirect:/admin/vouchers/{id}"; + } + + @GetMapping("/{id}/edit") + String getUpdateForm(@PathVariable String id, Model model) { + Voucher voucher = voucherService.findById(UUID.fromString(id)); + model.addAttribute("voucher", voucher); + return "voucher_edit.html"; + } + + @PutMapping("/{id}/edit") + String update(@PathVariable String id, @ModelAttribute UpdateVoucherDto dto, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { + if (bindingResult.hasErrors()) { + model.addAttribute("code", "바우처 입력 정보가 잘못되었습니다."); + return "voucher_exception.html"; + } + if (dto.getVoucherType() == 2 && dto.getValue() > 100) { + model.addAttribute("code", "percent는 100%를 넘어갈 수 없습니다."); + return "voucher_exception.html"; + } + voucherService.update(UUID.fromString(id), dto); + redirectAttributes.addAttribute("id", id); + return "redirect:/admin/vouchers/{id}"; + + } + + @DeleteMapping("/{id}") + String delete(@PathVariable String id) { + voucherService.deleteById(UUID.fromString(id)); + return "redirect:/admin/vouchers"; + } + + @ExceptionHandler + String ExceedVoucherPercent(InputMismatchException e, Model model) { + model.addAttribute("code", e.getMessage()); + return "voucher_exception.html"; + } + + @ExceptionHandler + String CommonException(Exception e, Model model) { + model.addAttribute("code", "잘못된 접근입니다."); + return "voucher_exception.html"; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/wallet/WalletController.java b/src/main/java/com/prgms/vouchermanager/contorller/wallet/WalletController.java new file mode 100644 index 0000000000..0b971992fc --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/wallet/WalletController.java @@ -0,0 +1,88 @@ +package com.prgms.vouchermanager.contorller.wallet; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.wallet.Wallet; +import com.prgms.vouchermanager.dto.CreateWalletDto; +import com.prgms.vouchermanager.service.wallet.WalletService; +import com.prgms.vouchermanager.util.io.ConsoleInput; +import com.prgms.vouchermanager.util.io.ConsoleOutput; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@Controller +public class WalletController { + + private final WalletService walletService; + private final ConsoleOutput consoleOutput; + private final ConsoleInput consoleInput; + + public WalletController(WalletService walletService, ConsoleOutput consoleOutput, ConsoleInput consoleInput) { + this.walletService = walletService; + this.consoleOutput = consoleOutput; + this.consoleInput = consoleInput; + } + + public void create() { + + try { + consoleOutput.printCustomerId(); + Long customerId = consoleInput.inputCustomerId(); + consoleOutput.printVoucherId(); + UUID voucherId = consoleInput.inputVoucherId(); + Wallet wallet = walletService.save(new CreateWalletDto(customerId, voucherId)); + consoleOutput.printWallet(wallet); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } + + public void deleteByCustomerId() { + + try { + consoleOutput.printCustomerId(); + Long customerId = consoleInput.inputCustomerId(); + walletService.deleteByCustomerId(customerId); + consoleOutput.printSuccessDelete(); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + } + + public void findByCustomerId() { + + try { + consoleOutput.printCustomerId(); + Long customerId = consoleInput.inputCustomerId(); + List wallets = walletService.findByCustomerId(customerId); + wallets.forEach(wallet -> consoleOutput.printWallet(wallet)); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } + + public void findByVoucherId() { + + try { + + consoleOutput.printVoucherId(); + UUID voucherId = consoleInput.inputVoucherId(); + + Wallet wallet = walletService.findByVoucherId(voucherId); + consoleOutput.printWallet(wallet); + + } catch (RuntimeException e) { + log.warn(e.getMessage()); + } + + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/wallet/WalletMenuType.java b/src/main/java/com/prgms/vouchermanager/contorller/wallet/WalletMenuType.java new file mode 100644 index 0000000000..5d8ebc2cdb --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/wallet/WalletMenuType.java @@ -0,0 +1,28 @@ +package com.prgms.vouchermanager.contorller.wallet; + +import java.util.Arrays; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_WALLET_MENU; + +public enum WalletMenuType { + CREATE(1), FIND_BY_CUSTOMER_ID(2), FIND_BY_VOUCHER_ID(3), DELETE_BY_CUSTOMER_ID(4); + + private final int number; + + WalletMenuType(int number) { + this.number = number; + } + + public static WalletMenuType fromValue(int menu) { + + return Arrays.stream(WalletMenuType.values()) + .filter(walletMenuType -> walletMenuType.getNumber() == menu) + .findFirst() + .orElseThrow(() -> new RuntimeException(INVALID_WALLET_MENU.getMessage())); + + } + + public int getNumber() { + return number; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/contorller/wallet/WebWalletController.java b/src/main/java/com/prgms/vouchermanager/contorller/wallet/WebWalletController.java new file mode 100644 index 0000000000..09931c3706 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/contorller/wallet/WebWalletController.java @@ -0,0 +1,78 @@ +package com.prgms.vouchermanager.contorller.wallet; + +import com.prgms.vouchermanager.domain.wallet.Wallet; +import com.prgms.vouchermanager.dto.CreateWalletDto; +import com.prgms.vouchermanager.service.wallet.WalletService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.util.List; +import java.util.UUID; + + +@Controller +@Slf4j +@RequestMapping("/admin/wallets") +@RequiredArgsConstructor +public class WebWalletController { + + private final WalletService walletService; + + @GetMapping("/customer/{customerId}") + String findByCustomerId(@PathVariable Long customerId, Model model) { + List wallets = walletService.findByCustomerId(customerId); + model.addAttribute("wallets", wallets); + return "wallet_list.html"; + } + + @GetMapping("/voucher/{voucherId}") + String findByVoucherId(@PathVariable UUID voucherId, Model model) { + Wallet wallet = walletService.findByVoucherId(voucherId); + model.addAttribute("wallets", wallet); + return "wallet_list.html"; + } + + @GetMapping("") + String findAll(Model model) { + List wallets = walletService.findAll(); + model.addAttribute("wallets", wallets); + + return "wallet_list.html"; + } + + @GetMapping("/create") + String getCreateForm() { + return "wallet_create.html"; + } + + @PostMapping("/create") + String create(@ModelAttribute CreateWalletDto dto, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { + if (bindingResult.hasErrors()) { + model.addAttribute("code", "입력값 타입 형태가 잘못되었습니다."); + return "wallet_exception.html"; + } + Wallet wallet = walletService.save(dto); + redirectAttributes.addAttribute("id", wallet.getId()); + return "redirect:/admin/wallets"; + } + + @DeleteMapping("/{id}") + String deleteByCustomerId(@PathVariable Long id) { + walletService.deleteByCustomerId(id); + return "redirect:/admin/wallets"; + } + + @ExceptionHandler + String NotExistInfo(DataIntegrityViolationException e1, EmptyResultDataAccessException e2, Model model) { + model.addAttribute("code", "회원번호 또는 바우처번호가 존재하지 않습니다."); + return "wallet_exception.html"; + } + +} diff --git a/src/main/java/com/prgms/vouchermanager/domain/customer/Customer.java b/src/main/java/com/prgms/vouchermanager/domain/customer/Customer.java new file mode 100644 index 0000000000..c93243c73d --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/domain/customer/Customer.java @@ -0,0 +1,38 @@ +package com.prgms.vouchermanager.domain.customer; + + +import lombok.Getter; +@Getter +public class Customer { + + private Long id; + + private final String name; + + private final String email; + + private final boolean blackList; + + public Customer(Long id, String name, String email, boolean blackList) { + + this.id = id; + this.name = name; + this.email = email; + this.blackList = blackList; + + } + + public void setId(long longValue) { + this.id = longValue; + } + + @Override + public String toString() { + return "Customer{" + + "id=" + id + + ", name='" + name + '\'' + + ", email='" + email + '\'' + + ", blackList=" + blackList + + '}'; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/domain/voucher/FixedAmountVoucher.java b/src/main/java/com/prgms/vouchermanager/domain/voucher/FixedAmountVoucher.java new file mode 100644 index 0000000000..3b76eba4b8 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/domain/voucher/FixedAmountVoucher.java @@ -0,0 +1,53 @@ +package com.prgms.vouchermanager.domain.voucher; + +import java.time.LocalDateTime; +import java.util.UUID; + +public class FixedAmountVoucher implements Voucher { + + private final UUID id; + + private final long amount; + + private final VoucherType type; + + private LocalDateTime createdAt; + + public FixedAmountVoucher(UUID id, long amount, LocalDateTime createdAt) { + this.id = id; + this.amount = amount; + this.createdAt = createdAt; + type = VoucherType.FIXED_AMOUNT; + } + + + @Override + public UUID getId() { + return id; + } + + @Override + public long getDiscountValue() { + return amount; + } + + @Override + public VoucherType getVoucherType() { + return VoucherType.FIXED_AMOUNT; + } + + @Override + public LocalDateTime getCreatedAt() { + return createdAt; + } + + @Override + public String toString() { + return "FixedAmountVoucher{" + + "id=" + id + + ", amount=" + amount + + ", type=" + type + + ", createdAt=" + createdAt + + '}'; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/domain/voucher/PercentDiscountVoucher.java b/src/main/java/com/prgms/vouchermanager/domain/voucher/PercentDiscountVoucher.java new file mode 100644 index 0000000000..2f088c9fac --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/domain/voucher/PercentDiscountVoucher.java @@ -0,0 +1,52 @@ +package com.prgms.vouchermanager.domain.voucher; + +import java.time.LocalDateTime; +import java.util.UUID; + +public class PercentDiscountVoucher implements Voucher { + + private final UUID id; + + private final long percent; + + private final VoucherType type; + + private LocalDateTime createdAt; + + public PercentDiscountVoucher(UUID id, long percent, LocalDateTime createdAt) { + this.id = id; + this.percent = percent; + this.createdAt = createdAt; + type = VoucherType.PERCENT_DISCOUNT; + } + + @Override + public UUID getId() { + return id; + } + + @Override + public long getDiscountValue() { + return percent; + } + + @Override + public VoucherType getVoucherType() { + return VoucherType.PERCENT_DISCOUNT; + } + + @Override + public LocalDateTime getCreatedAt() { + return createdAt; + } + + @Override + public String toString() { + return "PercentDiscountVoucher{" + + "id=" + id + + ", percent=" + percent + + ", type=" + type + + ", createdAt=" + createdAt + + '}'; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/domain/voucher/Voucher.java b/src/main/java/com/prgms/vouchermanager/domain/voucher/Voucher.java new file mode 100644 index 0000000000..391125f589 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/domain/voucher/Voucher.java @@ -0,0 +1,15 @@ +package com.prgms.vouchermanager.domain.voucher; + +import java.time.LocalDateTime; +import java.util.UUID; + +public interface Voucher { + UUID getId(); + + long getDiscountValue(); + + VoucherType getVoucherType(); + + LocalDateTime getCreatedAt(); + +} diff --git a/src/main/java/com/prgms/vouchermanager/domain/voucher/VoucherType.java b/src/main/java/com/prgms/vouchermanager/domain/voucher/VoucherType.java new file mode 100644 index 0000000000..84b0738a47 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/domain/voucher/VoucherType.java @@ -0,0 +1,17 @@ +package com.prgms.vouchermanager.domain.voucher; + +public enum VoucherType { + FIXED_AMOUNT(1), PERCENT_DISCOUNT(2); + + private final int number; + + VoucherType(int number) { + this.number = number; + } + + public int getNumber() { + return number; + } + + +} diff --git a/src/main/java/com/prgms/vouchermanager/domain/wallet/Wallet.java b/src/main/java/com/prgms/vouchermanager/domain/wallet/Wallet.java new file mode 100644 index 0000000000..93e666fa71 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/domain/wallet/Wallet.java @@ -0,0 +1,32 @@ +package com.prgms.vouchermanager.domain.wallet; + +import lombok.Getter; + +import java.util.UUID; + +@Getter +public class Wallet { + + private Long id; + private final Long customerId; + private final UUID voucherId; + + public Wallet(Long id, Long customerId, UUID voucherId) { + this.id = id; + this.customerId = customerId; + this.voucherId = voucherId; + } + + public void setId(Long id) { + this.id = id; + } + + @Override + public String toString() { + return "Wallet{" + + "id=" + id + + ", customerId=" + customerId + + ", voucherId=" + voucherId + + '}'; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/dto/CreateCustomerDto.java b/src/main/java/com/prgms/vouchermanager/dto/CreateCustomerDto.java new file mode 100644 index 0000000000..f06e3c6793 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/dto/CreateCustomerDto.java @@ -0,0 +1,17 @@ +package com.prgms.vouchermanager.dto; + +import lombok.Getter; + +@Getter +public class CreateCustomerDto { + private final String name; + private final String email; + private final int blackList; + + public CreateCustomerDto(String name, String email, int blackList) { + this.name = name; + this.email = email; + + this.blackList = blackList; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/dto/CreateVoucherDto.java b/src/main/java/com/prgms/vouchermanager/dto/CreateVoucherDto.java new file mode 100644 index 0000000000..9d77dc4153 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/dto/CreateVoucherDto.java @@ -0,0 +1,20 @@ +package com.prgms.vouchermanager.dto; + +public class CreateVoucherDto { + + private final long value; + private final int voucherType; + + public CreateVoucherDto(long value, int voucherType) { + this.value = value; + this.voucherType = voucherType; + } + + public long getValue() { + return value; + } + + public int getVoucherType() { + return voucherType; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/dto/CreateWalletDto.java b/src/main/java/com/prgms/vouchermanager/dto/CreateWalletDto.java new file mode 100644 index 0000000000..af0219f024 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/dto/CreateWalletDto.java @@ -0,0 +1,17 @@ +package com.prgms.vouchermanager.dto; + +import lombok.Getter; + +import java.util.UUID; + +@Getter +public class CreateWalletDto { + private final Long customerId; + private final UUID voucherId; + + public CreateWalletDto(Long customerId, UUID voucherId) { + this.customerId = customerId; + this.voucherId = voucherId; + } + +} diff --git a/src/main/java/com/prgms/vouchermanager/dto/UpdateCustomerDto.java b/src/main/java/com/prgms/vouchermanager/dto/UpdateCustomerDto.java new file mode 100644 index 0000000000..02a3d66464 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/dto/UpdateCustomerDto.java @@ -0,0 +1,17 @@ +package com.prgms.vouchermanager.dto; + +import lombok.Getter; + +@Getter +public class UpdateCustomerDto { + private final String name; + private final String email; + + private final int blackList; + + public UpdateCustomerDto(String name, String email, int blackList) { + this.name = name; + this.email = email; + this.blackList = blackList; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/dto/UpdateVoucherDto.java b/src/main/java/com/prgms/vouchermanager/dto/UpdateVoucherDto.java new file mode 100644 index 0000000000..0929ecf891 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/dto/UpdateVoucherDto.java @@ -0,0 +1,22 @@ +package com.prgms.vouchermanager.dto; + +import lombok.Getter; + +@Getter +public class UpdateVoucherDto { + private final long value; + private final int VoucherType; + + public UpdateVoucherDto(long value, int voucherType) { + this.value = value; + this.VoucherType = voucherType; + } + + public long getValue() { + return value; + } + + public int getVoucherType() { + return VoucherType; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/exception/ExceptionType.java b/src/main/java/com/prgms/vouchermanager/exception/ExceptionType.java new file mode 100644 index 0000000000..8383d328ea --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/exception/ExceptionType.java @@ -0,0 +1,32 @@ +package com.prgms.vouchermanager.exception; + +public enum ExceptionType { + INVALID_FRONT_MENU("초기 메뉴 번호를 잘못 입력하셨습니다."), + INVALID_VOUCHER_MENU("바우처 메뉴 번호를 잘못 입력하셨습니다."), + INVALID_CUSTOMER_MENU("고객 메뉴 번호를 잘못 입력하셨습니다."), + + INVALID_VOUCHER_PERCENT("할인율은 최대 100%입니다."), + INVALID_VOUCHER_INFO("쿠폰 정보를 잘못 입력하셨습니다."), + + INVALID_VOUCHER_TYPE("쿠폰 타입을 잘못 입력하셨습니다."), + + INVALID_READ_FILE("파일을 읽을 수 없습니다."), + + INVALID_WRITE_FILE("파일에 저장할 수 없습니다."), + + DUPLICATED_KEY("이미 등록된 쿠폰 번호입니다."), + INVALID_VOUCHER_ID("존재하지 않는 쿠폰 ID입니다."), + INVALID_CUSTOMER_INFO("고객정보가 너무 길거나 너무 짧습니다."), + INVALID_CUSTOMER_ID("존재하지 않는 고객 ID입니다."), + INVALID_WALLET_INFO("지갑에 저장할수 없는 정보입니다"), + INVALID_WALLET_MENU("지갑 메뉴를 잘못 입력하셨습니다."); + private final String message; + + ExceptionType(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerFileRepository.java b/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerFileRepository.java new file mode 100644 index 0000000000..2d709e0ee7 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerFileRepository.java @@ -0,0 +1,25 @@ +package com.prgms.vouchermanager.repository.customer; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.util.file.FileManager; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Repository +@Profile("file") +public class CustomerFileRepository { + private final Map blackList; + + public CustomerFileRepository(FileManager fileManager) { + + blackList = fileManager.readBlackListCsv(); + } + public List getBlackList() { + + return blackList.values() + .stream().toList(); + } +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerQueryType.java b/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerQueryType.java new file mode 100644 index 0000000000..968aba6906 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerQueryType.java @@ -0,0 +1,22 @@ +package com.prgms.vouchermanager.repository.customer; + +public enum CustomerQueryType { + + INSERT("insert into customers (id, name, email, black_list ) values (:id, :name, :email, :black_list )"), + UPDATE("update customers set id = :id , name = :name , email = :email , black_list = :black_list where id = :id"), + SELECT_BY_ID("select * from customers where id = :id"), + SELECT_ALL("select * from customers"), + DELETE_ALL("delete from customers"), + DELETE_BY_ID("delete from customers where id = :id"), + BLACKLIST("select * from customers where black_list=0"); + + private final String query; + + CustomerQueryType(String query) { + this.query = query; + } + + public String getQuery() { + return query; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerRepository.java b/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerRepository.java new file mode 100644 index 0000000000..66f293eab6 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/customer/CustomerRepository.java @@ -0,0 +1,24 @@ +package com.prgms.vouchermanager.repository.customer; + +import com.prgms.vouchermanager.domain.customer.Customer; + +import java.util.List; +import java.util.Optional; + +public interface CustomerRepository { + Customer save(Customer customer); + + void update(Customer customer); + + + Optional findById(Long id); + + List findAll(); + + void deleteById(Long id); + + void deleteAll(); + + List findBlackList(); + +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/customer/JdbcCustomerRepository.java b/src/main/java/com/prgms/vouchermanager/repository/customer/JdbcCustomerRepository.java new file mode 100644 index 0000000000..48d0b82982 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/customer/JdbcCustomerRepository.java @@ -0,0 +1,116 @@ +package com.prgms.vouchermanager.repository.customer; + +import com.prgms.vouchermanager.domain.customer.Customer; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.util.List; +import java.util.Optional; + +import static com.prgms.vouchermanager.repository.customer.CustomerQueryType.*; + + +@Repository +@Slf4j +@Profile("jdbc") +public class JdbcCustomerRepository implements CustomerRepository { + private final NamedParameterJdbcTemplate template; + + public JdbcCustomerRepository(DataSource dataSource) { + template = new NamedParameterJdbcTemplate(dataSource); + } + + public Customer save(Customer customer) { + + KeyHolder keyHolder = new GeneratedKeyHolder(); + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", customer.getId()) + .addValue("name", customer.getName()) + .addValue("email", customer.getEmail()) + .addValue("black_list", customer.isBlackList()); + + template.update(INSERT.getQuery(), param, keyHolder); + long id = keyHolder.getKey().longValue(); + + customer.setId(id); + return customer; + + } + + @Override + public void update(Customer customer) { + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", customer.getId()) + .addValue("name", customer.getName()) + .addValue("email", customer.getEmail()) + .addValue("black_list", customer.isBlackList()); + + template.update(UPDATE.getQuery(), param); + } + + @Override + public Optional findById(Long id) { + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", id); + + try { + return Optional.ofNullable(template.queryForObject(SELECT_BY_ID.getQuery(), param, customerRowMapper())); + } catch (EmptyResultDataAccessException e) { + return Optional.empty(); + } + + } + + @Override + public List findAll() { + + return template.query(SELECT_ALL.getQuery(), customerRowMapper()); + } + + @Override + public void deleteById(Long id) { + + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", id); + + template.update(DELETE_BY_ID.getQuery(), param); + + } + + @Override + public void deleteAll() { + + template.update(DELETE_ALL.getQuery(),new MapSqlParameterSource()); + + } + + @Override + public List findBlackList() { + return template.query(BLACKLIST.getQuery(), customerRowMapper()); + } + + private RowMapper customerRowMapper() { + return (rs, count) -> { + Long id = Long.parseLong(rs.getString("id")); + String name = rs.getString("name"); + String email = rs.getString("email"); + Boolean black_list = Boolean.valueOf(rs.getString("black_list")); + + return new Customer(id, name, email, black_list); + }; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/voucher/FileVoucherRepository.java b/src/main/java/com/prgms/vouchermanager/repository/voucher/FileVoucherRepository.java new file mode 100644 index 0000000000..5c31242c93 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/voucher/FileVoucherRepository.java @@ -0,0 +1,83 @@ +package com.prgms.vouchermanager.repository.voucher; + + +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.voucher.VoucherType; +import com.prgms.vouchermanager.util.file.FileManager; +import jakarta.annotation.PreDestroy; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +@Repository +@Profile("file") +public class FileVoucherRepository implements VoucherRepository { + private final FileManager fileManager; + + private final Map vouchers; + + public FileVoucherRepository(FileManager fileManager) { + this.fileManager = fileManager; + vouchers = fileManager.readVoucherCsv(); + + } + + @Override + public Voucher save(Voucher voucher) { + return vouchers.put(voucher.getId(), voucher); + } + + @Override + public void update(Voucher voucher) { + vouchers.put(voucher.getId(), voucher); + } + + @Override + public Optional findById(UUID id) { + try { + Voucher voucher = vouchers.get(id); + return Optional.of(voucher); + } catch (NullPointerException e) { + return Optional.empty(); + } + } + + @Override + public List findAll() { + return new ArrayList<>(vouchers.values()); + } + + @Override + public void deleteById(UUID id) { + vouchers.remove(id); + } + + @Override + public void deleteAll() { + vouchers.clear(); + } + + @Override + public List findByDate(LocalDateTime startTime, LocalDateTime endTime) { + return vouchers.values().stream() + .filter(voucher -> voucher.getCreatedAt().isAfter(startTime) && voucher.getCreatedAt().isBefore(endTime)) + .collect(Collectors.toUnmodifiableList()); + } + + @Override + public List findByType(VoucherType type) { + return vouchers.values().stream() + .filter(voucher -> voucher.getVoucherType().equals(VoucherType.FIXED_AMOUNT)) + .collect(Collectors.toUnmodifiableList()); + } + + + @PreDestroy + public void saveRepository() { + fileManager.saveVoucherFile(vouchers); + } +} + diff --git a/src/main/java/com/prgms/vouchermanager/repository/voucher/JdbcVoucherRepository.java b/src/main/java/com/prgms/vouchermanager/repository/voucher/JdbcVoucherRepository.java new file mode 100644 index 0000000000..1d2c4cbf5d --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/voucher/JdbcVoucherRepository.java @@ -0,0 +1,135 @@ +package com.prgms.vouchermanager.repository.voucher; + +import com.prgms.vouchermanager.domain.voucher.FixedAmountVoucher; +import com.prgms.vouchermanager.domain.voucher.PercentDiscountVoucher; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.voucher.VoucherType; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static com.prgms.vouchermanager.exception.ExceptionType.DUPLICATED_KEY; +import static com.prgms.vouchermanager.repository.voucher.VoucherQueryType.*; + + +@Repository +@Slf4j +@Profile("jdbc") +public class JdbcVoucherRepository implements VoucherRepository { + private final NamedParameterJdbcTemplate template; + + public JdbcVoucherRepository(DataSource dataSource) { + template = new NamedParameterJdbcTemplate(dataSource); + } + + @Override + public Voucher save(Voucher voucher) { + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", voucher.getId().toString()) + .addValue("discount_value", voucher.getDiscountValue()) + .addValue("type", voucher.getVoucherType().name()); + + try { + template.update(INSERT.getQuery(), param); + } catch (DuplicateKeyException e) { + throw new DuplicateKeyException(DUPLICATED_KEY.getMessage()); + } + + return voucher; + + } + + @Override + public Optional findById(UUID id) { + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", id.toString()); + try { + return Optional.ofNullable(template.queryForObject(SELECT_BY_ID.getQuery(), param, voucherRowMapper())); + } catch (EmptyResultDataAccessException e) { + return Optional.empty(); + } + } + + @Override + public List findAll() { + + return template.query(SELECT_ALL.getQuery(), voucherRowMapper()); + + } + + @Override + public void update(Voucher voucher) { + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", voucher.getId().toString()) + .addValue("discount_value", voucher.getDiscountValue()) + .addValue("type", voucher.getVoucherType().name()); + + template.update(UPDATE.getQuery(), param); + } + + @Override + public void deleteById(UUID id) { + SqlParameterSource param = new MapSqlParameterSource() + .addValue("id", id.toString()); + + template.update(DELETE_BY_ID.getQuery(), param); + + } + + @Override + public void deleteAll() { + template.update(DELETE_ALL.getQuery(), new MapSqlParameterSource()); + } + + @Override + public List findByDate(LocalDateTime startTime, LocalDateTime endTime) { + { + SqlParameterSource param = new MapSqlParameterSource() + .addValue("start_time", startTime) + .addValue("end_time", endTime); + + return template.query(SELECT_BETWEEN_DATE.getQuery(), param, voucherRowMapper()); + } + } + + @Override + public List findByType(VoucherType type) { + { + SqlParameterSource param = new MapSqlParameterSource() + .addValue("type", type.name()); + + return template.query(SELECT_BY_TYPE.getQuery(), param, voucherRowMapper()); + } + } + + + private RowMapper voucherRowMapper() { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return (rs, count) -> { + UUID id = UUID.fromString(rs.getString("id")); + VoucherType type = VoucherType.valueOf(rs.getString("type")); + Long discountValue = rs.getLong("discount_value"); + LocalDateTime createdAt = LocalDateTime.parse(rs.getString("created_at"), formatter); + return type == VoucherType.FIXED_AMOUNT ? + new FixedAmountVoucher(id, discountValue, createdAt) : + new PercentDiscountVoucher(id, discountValue, createdAt); + }; + } + + +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/voucher/MemoryVoucherRepository.java b/src/main/java/com/prgms/vouchermanager/repository/voucher/MemoryVoucherRepository.java new file mode 100644 index 0000000000..41f9f1b2d3 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/voucher/MemoryVoucherRepository.java @@ -0,0 +1,75 @@ +package com.prgms.vouchermanager.repository.voucher; + +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.voucher.VoucherType; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +@Repository +@Profile("memory") +public class MemoryVoucherRepository implements VoucherRepository { + + private final Map vouchers; + + public MemoryVoucherRepository() { + this.vouchers = new ConcurrentHashMap<>(); + } + + @Override + public Voucher save(Voucher voucher) { + return vouchers.put(voucher.getId(), voucher); + } + + @Override + public void update(Voucher voucher) { + vouchers.put(voucher.getId(), voucher); + } + + @Override + public Optional findById(UUID id) { + try { + Voucher voucher = vouchers.get(id); + return Optional.of(voucher); + } catch (NullPointerException e) { + return Optional.empty(); + } + } + + @Override + public List findAll() { + return new ArrayList<>(vouchers.values()); + } + + @Override + public void deleteAll() { + vouchers.clear(); + } + + + @Override + public List findByType(VoucherType type) { + return vouchers.values().stream() + .filter(voucher -> voucher.getVoucherType().equals(VoucherType.FIXED_AMOUNT)) + .collect(Collectors.toUnmodifiableList()); + } + + @Override + public List findByDate(LocalDateTime startTime, LocalDateTime endTime) { + return vouchers.values().stream() + .filter(voucher -> voucher.getCreatedAt().isAfter(startTime) && voucher.getCreatedAt().isBefore(endTime)) + .collect(Collectors.toUnmodifiableList()); + } + + @Override + public void deleteById(UUID id) { + if (vouchers.containsKey(id)) { + vouchers.remove(id); + } + } + +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/voucher/VoucherQueryType.java b/src/main/java/com/prgms/vouchermanager/repository/voucher/VoucherQueryType.java new file mode 100644 index 0000000000..4c60a2f7dc --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/voucher/VoucherQueryType.java @@ -0,0 +1,26 @@ +package com.prgms.vouchermanager.repository.voucher; + +public enum VoucherQueryType { + + SELECT_BY_ID("select * from vouchers WHERE id = :id"), + SELECT_BY_TYPE("select * from vouchers WHERE type = :type "), + SELECT_BETWEEN_DATE("select * from vouchers where created_at >= :start_time and created_at <= :end_time"), + SELECT_ALL("select * from vouchers"), + INSERT("insert into vouchers (id, discount_value, type) " + + "values (:id, :discount_value, :type)"), + + UPDATE("update vouchers set id = :id , discount_value = :discount_value, type = :type " + + "where id = :id"), + DELETE_BY_ID("delete from vouchers where id = :id"), + DELETE_ALL("delete from vouchers"); + + private final String query; + + VoucherQueryType(String query) { + this.query = query; + } + + public String getQuery() { + return query; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/voucher/VoucherRepository.java b/src/main/java/com/prgms/vouchermanager/repository/voucher/VoucherRepository.java new file mode 100644 index 0000000000..accd0bf8a5 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/voucher/VoucherRepository.java @@ -0,0 +1,28 @@ +package com.prgms.vouchermanager.repository.voucher; + +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.voucher.VoucherType; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface VoucherRepository { + + Voucher save(Voucher voucher); + + void update(Voucher voucher); + + Optional findById(UUID id); + + List findAll(); + + void deleteById(UUID id); + + void deleteAll(); + + List findByDate(LocalDateTime startTime, LocalDateTime endTime); + + List findByType(VoucherType type); +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/wallet/JdbcWalletRepository.java b/src/main/java/com/prgms/vouchermanager/repository/wallet/JdbcWalletRepository.java new file mode 100644 index 0000000000..92542cdbe9 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/wallet/JdbcWalletRepository.java @@ -0,0 +1,95 @@ +package com.prgms.vouchermanager.repository.wallet; + +import com.prgms.vouchermanager.domain.wallet.Wallet; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import javax.sql.DataSource; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static com.prgms.vouchermanager.repository.wallet.WalletQueryType.*; + + +@Repository +public class JdbcWalletRepository implements WalletRepository { + + private final NamedParameterJdbcTemplate template; + + public JdbcWalletRepository(DataSource dataSource) { + template = new NamedParameterJdbcTemplate(dataSource); + } + + @Transactional + @Override + public Wallet save(Wallet wallet) { + + KeyHolder keyHolder = new GeneratedKeyHolder(); + + MapSqlParameterSource param = new MapSqlParameterSource() + .addValue("id", wallet.getId()) + .addValue("customer_id", wallet.getCustomerId()) + .addValue("voucher_id", wallet.getVoucherId().toString()); + + template.update(INSERT.getQuery(), param, keyHolder); + long id = keyHolder.getKey().longValue(); + + wallet.setId(id); + + return wallet; + } + + @Override + public List findByCustomerId(Long customerId) { + + MapSqlParameterSource param = new MapSqlParameterSource() + .addValue("customer_id", customerId); + + return template.query(SELECT_BY_CUSTOMER_ID.getQuery(), param, walletRowMapper()); + + } + + @Override + public Optional findByVoucherId(UUID voucherId) { + MapSqlParameterSource param = new MapSqlParameterSource() + .addValue("voucher_id", voucherId.toString()); + + try { + return Optional.ofNullable(template.queryForObject(SELECT_BY_VOUCHER_ID.getQuery(), param, walletRowMapper())); + } catch (EmptyResultDataAccessException e) { + return Optional.empty(); + } + } + + @Override + public List findAll() { + return template.query(SELECT_ALL.getQuery(), walletRowMapper()); + } + + @Transactional + @Override + public void deleteByCustomerId(Long customerId) { + MapSqlParameterSource param = new MapSqlParameterSource() + .addValue("customer_id", customerId); + + template.update(DELETE_BY_CUSTOMER_ID.getQuery(), param); + + } + + private RowMapper walletRowMapper() { + return (rs, count) -> { + Long id = Long.parseLong(rs.getString("id")); + Long customerId = Long.parseLong(rs.getString("customer_id")); + UUID voucherId = UUID.fromString(rs.getString("voucher_id")); + + return new Wallet(id, customerId, voucherId); + }; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/wallet/WalletQueryType.java b/src/main/java/com/prgms/vouchermanager/repository/wallet/WalletQueryType.java new file mode 100644 index 0000000000..b2464fbed1 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/wallet/WalletQueryType.java @@ -0,0 +1,23 @@ +package com.prgms.vouchermanager.repository.wallet; + +public enum WalletQueryType { + INSERT("insert into wallets (id, customer_id, voucher_id) " + + "values (:id, :customer_id, :voucher_id)"), + + SELECT_BY_CUSTOMER_ID("select * from wallets where customer_id = :customer_id "), + + SELECT_BY_VOUCHER_ID("select * from wallets where voucher_id = :voucher_id "), + + DELETE_BY_CUSTOMER_ID("delete from wallets where customer_id = :customer_id"), + SELECT_ALL("select * from wallets"); + + private final String query; + + WalletQueryType(String query) { + this.query = query; + } + + public String getQuery() { + return query; + } +} diff --git a/src/main/java/com/prgms/vouchermanager/repository/wallet/WalletRepository.java b/src/main/java/com/prgms/vouchermanager/repository/wallet/WalletRepository.java new file mode 100644 index 0000000000..9698d9a7b6 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/repository/wallet/WalletRepository.java @@ -0,0 +1,20 @@ +package com.prgms.vouchermanager.repository.wallet; + +import com.prgms.vouchermanager.domain.wallet.Wallet; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface WalletRepository { + + Wallet save(Wallet wallet); + + List findByCustomerId(Long customerId); + + void deleteByCustomerId(Long customerId); + + Optional findByVoucherId(UUID voucherId); + + List findAll(); +} diff --git a/src/main/java/com/prgms/vouchermanager/service/customer/CustomerService.java b/src/main/java/com/prgms/vouchermanager/service/customer/CustomerService.java new file mode 100644 index 0000000000..c04f4d378c --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/service/customer/CustomerService.java @@ -0,0 +1,91 @@ +package com.prgms.vouchermanager.service.customer; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.dto.CreateCustomerDto; +import com.prgms.vouchermanager.dto.UpdateCustomerDto; +import com.prgms.vouchermanager.repository.customer.CustomerRepository; +import com.prgms.vouchermanager.validation.InputValidation; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_CUSTOMER_ID; +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_CUSTOMER_INFO; + +@Service +public class CustomerService { + + private final CustomerRepository customerRepository; + private final InputValidation inputValidation; + + public CustomerService(CustomerRepository customerRepository, InputValidation inputValidation) { + this.customerRepository = customerRepository; + this.inputValidation = inputValidation; + } + + @Transactional + public Customer create(CreateCustomerDto dto) { + + boolean blackList = false; + + if (inputValidation.validCustomerInfo(dto.getName(), dto.getEmail(), dto.getBlackList())) { + + if (dto.getBlackList() == 1) { + blackList = true; + } + + return customerRepository.save(new Customer(null, dto.getName(), dto.getEmail(), blackList)); + } + throw new RuntimeException(INVALID_CUSTOMER_INFO.getMessage()); + + } + + @Transactional + public void update(Long id, UpdateCustomerDto dto) { + + boolean blackList = false; + if (inputValidation.validCustomerInfo(dto.getName(), dto.getEmail(), dto.getBlackList())) { + if (dto.getBlackList() == 1) { + blackList = true; + } + customerRepository.update(new Customer(id, dto.getName(), dto.getEmail(), blackList)); + } else throw new RuntimeException(INVALID_CUSTOMER_INFO.getMessage()); + } + + @Transactional(readOnly = true) + public Customer findById(Long id) { + + return customerRepository.findById(id).orElseThrow(() -> new EmptyResultDataAccessException(INVALID_CUSTOMER_ID.getMessage(), 1)); + + } + + @Transactional(readOnly = true) + public List findAll() { + + List customers = customerRepository.findAll(); + return customers; + } + + @Transactional + public void deleteById(Long id) { + + customerRepository.deleteById(id); + + } + + @Transactional + public void deleteAll() { + + customerRepository.deleteAll(); + + } + + @Transactional(readOnly = true) + public List findBlackList() { + + return customerRepository.findBlackList(); + + } +} diff --git a/src/main/java/com/prgms/vouchermanager/service/voucher/VoucherService.java b/src/main/java/com/prgms/vouchermanager/service/voucher/VoucherService.java new file mode 100644 index 0000000000..dbf257330e --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/service/voucher/VoucherService.java @@ -0,0 +1,92 @@ +package com.prgms.vouchermanager.service.voucher; + + +import com.prgms.vouchermanager.domain.voucher.FixedAmountVoucher; +import com.prgms.vouchermanager.domain.voucher.PercentDiscountVoucher; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.voucher.VoucherType; +import com.prgms.vouchermanager.dto.CreateVoucherDto; +import com.prgms.vouchermanager.dto.UpdateVoucherDto; +import com.prgms.vouchermanager.repository.voucher.VoucherRepository; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_VOUCHER_ID; +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_VOUCHER_INFO; + +@Service +public class VoucherService { + + private final VoucherRepository voucherRepository; + + public VoucherService(VoucherRepository voucherRepository) { + this.voucherRepository = voucherRepository; + } + + @Transactional + public Voucher create(CreateVoucherDto dto) { + + Voucher voucher = null; + + if (dto.getVoucherType() == 1) { + voucher = new FixedAmountVoucher(UUID.randomUUID(), dto.getValue(), null); + } else if (dto.getVoucherType() == 2) { + voucher = new PercentDiscountVoucher(UUID.randomUUID(), dto.getValue(), null); + } else throw new RuntimeException(INVALID_VOUCHER_INFO.getMessage()); + + return voucherRepository.save(voucher); + } + + @Transactional + public void update(UUID id, UpdateVoucherDto dto) { + + Voucher voucher = null; + + if (dto.getVoucherType() == 1) { + voucher = new FixedAmountVoucher(id, dto.getValue(), null); + } else if (dto.getVoucherType() == 2) { + voucher = new PercentDiscountVoucher(id, dto.getValue(), null); + } else throw new RuntimeException(INVALID_VOUCHER_INFO.getMessage()); + + voucherRepository.update(voucher); + + } + + @Transactional(readOnly = true) + + public Voucher findById(UUID id) { + + return voucherRepository.findById(id).orElseThrow(() -> new EmptyResultDataAccessException(INVALID_VOUCHER_ID.getMessage(), 1)); + + } + + @Transactional(readOnly = true) + + public List findAll() { + return voucherRepository.findAll(); + } + + @Transactional + public void deleteById(UUID id) { + voucherRepository.deleteById(id); + } + + @Transactional + public void deleteAll() { + voucherRepository.deleteAll(); + } + + public List findByDate(LocalDateTime startTime, LocalDateTime endTime) { + return voucherRepository.findByDate(startTime, endTime); + } + + public List findByType(VoucherType type) { + return voucherRepository.findByType(type); + } +} + diff --git a/src/main/java/com/prgms/vouchermanager/service/wallet/WalletService.java b/src/main/java/com/prgms/vouchermanager/service/wallet/WalletService.java new file mode 100644 index 0000000000..4714f6a312 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/service/wallet/WalletService.java @@ -0,0 +1,65 @@ +package com.prgms.vouchermanager.service.wallet; + +import com.prgms.vouchermanager.domain.wallet.Wallet; +import com.prgms.vouchermanager.dto.CreateWalletDto; +import com.prgms.vouchermanager.repository.wallet.WalletRepository; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +import static com.prgms.vouchermanager.exception.ExceptionType.*; + +@Service +public class WalletService { + + private final WalletRepository walletRepository; + + public WalletService(WalletRepository walletRepository) { + this.walletRepository = walletRepository; + } + + @Transactional + public Wallet save(CreateWalletDto dto) { + + try { + return walletRepository.save(new Wallet(null, dto.getCustomerId(), dto.getVoucherId())); + } catch (DataIntegrityViolationException e) { + throw new DataIntegrityViolationException(INVALID_WALLET_INFO.getMessage()); + } + } + + @Transactional + public void deleteByCustomerId(Long customerId) { + + try { + walletRepository.deleteByCustomerId(customerId); + } catch (EmptyResultDataAccessException e) { + throw new EmptyResultDataAccessException(INVALID_CUSTOMER_ID.getMessage(), 0); + } + } + + @Transactional(readOnly = true) + + public List findByCustomerId(Long customerId) { + try { + return walletRepository.findByCustomerId(customerId); + } catch (EmptyResultDataAccessException e) { + throw new EmptyResultDataAccessException(INVALID_CUSTOMER_ID.getMessage(), 0); + } + } + + @Transactional(readOnly = true) + + public Wallet findByVoucherId(UUID voucherId) { + + return walletRepository.findByVoucherId(voucherId).orElseThrow(() -> new EmptyResultDataAccessException(INVALID_VOUCHER_ID.getMessage(), 0)); + } + + public List findAll() { + return walletRepository.findAll(); + } +} diff --git a/src/main/java/com/prgms/vouchermanager/util/file/FileManager.java b/src/main/java/com/prgms/vouchermanager/util/file/FileManager.java new file mode 100644 index 0000000000..3fec51bef5 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/util/file/FileManager.java @@ -0,0 +1,109 @@ +package com.prgms.vouchermanager.util.file; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.domain.voucher.FixedAmountVoucher; +import com.prgms.vouchermanager.domain.voucher.PercentDiscountVoucher; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.voucher.VoucherType; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import static com.prgms.vouchermanager.domain.voucher.VoucherType.valueOf; +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_READ_FILE; +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_WRITE_FILE; + +/** + * 1. 바우처 FIle을 Repo에 return하기 + * 2. Repo를 바우처 File에 저장하기 + *

+ * 3. BlackList File을 Repo에 return하기 + */ +@Component +public class FileManager { + + private final String voucherListPath; + private final String blackListPath; + + + public FileManager( + @Value("${file.path.voucher}") String voucherListPath, + @Value("${file.path.blacklist}") String blackListPath) { + this.voucherListPath = voucherListPath; + this.blackListPath = blackListPath; + + } + + public Map readVoucherCsv() { + Map voucherMap = new ConcurrentHashMap<>(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(voucherListPath)))) { + String line = ""; + br.readLine(); + while ((line = br.readLine()) != null) { + String[] split = line.split(", "); + + UUID id = UUID.fromString(split[0]); + Long value = Long.parseLong(split[1]); + VoucherType voucherType = valueOf(split[2]); + LocalDateTime createdAt = LocalDateTime.now(); + if (voucherType == VoucherType.FIXED_AMOUNT) { + voucherMap.put(id, new FixedAmountVoucher(id, value, createdAt)); + } else if (voucherType == VoucherType.PERCENT_DISCOUNT) { + voucherMap.put(id, new PercentDiscountVoucher(id, value, createdAt)); + } + } + } catch (IOException e) { + throw new RuntimeException(INVALID_READ_FILE.getMessage()); + } + return voucherMap; + } + + + public Map readBlackListCsv() { + + Map customerMap = new ConcurrentHashMap<>(); + + try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(blackListPath)))) { + String line = ""; + br.readLine(); + while ((line = br.readLine()) != null) { + String[] split = line.split(", "); + + Long id = Long.parseLong(split[0]); + String name = split[1]; + String email = split[2]; + boolean blackList = split[3].equals("1"); + + customerMap.put(id, new Customer(id, name, email, blackList)); + } + } catch (IOException e) { + throw new RuntimeException(INVALID_READ_FILE.getMessage()); + } + return customerMap; + } + + public void saveVoucherFile(Map voucherMap) { + try (BufferedWriter bw = new BufferedWriter(new FileWriter(voucherListPath))) { + bw.write("id, discount value, voucher type"); + bw.newLine(); + for (Voucher voucher : new ArrayList<>(voucherMap.values())) { + bw.write(voucher.getId() + ", " + voucher.getDiscountValue() + ", " + voucher.getVoucherType()); + bw.newLine(); + } + } catch (IOException e) { + throw new RuntimeException(INVALID_WRITE_FILE.getMessage()); + } + } + +} + diff --git a/src/main/java/com/prgms/vouchermanager/util/io/ConsoleInput.java b/src/main/java/com/prgms/vouchermanager/util/io/ConsoleInput.java new file mode 100644 index 0000000000..f0adf3cac3 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/util/io/ConsoleInput.java @@ -0,0 +1,81 @@ +package com.prgms.vouchermanager.util.io; + +import com.prgms.vouchermanager.exception.ExceptionType; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Scanner; +import java.util.UUID; + +import static com.prgms.vouchermanager.exception.ExceptionType.*; +import static com.prgms.vouchermanager.exception.ExceptionType.INVALID_VOUCHER_INFO; + +@Slf4j +@Component +public class ConsoleInput { + private final Scanner scanner = new Scanner(System.in); + + private int inputMenu(ExceptionType type) { + try { + return scanner.nextInt(); + } catch (RuntimeException e) { + scanner.next(); + throw new RuntimeException(type.getMessage()); + } + } + + public int inputFrontMenu() { + return inputMenu(INVALID_FRONT_MENU); + } + + public int inputVoucherMenu() { + return inputMenu(INVALID_VOUCHER_MENU); + } + + public int inputCustomerMenu() { + + return inputMenu(INVALID_CUSTOMER_MENU); + } + + public int inputVoucherType() { + + return inputMenu(INVALID_VOUCHER_TYPE); + } + + public int inputBlackList() { + + return inputMenu(INVALID_CUSTOMER_INFO); + } + + public long inputVoucherValue() { + try { + return scanner.nextLong(); + } catch (RuntimeException e) { + throw new RuntimeException(INVALID_VOUCHER_INFO.getMessage()); + } + } + + public UUID inputVoucherId() { + try { + return UUID.fromString(scanner.next()); + } catch (RuntimeException e) { + throw new RuntimeException(INVALID_VOUCHER_INFO.getMessage()); + } + } + + public String inputCustomerName() { + return scanner.next(); + } + + public String inputCustomerEmail() { + return scanner.next(); + } + + public Long inputCustomerId() { + try { + return scanner.nextLong(); + } catch (RuntimeException e) { + throw new RuntimeException(INVALID_CUSTOMER_INFO.getMessage()); + } + } +} diff --git a/src/main/java/com/prgms/vouchermanager/util/io/ConsoleOutput.java b/src/main/java/com/prgms/vouchermanager/util/io/ConsoleOutput.java new file mode 100644 index 0000000000..a4b15fedd9 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/util/io/ConsoleOutput.java @@ -0,0 +1,137 @@ +package com.prgms.vouchermanager.util.io; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.domain.wallet.Wallet; +import org.springframework.stereotype.Component; + +@Component +public class ConsoleOutput { + + private void printCommon(String s) { + System.out.println(s); + } + public void printFrontMenu() { + printCommon(""" + + 사용할 메뉴를 선택해주세요. + + 1. Voucher + + 2. Customer + + 3. Wallet + + 4. EXIT + """); + } + + public void printVoucherMenu() { + printCommon(""" + === Voucher Program === + + 이용할 바우처 메뉴를 선택해주세요 + + 1. create + + 2. update + + 3. list + + 4. find one + + 5. delete one + + 6. delete all + + """); + } + + + public void printVoucherType() { + printCommon(""" + + 이용하실 쿠폰의 타입 번호를 입력해주세요 + + 1. FixedAmount + + 2. PercentDiscount + + """); + } + + public void printCustomerMenu() { + printCommon(""" + + 이용하실 고객 메뉴를 입력해주세요 + + 1. CREATE + + 2. UPDATE + + 3. FIND ALL + + 4. FIND ONE + + 5. DELETE ONE + + 6. DELETE ALL + + 7. BLACK LIST + + """); + } + + public void printWalletMenu() { + printCommon(""" + 이용하실 지갑 메뉴를 입력해주세요 + + 1. CREATE + + 2. FIND BY CUSTOMER ID + + 3. FIND BY VOUCHER ID + + 4. DELETE BY CUSTOMER ID + + """); + } + public void printVoucherAmount() { + printCommon("쿠폰의 할인값을 입력해주세요"); + } + + public void printVoucherId() { + printCommon("쿠폰 번호를 입력해주세요."); + } + + public void printSuccessDelete() { + printCommon("성공적으로 삭제되었습니다."); + } + + public void printCustomerName() { + printCommon("고객명을 입력해주세요.{"); + } + + public void printCustomerEmail() { + printCommon("이메일을 입력해주세요."); + } + + public void printBlackList() { + printCommon("블랙리스트에 등록하시려면 1번, 아니라면 2번을 입력해주세요"); + } + + public void printCustomerId() { + printCommon("고객 ID를 입력해주세요."); + } + + public void printCustomer(Customer customer) { + printCommon(customer.toString()); + } + + public void printSuccessUpdate() { + printCommon("성공적으로 업데이트 되었습니다."); + } + + public void printWallet(Wallet wallet) { + printCommon(wallet.toString()); + } +} diff --git a/src/main/java/com/prgms/vouchermanager/validation/InputValidation.java b/src/main/java/com/prgms/vouchermanager/validation/InputValidation.java new file mode 100644 index 0000000000..0f5446c469 --- /dev/null +++ b/src/main/java/com/prgms/vouchermanager/validation/InputValidation.java @@ -0,0 +1,32 @@ +package com.prgms.vouchermanager.validation; + +import org.springframework.stereotype.Component; + +@Component +public class InputValidation { + + + public boolean validFrontMenu(int menu) { + return menu>=1&&menu<=4; + } + + public boolean validVoucherMenu(int menu) { + return menu>=1 && menu<=6; + } + + public boolean validCustomerMenu(int menu) { + return menu>=1 && menu<=7; + } + public boolean validWalletMenu(int menu) { + return menu>=1 && menu<=4; + } + + public boolean validVoucherPercent(long percent) { + return percent<=100 ; + } + public boolean validCustomerInfo(String name, String email,int blackList) { + return name.length()<=20 + && email.length()<=40 + && blackList>=1 && blackList<=2 ; + } +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000000..42bb539b35 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,29 @@ +spring: + profiles: + active: jdbc , tomcat + + + datasource: + driverClassName: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/voucher?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul + username: yong + password: 1234 + + sql: + init: + mode: always + + mvc: + hiddenmethod: + filter: + enabled: true + + +file: + path: + voucher: src/main/resources/voucher_list.csv + blacklist: src/main/resources/customer_blackList.csv + + + + diff --git a/src/main/resources/customer_blackList.csv b/src/main/resources/customer_blackList.csv new file mode 100644 index 0000000000..d170b9a86e --- /dev/null +++ b/src/main/resources/customer_blackList.csv @@ -0,0 +1,6 @@ +id, name, email , blackList +1, kim, kim@naver.com, 1 +2, lee, lee@naver.com, 1 +3, park, park@naver.com, 2 +4, hong, hong@naver.com, 2 +5, kang, kang@naver.com, 2 diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql new file mode 100644 index 0000000000..f7d2189210 --- /dev/null +++ b/src/main/resources/data.sql @@ -0,0 +1,17 @@ +insert into vouchers +values ('bc2e6a9d-1319-4db0-83ba-e07a85fffab8', 22, 'PERCENT_DISCOUNT', now()); +insert into vouchers +values ('50976229-81af-4dd2-a36d-0f15a58d6f33', 10000, 'FIXED_AMOUNT', now()); + + +insert into customers +values (1, 'kim', 'won05121@naver.com', 0); +insert into customers +values (2, 'park', 'park@naver.com', 1); +insert into customers +values (3, 'lee', 'lee@naver.com', 0); + +insert into wallets +values (1, 2, 'bc2e6a9d-1319-4db0-83ba-e07a85fffab8'); +insert into wallets +values (2, 3, '50976229-81af-4dd2-a36d-0f15a58d6f33'); diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000000..243ad25b70 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,37 @@ + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + logs/access.log + + logs/access-%d{yyyy-MM-dd}.log + + + + ${FILE_LOG_PATTERN} + + + + + + + + + + + + + + diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000000..077f988453 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,31 @@ +DROP TABLE IF EXISTS wallets; +DROP TABLE IF EXISTS vouchers; +DROP TABLE IF EXISTS customers; + +CREATE TABLE vouchers +( + id varchar(36) primary key, + discount_value INT, + type varchar(20), + created_at datetime default now() +); + + +CREATE TABLE customers +( + id BIGINT primary key auto_increment, + name varchar(10), + email varchar(40), + black_list bool +); + + +CREATE TABLE wallets +( + id BIGINT primary key auto_increment, + customer_id BIGINT, + voucher_id VARCHAR(36), + foreign key (customer_id) REFERENCES customers (id) on delete cascade on update cascade, + foreign key (voucher_id) REFERENCES vouchers (id) on delete cascade on update cascade +); + diff --git a/src/main/resources/templates/fragment/header.html b/src/main/resources/templates/fragment/header.html new file mode 100644 index 0000000000..2e9e001695 --- /dev/null +++ b/src/main/resources/templates/fragment/header.html @@ -0,0 +1,64 @@ +

+ + +
+ + + + + + + diff --git a/src/main/resources/templates/voucher_create.html b/src/main/resources/templates/voucher_create.html new file mode 100644 index 0000000000..e3ee9dc6d6 --- /dev/null +++ b/src/main/resources/templates/voucher_create.html @@ -0,0 +1,38 @@ + + + +
+
+
+ + + + +
+
+
+
+

+ +

+ + +
+ +
+
+
+ + diff --git a/src/main/resources/templates/voucher_edit.html b/src/main/resources/templates/voucher_edit.html new file mode 100644 index 0000000000..15699be6c3 --- /dev/null +++ b/src/main/resources/templates/voucher_edit.html @@ -0,0 +1,41 @@ + + + +
+
+
+ + + + +
+
+
+
+ + +

+ + +

+ + +
+ +
+
+
+ + diff --git a/src/main/resources/templates/voucher_exception.html b/src/main/resources/templates/voucher_exception.html new file mode 100644 index 0000000000..a5fd898494 --- /dev/null +++ b/src/main/resources/templates/voucher_exception.html @@ -0,0 +1,29 @@ + + + +
+
+
+ + + + +
+
+
+

+ +
+
+
+ + diff --git a/src/main/resources/templates/voucher_list.html b/src/main/resources/templates/voucher_list.html new file mode 100644 index 0000000000..8d5b4c39c2 --- /dev/null +++ b/src/main/resources/templates/voucher_list.html @@ -0,0 +1,32 @@ + + + +
+
+
+ + + + +
+
+
+
+

쿠폰 번호

+ +
+
+
+
+
+ + diff --git a/src/main/resources/templates/voucher_one.html b/src/main/resources/templates/voucher_one.html new file mode 100644 index 0000000000..a7fddda9d2 --- /dev/null +++ b/src/main/resources/templates/voucher_one.html @@ -0,0 +1,37 @@ + + + +
+
+
+ + + + +
+
+
+

쿠폰번호

+

할인 타입

+
할인값
+
생성 시간
+
+
+ +
+
+ +
+
+
+ + diff --git a/src/main/resources/templates/wallet_create.html b/src/main/resources/templates/wallet_create.html new file mode 100644 index 0000000000..9d8a219eb4 --- /dev/null +++ b/src/main/resources/templates/wallet_create.html @@ -0,0 +1,35 @@ + + + +
+
+
+ + + + +
+
+
+
+ +

+ +

+ +
+ +
+
+
+ + diff --git a/src/main/resources/templates/wallet_exception.html b/src/main/resources/templates/wallet_exception.html new file mode 100644 index 0000000000..cf9edebce2 --- /dev/null +++ b/src/main/resources/templates/wallet_exception.html @@ -0,0 +1,29 @@ + + + +
+
+
+ + + + +
+
+
+

+ +
+
+
+ + diff --git a/src/main/resources/templates/wallet_list.html b/src/main/resources/templates/wallet_list.html new file mode 100644 index 0000000000..7a5ee73d3d --- /dev/null +++ b/src/main/resources/templates/wallet_list.html @@ -0,0 +1,38 @@ + + + +
+
+
+ + + + +
+
+
+
+

지갑 ID

+ +

회원 ID

+

바우처 ID

+ + +
+
+
+
+
+ + diff --git a/src/main/resources/voucher_list.csv b/src/main/resources/voucher_list.csv new file mode 100644 index 0000000000..9c4001d695 --- /dev/null +++ b/src/main/resources/voucher_list.csv @@ -0,0 +1,4 @@ +id, discount value, voucher type +96d02c0a-1a58-4191-93d4-2cee987886f1, 6, PERCENT_DISCOUNT +df5dbaa0-d748-4d04-9138-89a9fa911450, 10000, FIXED_AMOUNT +63feab9e-36ed-474a-92f8-1ade4ffb7788, 30, PERCENT_DISCOUNT diff --git a/src/test/java/com/prgms/vouchermanager/VouchermanagerApplicationTests.java b/src/test/java/com/prgms/vouchermanager/VouchermanagerApplicationTests.java new file mode 100644 index 0000000000..6f0459d0a9 --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/VouchermanagerApplicationTests.java @@ -0,0 +1,13 @@ +package com.prgms.vouchermanager; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class VouchermanagerApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/src/test/java/com/prgms/vouchermanager/controller/voucher/ApiVoucherControllerTest.java b/src/test/java/com/prgms/vouchermanager/controller/voucher/ApiVoucherControllerTest.java new file mode 100644 index 0000000000..dda2278e06 --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/controller/voucher/ApiVoucherControllerTest.java @@ -0,0 +1,60 @@ +package com.prgms.vouchermanager.controller.voucher; + +import com.prgms.vouchermanager.contorller.voucher.ApiVoucherController; +import com.prgms.vouchermanager.service.voucher.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.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.UUID; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(ApiVoucherController.class) +public class ApiVoucherControllerTest { + private final UUID existId = UUID.fromString("bc2e6a9d-1319-4db0-83ba-e07a85fffab8"); + private final UUID NotExistId = UUID.fromString("ac2e6a9d-1319-4db0-83ba-e07a85fffab1"); + @Autowired + private MockMvc mockMvc; + @MockBean + private VoucherService voucherService; + + @Test + @DisplayName("findAll()으로 모든 목록 불러오기를 성공한다.") + void findAll() throws Exception { + + mockMvc.perform(get("/api/vouchers") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()); + + } + + @Test + @DisplayName("findById()로 존재하는 바우처 읽기에 성공한다.") + void findByIdSuccess() throws Exception { + + mockMvc.perform(get("/api/vouchers/{id}", existId) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()); + + } + +// @Test +// @DisplayName("findById()로 존재하지 않는 바우처 읽기에 실패한다.") +// void findByIdFail() throws Exception { +// mockMvc.perform(get("/api/vouchers/{id}", NotExistId) +// .contentType(MediaType.APPLICATION_JSON)) +// .andExpect(status().isNotFound()) +// .andDo(print()); +// } --> 웹이나 postman에서는 notFound 처리되지만, mockMvc 테스트만 항상 200처리됩니다. + + +} diff --git a/src/test/java/com/prgms/vouchermanager/repository/customer/CustomerRepositoryTest.java b/src/test/java/com/prgms/vouchermanager/repository/customer/CustomerRepositoryTest.java new file mode 100644 index 0000000000..301c9f6ee7 --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/repository/customer/CustomerRepositoryTest.java @@ -0,0 +1,139 @@ +package com.prgms.vouchermanager.repository.customer; + +import com.prgms.vouchermanager.domain.customer.Customer; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; + +@SpringBootTest +@Transactional +public class CustomerRepositoryTest { + + @Autowired + private CustomerRepository customerRepository; + + @Test + @DisplayName("save()를 통해 id는 자동 증가하면서, 쿼리가 정상적으로 동작한다. ") + void saveCustomrSuccess() { + + //given + Customer customer1 = new Customer(null, "heo", "heo@naver.com", true); + Customer customer2 = new Customer(null, "koo", "koo@naver.com", false); + Customer customer3 = new Customer(null, "koo1", "koo@naver.com", false); + + //when + Customer saveCustomer1 = customerRepository.save(customer1); + Customer saveCustomer2 = customerRepository.save(customer2); + Customer saveCustomer3 = customerRepository.save(customer3); + + + //then + Assertions.assertThat(saveCustomer1.getId() + 1).isEqualTo(saveCustomer2.getId()); + Assertions.assertThat(saveCustomer2.getId() + 1).isEqualTo(saveCustomer3.getId()); + } + + @Test + @DisplayName("update()를 이용해 정보수정을 자유롭게 할수 있다.") + void updateCustomerSuccess() { + + //given + Customer customer1 = new Customer(null, "heo", "heo@naver.com", false); + String newEmail = "new@naver.com"; + + //when + Customer savedCustomer = customerRepository.save(customer1); + Customer updateCustomer = new Customer(savedCustomer.getId(), savedCustomer.getName(), newEmail, savedCustomer.isBlackList()); + customerRepository.update(updateCustomer); + Optional findCustomer = customerRepository.findById(savedCustomer.getId()); + + //then + Assertions.assertThat(updateCustomer.getName()).isEqualTo(findCustomer.get().getName()); + Assertions.assertThat(updateCustomer.getEmail()).isEqualTo(findCustomer.get().getEmail()); + Assertions.assertThat(updateCustomer.getId()).isEqualTo(findCustomer.get().getId()); + Assertions.assertThat(updateCustomer.isBlackList()).isEqualTo(findCustomer.get().isBlackList()); + + } + + @Test + @DisplayName("findById() 를 통해 Customer를 찾아올 수 있다.") + void findByIdCustomerSuccess() { + + //given + Customer customer = new Customer(null, "kim", "heo@naver.com", false); + + //when + Customer savedCustomer = customerRepository.save(customer); + Long id = savedCustomer.getId(); + Optional findByIdCustomer = customerRepository.findById(id); + + //then + Assertions.assertThat(customer.getName()).isEqualTo(findByIdCustomer.get().getName()); + Assertions.assertThat(customer.getEmail()).isEqualTo(findByIdCustomer.get().getEmail()); + Assertions.assertThat(customer.getId()).isEqualTo(findByIdCustomer.get().getId()); + Assertions.assertThat(customer.isBlackList()).isEqualTo(findByIdCustomer.get().isBlackList()); + } + + @Test + @DisplayName("findById 를 실행시 없는 ID를 조회하면, 빈 값이 넘어온다.") + void findByIdCustomerFail() { + + //given + Long notExistId = 123456L; + + //when + Optional findById = customerRepository.findById(notExistId); + + //then + Assertions.assertThat(findById).isEmpty(); + + } + + @Test + @DisplayName("findAll()실행시 성공적으로 모든 목록을 조회한다.") + void findAllCustomerSuccess() { + + //given + //when + List all = customerRepository.findAll(); + + //then + Assertions.assertThat(all).isNotNull(); + + } + + @Test + @DisplayName("deleteById()실행 시 customer를 성공적으로 삭제한다.") + void deleteByCustomerSuccess() { + + //given + Long id = 1L; + Customer customer = new Customer(null, "kim33", "lee@naver.com", true); + customerRepository.save(customer); + + //when + customerRepository.deleteById(id); + Optional findById = customerRepository.findById(id); + + //then + Assertions.assertThat(findById).isEmpty(); + } + + @Test + @DisplayName("findBlackList()실행시 성공적으로 blackList를 조회한다.") + void findBlackListSuccess() { + + //given + //when + List blackList = customerRepository.findBlackList(); + + //then + Assertions.assertThat(blackList).isNotNull(); + + } +} diff --git a/src/test/java/com/prgms/vouchermanager/repository/voucher/VoucherRepositoryTest.java b/src/test/java/com/prgms/vouchermanager/repository/voucher/VoucherRepositoryTest.java new file mode 100644 index 0000000000..ee1a5a7095 --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/repository/voucher/VoucherRepositoryTest.java @@ -0,0 +1,141 @@ +package com.prgms.vouchermanager.repository.voucher; + +import com.prgms.vouchermanager.domain.voucher.FixedAmountVoucher; +import com.prgms.vouchermanager.domain.voucher.PercentDiscountVoucher; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@SpringBootTest +@Transactional +public class VoucherRepositoryTest { + + @Autowired + private VoucherRepository voucherRepository; + + @Test + @DisplayName("save()실행시 정상적으로 저장된다. ") + void saveVoucherSuccess() { + + //given + + Voucher voucher = new FixedAmountVoucher(UUID.randomUUID(), 100000, null); + + //when + Voucher savedVoucher = voucherRepository.save(voucher); + + //then + Assertions.assertThat(voucher).isEqualTo(savedVoucher); + } + + @Test + @DisplayName("save()실행시 ID가 중복될 경우 예외가 발생한다.") + void saveVoucherFail() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher1 = new FixedAmountVoucher(id, 100000, null); + Voucher voucher2 = new PercentDiscountVoucher(id, 10, null); + + //when + voucherRepository.save(voucher1); + + //then + Assertions.assertThatThrownBy(() -> voucherRepository.save(voucher2)).isInstanceOf(DuplicateKeyException.class); + + } + + @Test + @DisplayName("update()를 이용해 정보수정을 자유롭게 할수 있다.") + void updateVoucherSuccess() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Voucher savedVoucher = voucherRepository.save(voucher); + Voucher updatedVoucher = new FixedAmountVoucher(savedVoucher.getId(), 9999, LocalDateTime.now()); + + //when + voucherRepository.update(updatedVoucher); + + Optional findVoucher = voucherRepository.findById(updatedVoucher.getId()); + + //then + Assertions.assertThat(updatedVoucher.getId()).isEqualTo(findVoucher.get().getId()); + Assertions.assertThat(updatedVoucher.getVoucherType()).isEqualTo(findVoucher.get().getVoucherType()); + Assertions.assertThat(updatedVoucher.getDiscountValue()).isEqualTo(findVoucher.get().getDiscountValue()); + + } + + @Test + @DisplayName("findById() 를 통해 Voucher를 찾아올 수 있다.") + void findByIdVoucherSuccess() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + + Voucher savedCustomer = voucherRepository.save(voucher); + + Optional findByIdVoucher = voucherRepository.findById(savedCustomer.getId()); + + //then + Assertions.assertThat(voucher.getId()).isEqualTo(findByIdVoucher.get().getId()); + Assertions.assertThat(voucher.getDiscountValue()).isEqualTo(findByIdVoucher.get().getDiscountValue()); + Assertions.assertThat(voucher.getVoucherType()).isEqualTo(findByIdVoucher.get().getVoucherType()); + } + + @Test + @DisplayName("findById 를 실행시 없는 ID를 조회하면, 빈 값이 넘어온다.") + void findByIdVoucherFail() { + + //given + UUID notExistId = UUID.randomUUID(); + + //when + Optional findById = voucherRepository.findById(notExistId); + + //then + Assertions.assertThat(findById).isEmpty(); + + } + + @Test + @DisplayName("findAll()실행시 성공적으로 모든 목록을 조회한다.") + void findAllVoucherSuccess() { + + //given + //when + List all = voucherRepository.findAll(); + + //then + Assertions.assertThat(all).isNotNull(); + + } + + @Test + @DisplayName("deleteById()실행 시 customer를 성공적으로 삭제한다.") + void deleteByVoucherSuccess() { + + //given + UUID id = UUID.randomUUID(); + voucherRepository.save(new FixedAmountVoucher(id, 1000, LocalDateTime.now())); + //when + voucherRepository.deleteById(id); + Optional findById = voucherRepository.findById(id); + + //then + Assertions.assertThat(findById).isEmpty(); + } + +} diff --git a/src/test/java/com/prgms/vouchermanager/repository/wallet/WalletRepositoryTest.java b/src/test/java/com/prgms/vouchermanager/repository/wallet/WalletRepositoryTest.java new file mode 100644 index 0000000000..dbe5ec11cc --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/repository/wallet/WalletRepositoryTest.java @@ -0,0 +1,176 @@ +package com.prgms.vouchermanager.repository.wallet; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.domain.voucher.FixedAmountVoucher; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.domain.wallet.Wallet; +import com.prgms.vouchermanager.repository.customer.CustomerRepository; +import com.prgms.vouchermanager.repository.voucher.VoucherRepository; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@SpringBootTest +@Transactional +public class WalletRepositoryTest { + + @Autowired + private WalletRepository walletRepository; + @Autowired + private VoucherRepository voucherRepository; + @Autowired + private CustomerRepository customerRepository; + + @Test + @DisplayName("save()실행시 wallets이 참조하는 customer_id와 voucher_id가 존재한다면, 정상적으로 저장된다. ") + void saveWalletSuccess() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Customer customer = new Customer(null, "ko", "kp@naver.com", true); + voucherRepository.save(voucher); + Customer savedCustomer = customerRepository.save(customer); + + Wallet wallet = new Wallet(6L, savedCustomer.getId(), id); + + //when + Wallet savedWallet = walletRepository.save(wallet); + + //then + Assertions.assertThat(wallet).isEqualTo(savedWallet); + } + + + @Test + @DisplayName("save()실행시 wallets이 참조하는 customer_id와 voucher_id가 존재하지 않는다면, 예외가 발생한다. ") + void saveWalletFail() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Customer customer = new Customer(null, "ko", "kp@naver.com", true); + Wallet wallet = new Wallet(10L, 1214L, UUID.randomUUID()); //존재하지 않는 참조데이터 + + //when + voucherRepository.save(voucher); + customerRepository.save(customer); + + //then + Assertions.assertThatThrownBy(() -> walletRepository.save(wallet)).isInstanceOf(DataIntegrityViolationException.class); + } + + + @Test + @DisplayName("customer_id에 해당하는 쿠폰 조회에 성공한다.") + void findByCustomerIdSuccess() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Customer customer = new Customer(10L, "ko", "kp@naver.com", true); + voucherRepository.save(voucher); + customerRepository.save(customer); + Wallet wallet = new Wallet(6L, customer.getId(), id); + + //when + walletRepository.save(wallet); + List wallets = walletRepository.findByCustomerId(customer.getId()); + + //then + Assertions.assertThat(wallets).isNotNull(); + } + + @Test + @DisplayName("customer_id에 해당하는 쿠폰 조회에 실패한다.") + void findByCustomerIdFail() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Customer customer = new Customer(10L, "ko", "kp@naver.com", true); + voucherRepository.save(voucher); + customerRepository.save(customer); + Wallet wallet = new Wallet(6L, customer.getId(), id); + + //when + walletRepository.save(wallet); + List wallets = walletRepository.findByCustomerId(123132L); + + //then + Assertions.assertThat(wallets).isEmpty(); + } + + @Test + @DisplayName("voucher_id에 해당하는 고객 조회에 성공한다.") + void findByVoucherIdSuccess() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Customer customer = new Customer(10L, "ko", "kp@naver.com", true); + voucherRepository.save(voucher); + customerRepository.save(customer); + Wallet wallet = new Wallet(6L, customer.getId(), id); + + //when + walletRepository.save(wallet); + Optional findByVoucherIdwallet = walletRepository.findByVoucherId(id); + + //then + Assertions.assertThat(findByVoucherIdwallet.get().getId()).isEqualTo(wallet.getId()); + Assertions.assertThat(findByVoucherIdwallet.get().getVoucherId()).isEqualTo(wallet.getVoucherId()); + Assertions.assertThat(findByVoucherIdwallet.get().getCustomerId()).isEqualTo(wallet.getCustomerId()); + } + + @Test + @DisplayName("voucher_id에 해당하는 고객 조회에 실패한다.") + void findByVoucherIdFail() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Customer customer = new Customer(10L, "ko", "kp@naver.com", true); + voucherRepository.save(voucher); + customerRepository.save(customer); + Wallet wallet = new Wallet(6L, customer.getId(), id); + + //when + walletRepository.save(wallet); + Optional findByVoucherIdwallet = walletRepository.findByVoucherId(UUID.randomUUID()); + + //then + Assertions.assertThat(findByVoucherIdwallet).isEmpty(); + } + + @Test + @DisplayName("deleteByCustomerId()실행 시 지갑 정보를 성공적으로 삭제한다..") + void deleteByCustomerIdSuccess() { + + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 100000, LocalDateTime.now()); + Customer customer = new Customer(10L, "ko", "kp@naver.com", true); + voucherRepository.save(voucher); + customerRepository.save(customer); + Wallet wallet = new Wallet(6L, customer.getId(), id); + walletRepository.save(wallet); + + //when + walletRepository.deleteByCustomerId(customer.getId()); + + //then + List wallets = walletRepository.findByCustomerId(customer.getId()); + Assertions.assertThat(wallets).isEmpty(); + } + +} diff --git a/src/test/java/com/prgms/vouchermanager/service/customer/CustomerServiceTest.java b/src/test/java/com/prgms/vouchermanager/service/customer/CustomerServiceTest.java new file mode 100644 index 0000000000..c61e7fe24b --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/service/customer/CustomerServiceTest.java @@ -0,0 +1,169 @@ +package com.prgms.vouchermanager.service.customer; + +import com.prgms.vouchermanager.domain.customer.Customer; +import com.prgms.vouchermanager.dto.CreateCustomerDto; +import com.prgms.vouchermanager.dto.UpdateCustomerDto; +import com.prgms.vouchermanager.repository.customer.CustomerRepository; +import com.prgms.vouchermanager.validation.InputValidation; +import org.assertj.core.api.Assertions; +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.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.EmptyResultDataAccessException; + +import java.util.List; +import java.util.Optional; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class CustomerServiceTest { + + @InjectMocks + CustomerService customerService; + @Mock + private CustomerRepository customerRepsotiory; + @Mock + private InputValidation inputValidation; + + @Test + @DisplayName("service의 create()를 통해 repository의 save()를 정상 실행하고, 값을 받아올수 있다.") + void createCusteomerSuccess() { + + //given + CreateCustomerDto dto = new CreateCustomerDto("kim", "won05121@naver.com", 1); + Customer result = new Customer(null, dto.getName(), dto.getEmail(), true); + + when(customerRepsotiory.save(any(Customer.class))).thenReturn(result); + when(inputValidation.validCustomerInfo(dto.getName(), dto.getEmail(), dto.getBlackList())).thenReturn(true); + + //when + Customer customer = customerService.create(dto); + + //then + Assertions.assertThat(customer).isEqualTo(result); + + } + + @Test + @DisplayName("service의 create()를 실행시 입력값 검증 실패로 RuntimeException 예외가 발생한다.") + void createCusteomerFail() { + //given + CreateCustomerDto dto = new CreateCustomerDto("kim", "won05121@naver.com", 12345); + when(inputValidation.validCustomerInfo(dto.getName(), dto.getEmail(), dto.getBlackList())) + .thenReturn(false); + + //when + //then + Assertions.assertThatThrownBy(() -> customerService.create(dto)). + isInstanceOf(RuntimeException.class); + } + + @Test + @DisplayName("service의 update()를 통해 repository의 update()가 정상적으로 실행된다.") + void updateCustomerSuccess() { + //given + UpdateCustomerDto dto = new UpdateCustomerDto("kim", "won05121@naver.com", 1); + when(inputValidation.validCustomerInfo(dto.getName(), dto.getEmail(), dto.getBlackList())).thenReturn(true); + + //when + customerService.update(1L, dto); + + //then + verify(customerRepsotiory, atLeast(1)).update(any(Customer.class)); + } + + @Test + @DisplayName("service의 update()를 통해 입력값 검증 실패시 RuntimeException예외가 발생한다.") + void updateCustomerFail() { + //given + UpdateCustomerDto dto = new UpdateCustomerDto("kim", "won05121@naver.com", 1); + when(inputValidation.validCustomerInfo(dto.getName(), dto.getEmail(), dto.getBlackList())).thenReturn(false); + + //when + //then + Assertions.assertThatThrownBy(() -> customerService.update(1L, dto)).isInstanceOf(RuntimeException.class); + + } + + @Test + @DisplayName("service의 findById()로 존재하는 ID가 들어오면 ,repository의 findById()는 성공적으로 값을 찾아온다. .") + void findByIdCustomerSuccess() { + //given + Customer customer = new Customer(1L, "kk", "kk@naver.com", true); + when(customerRepsotiory.findById(customer.getId())) + .thenReturn(Optional.ofNullable(customer)); + + //when + //then + Assertions.assertThat(customer).isEqualTo(customerService.findById(customer.getId())); + + } + + @Test + @DisplayName("service의 findById()의 인자로 존재하지 않는 ID가 들어오면 EmptyResultDataAccessException 예외가 발생한다 .") + void findByIdCustomerFail() { + //given + Long notExistId = 1L; + //when + when(customerRepsotiory.findById(any())).thenReturn(Optional.ofNullable(null)); + + //then + Assertions.assertThatThrownBy(() -> customerService.findById(notExistId)).isInstanceOf(EmptyResultDataAccessException.class); + + } + + @Test + @DisplayName("service의 findAll()을 통해 repository 의 findAll()실행시켜 성공적으로 값을 얻는다.") + void findAll() { + //given + List customers = List.of(new Customer(1L, "kk", "kk@naver.com", true)); + when(customerRepsotiory.findAll()).thenReturn(customers); + + //when + List customerList = customerService.findAll(); + + //then + Assertions.assertThat(customers).isEqualTo(customerList); + + } + + @Test + @DisplayName("service의 deleteById()의 인자와 상관없이, repository의 deleteById()는 반드시 한번은 실행된다.") + void deleteByIdSuccess() { + //given + //when + customerService.deleteById(null); + + //then + verify(customerRepsotiory, atLeastOnce()).deleteById(any()); + } + + @Test + @DisplayName("service의 deleteAll()을 통해 repository 의 deleteAll() 을 반드시 한번은 실행한다.") + void deleteAll() { + //given + //when + customerService.deleteAll(); + + //then + verify(customerRepsotiory, atLeastOnce()).deleteAll(); + } + + @Test + @DisplayName("service의 getBlackList()를 통해 repository의 getBlackList()을 실행시켜 성공적으로 값을 찾아온다.") + void getBlackList() { + //given + List blackList = List.of(new Customer(1L, "kk", "kk@naver.com", true)); + + //when + when(customerRepsotiory.findBlackList()).thenReturn(blackList); + + //then + Assertions.assertThat(blackList).isEqualTo(customerService.findBlackList()); + + } +} diff --git a/src/test/java/com/prgms/vouchermanager/service/voucher/VoucherServiceTest.java b/src/test/java/com/prgms/vouchermanager/service/voucher/VoucherServiceTest.java new file mode 100644 index 0000000000..796640ee1f --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/service/voucher/VoucherServiceTest.java @@ -0,0 +1,142 @@ +package com.prgms.vouchermanager.service.voucher; + +import com.prgms.vouchermanager.domain.voucher.FixedAmountVoucher; +import com.prgms.vouchermanager.domain.voucher.PercentDiscountVoucher; +import com.prgms.vouchermanager.domain.voucher.Voucher; +import com.prgms.vouchermanager.dto.CreateVoucherDto; +import com.prgms.vouchermanager.dto.UpdateVoucherDto; +import com.prgms.vouchermanager.repository.voucher.VoucherRepository; +import org.assertj.core.api.Assertions; +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.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.EmptyResultDataAccessException; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class VoucherServiceTest { + + @InjectMocks + VoucherService voucherService; + @Mock + private VoucherRepository voucherRepository; + + @Test + @DisplayName("service의 create()를 통해 repository의 save()를 정상 실행하고 값을 받아올 수 있다.") + void createVoucherSuccess() { + + //given + CreateVoucherDto dto = new CreateVoucherDto(99, 2); + UUID id = UUID.randomUUID(); + Voucher result = dto.getVoucherType() == 1 ? + new FixedAmountVoucher(id, dto.getValue(), LocalDateTime.now()) : + new PercentDiscountVoucher(id, dto.getValue(), LocalDateTime.now()); + + when(voucherRepository.save(any(Voucher.class))).thenReturn(result); + //when + Voucher voucher = voucherService.create(dto); + + //then + Assertions.assertThat(voucher).isEqualTo(result); + + } + + @Test + @DisplayName("service의 update()에서 repository의 update()가 정상적으로 실행된다.") + void updateUpdateSuccess() { + //given + UpdateVoucherDto dto = new UpdateVoucherDto(10, 2); + UUID id = UUID.randomUUID(); + + //when + voucherService.update(id, dto); + + //then + verify(voucherRepository, atLeastOnce()).update(any(Voucher.class)); + } + + @Test + @DisplayName("service의 update()에서 바우처타입 검증 실패시 RuntimeException예외가 발생한다.") + void updateVoucherFail() { + //given + UpdateVoucherDto dto = new UpdateVoucherDto(10000, 142124); + UUID id = UUID.randomUUID(); + + //when + //then + Assertions.assertThatThrownBy(() -> voucherService.update((id), dto)). + isInstanceOf(RuntimeException.class); + } + + @Test + @DisplayName("service의 findById()에 존재하는ID라면 ,repository의 findById()를 통해 정상 반환된다.") + void findByIdVoucherSuccess() { + //given + UUID id = UUID.randomUUID(); + Voucher voucher = new FixedAmountVoucher(id, 1000, LocalDateTime.now()); + when(voucherRepository.findById(id)).thenReturn(Optional.ofNullable(voucher)); + + //when + Voucher result = voucherService.findById(id); + + //then + Assertions.assertThat(id).isEqualTo(result.getId()); + + } + + @Test + @DisplayName("service의 findById()에 존재하지 않는 ID를 넘겨주면 , EmptyResultDataAccessException예외가 발생한다.") + void findByIdVoucherFail() { + //given + UUID id = UUID.randomUUID(); + when(voucherRepository.findById(id)).thenReturn(Optional.ofNullable(null)); + + Assertions.assertThatThrownBy(() -> voucherService.findById(id)).isInstanceOf(EmptyResultDataAccessException.class); + } + + @Test + @DisplayName("service의 findAll()을 성공적으로 실행해서 필요 데이터를 가져올 수 있다.") + void findAllSuccess() { + //given + List vouchers = List.of(new FixedAmountVoucher(UUID.randomUUID(), 100, LocalDateTime.now()), new PercentDiscountVoucher(UUID.randomUUID(), 22, LocalDateTime.now())); + when(voucherRepository.findAll()).thenReturn(vouchers); + + //when + List findAllVouchers = voucherService.findAll(); + + //then + Assertions.assertThat(findAllVouchers).isEqualTo(vouchers); + } + + @Test + @DisplayName("service의 deleteById()의 인자와 상관없이, repository의 deleteById()는 반드시 한번은 실행된다.") + void deleteByIdSuccess() { + + //given + //when + voucherService.deleteById(null); + + //then + verify(voucherRepository, atLeastOnce()).deleteById(any()); + } + + @Test + @DisplayName("service의 deleteAll()으로 repository 의 deleteAll()을 실행한다.") + void deleteAll() { + //given + //when + voucherService.deleteAll(); + + //then + verify(voucherRepository, atLeastOnce()).deleteAll(); + } +} diff --git a/src/test/java/com/prgms/vouchermanager/service/wallet/WalletServiceTest.java b/src/test/java/com/prgms/vouchermanager/service/wallet/WalletServiceTest.java new file mode 100644 index 0000000000..bb418de95b --- /dev/null +++ b/src/test/java/com/prgms/vouchermanager/service/wallet/WalletServiceTest.java @@ -0,0 +1,133 @@ +package com.prgms.vouchermanager.service.wallet; + +import com.prgms.vouchermanager.domain.wallet.Wallet; +import com.prgms.vouchermanager.dto.CreateWalletDto; +import com.prgms.vouchermanager.repository.wallet.WalletRepository; +import org.assertj.core.api.Assertions; +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.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.DataIntegrityViolationException; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class WalletServiceTest { + + @InjectMocks + WalletService walletService; + @Mock + private WalletRepository walletRepository; + + @Test + @DisplayName("service의 create()를 통해 repository의 save()를 정상 실행하고, 값을 받아올 수 있다.") + void createWalletSuccess() { + + //given + UUID voucherId = UUID.randomUUID(); + CreateWalletDto dto = new CreateWalletDto(1L, voucherId); + when(walletRepository.save(any(Wallet.class))).thenReturn(new Wallet(1L, 1L, voucherId)); + + //when + Wallet wallet = walletService.save(dto); + + //then + Assertions.assertThat(voucherId).isEqualTo(wallet.getVoucherId()); + + } + + @Test + @DisplayName("service의 create()를 통해 존재하지 않는 회원값,UUID쿠폰값을 입력하면 DataIntegrityViolationException예외를 터트린다. ") + void createWalletFail() { + //given + CreateWalletDto dto = new CreateWalletDto(1L, UUID.randomUUID()); + when(walletRepository.save(any())).thenThrow(DataIntegrityViolationException.class); + + //when + //then + Assertions.assertThatThrownBy(() -> walletService.save(dto)).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + @DisplayName("service의 findByCustomerId()를 통해 repository의 findByCustomerId()가 정상적으로 실행된다.") + void findByCustomerIdWalletSuccess() { + //given + Long customerId = 2L; + List wallets = List.of(new Wallet(1L, customerId, UUID.randomUUID())); + when(walletRepository.findByCustomerId(customerId)).thenReturn(wallets); + + //when + List byCustomerIdWallets = walletService.findByCustomerId(customerId); + + //then + Assertions.assertThat(wallets).isEqualTo(byCustomerIdWallets); + } + + @Test + @DisplayName("service의 findByCustomerId()실행시 존재하지 않는 customerId 입력시 DataIntegrityViolationException 예외를 터트린다. ") + void findByCustomerIdWalletFail() { + + //given + Long customerId = 2L; + + //when + when(walletRepository.findByCustomerId(customerId)).thenThrow(DataIntegrityViolationException.class); + + //then + Assertions.assertThatThrownBy(() -> walletService.findByCustomerId(customerId)).isInstanceOf(DataIntegrityViolationException.class); + + } + + @Test + @DisplayName("service의 findByVoucherId()를 통해 repository의 findByVoucherId()가 정상적으로 실행된다.") + void findByVoucherIdWalletSuccess() { + + //given + UUID voucherId = UUID.randomUUID(); + Wallet wallet = new Wallet(1L, 2L, voucherId); + when(walletRepository.findByVoucherId(voucherId)).thenReturn(Optional.of(wallet)); + + //when + Wallet byVoucherIdWallet = walletService.findByVoucherId(voucherId); + + //then + Assertions.assertThat(wallet).isEqualTo(byVoucherIdWallet); + } + + @Test + @DisplayName("service의 findByVoucherId()에 존재하지 않는 voucherId입력시 DataIntegrityViolationException 예외가 발생한다.") + void findByVoucherIdWalletFail() { + + //given + UUID voucherId = UUID.randomUUID(); + + //when + when(walletRepository.findByVoucherId(voucherId)).thenThrow(DataIntegrityViolationException.class); + + //then + Assertions.assertThatThrownBy(() -> walletService.findByVoucherId(voucherId)).isInstanceOf(DataIntegrityViolationException.class); + } + + @Test + @DisplayName("service의 deleteByCustomerId()를 통해 repository의 deleteByCustomerId()를 정상적으로 실행한다") + void deleteByCustomerId() { + + //given + Long customerId = 1L; + + //when + walletService.deleteByCustomerId(customerId); + + //then + verify(walletRepository, atLeastOnce()).deleteByCustomerId(customerId); + + } + +} diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml new file mode 100644 index 0000000000..3623cb01f5 --- /dev/null +++ b/src/test/resources/application.yaml @@ -0,0 +1,22 @@ +spring: + profiles: + active: jdbc + + datasource: + driverClassName: com.mysql.cj.jdbc.Driver + url : jdbc:mysql://127.0.0.1:3306/voucher?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul + username : yong + password : 1234 + + sql: + init: + mode: always + +file: + path: + voucher: src/test/resources/voucher_list.csv + blacklist: src/test/resources/customer_blackList.csv + + + +