diff --git a/Seoyeon/Mission/.gitignore b/Seoyeon/Mission/.gitignore new file mode 100644 index 0000000..2b1757d --- /dev/null +++ b/Seoyeon/Mission/.gitignore @@ -0,0 +1,39 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +application-secret.properties + +### 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/Seoyeon/Mission/build.gradle b/Seoyeon/Mission/build.gradle new file mode 100644 index 0000000..b7be612 --- /dev/null +++ b/Seoyeon/Mission/build.gradle @@ -0,0 +1,42 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.3.0' + id 'io.spring.dependency-management' version '1.1.5' +} + +group = 'umc' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + //swagger + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/Seoyeon/Mission/gradle/wrapper/gradle-wrapper.jar b/Seoyeon/Mission/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e644113 Binary files /dev/null and b/Seoyeon/Mission/gradle/wrapper/gradle-wrapper.jar differ diff --git a/Seoyeon/Mission/gradle/wrapper/gradle-wrapper.properties b/Seoyeon/Mission/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b82aa23 --- /dev/null +++ b/Seoyeon/Mission/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/Seoyeon/Mission/gradlew b/Seoyeon/Mission/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/Seoyeon/Mission/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=SC2039,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=SC2039,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, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +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/Seoyeon/Mission/gradlew.bat b/Seoyeon/Mission/gradlew.bat new file mode 100644 index 0000000..25da30d --- /dev/null +++ b/Seoyeon/Mission/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. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +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/Seoyeon/Mission/settings.gradle b/Seoyeon/Mission/settings.gradle new file mode 100644 index 0000000..e8a2b01 --- /dev/null +++ b/Seoyeon/Mission/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'practice' diff --git a/Seoyeon/Mission/src/main/java/umc/practice/PracticeApplication.java b/Seoyeon/Mission/src/main/java/umc/practice/PracticeApplication.java new file mode 100644 index 0000000..5289a7a --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/PracticeApplication.java @@ -0,0 +1,15 @@ +package umc.practice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@SpringBootApplication +@EnableJpaAuditing +public class PracticeApplication { + + public static void main(String[] args) { + SpringApplication.run(PracticeApplication.class, args); + } + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/ApiResponse.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/ApiResponse.java new file mode 100644 index 0000000..9800074 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/ApiResponse.java @@ -0,0 +1,28 @@ +package umc.practice.apiPayload; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Getter; +import umc.practice.apiPayload.code.status.SuccessStatus; + +@Getter +@AllArgsConstructor +@JsonPropertyOrder({"isSuccess","code","message","result"}) +public class ApiResponse { + @JsonProperty("isSuccess") + private final boolean isSuccess; + private final String code; + private final String message; + @JsonInclude(JsonInclude.Include.NON_NULL) + private T result; + + public static ApiResponse onSuccess(T result) { + return new ApiResponse<>(true, SuccessStatus._OK.getCode(),"success!",result); + } + + public static ApiResponse onFailure(String code, String message,T data) { + return new ApiResponse(false, code, message, data); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/BaseCode.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/BaseCode.java new file mode 100644 index 0000000..31df01a --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/BaseCode.java @@ -0,0 +1,8 @@ +package umc.practice.apiPayload.code; + +import java.awt.desktop.UserSessionEvent; + +public interface BaseCode { + public ReasonDTO getReason(); + public ReasonDTO getReasonHttpStatus(); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/BaseErrorCode.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/BaseErrorCode.java new file mode 100644 index 0000000..21e6a2c --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/BaseErrorCode.java @@ -0,0 +1,6 @@ +package umc.practice.apiPayload.code; + +public interface BaseErrorCode { + public ErrorReasonDTO getReason(); + public ErrorReasonDTO getReasonHttpStatus(); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/ErrorReasonDTO.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/ErrorReasonDTO.java new file mode 100644 index 0000000..9190740 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/ErrorReasonDTO.java @@ -0,0 +1,14 @@ +package umc.practice.apiPayload.code; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Builder +@Getter +public class ErrorReasonDTO { + private String code; + private String message; + private Boolean isSuccess; + private HttpStatus httpStatus; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/ReasonDTO.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/ReasonDTO.java new file mode 100644 index 0000000..1a8afa5 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/ReasonDTO.java @@ -0,0 +1,4 @@ +package umc.practice.apiPayload.code; + +public class ReasonDTO { +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/ExceptionAdvice.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/ExceptionAdvice.java new file mode 100644 index 0000000..08532ed --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/ExceptionAdvice.java @@ -0,0 +1,121 @@ +package umc.practice.apiPayload.code.exception; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import umc.practice.apiPayload.ApiResponse; +import umc.practice.apiPayload.code.ErrorReasonDTO; +import umc.practice.apiPayload.code.status.ErrorStatus; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@RestControllerAdvice(annotations = {RestController.class}) +public class ExceptionAdvice extends ResponseEntityExceptionHandler { + + + @org.springframework.web.bind.annotation.ExceptionHandler + public ResponseEntity validation(ConstraintViolationException e, WebRequest request) { + String errorMessage = e.getConstraintViolations().stream() + .map(constraintViolation -> constraintViolation.getMessage()) + .findFirst() + .orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생")); + + return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY,request); + } + + + @Override + public ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException e, HttpHeaders headers, HttpStatusCode status, WebRequest request) { + + Map errors = new LinkedHashMap<>(); + + e.getBindingResult().getFieldErrors().stream() + .forEach(fieldError -> { + String fieldName = fieldError.getField(); + String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse(""); + errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage); + }); + + return handleExceptionInternalArgs(e,HttpHeaders.EMPTY,ErrorStatus.valueOf("_BAD_REQUEST"),request,errors); + } + + @org.springframework.web.bind.annotation.ExceptionHandler + public ResponseEntity exception(Exception e, WebRequest request) { + e.printStackTrace(); + + return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(),request, e.getMessage()); + } + + @ExceptionHandler(value = GeneralException.class) + public ResponseEntity onThrowException(GeneralException generalException, HttpServletRequest request) { + ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus(); + return handleExceptionInternal(generalException,errorReasonHttpStatus,null,request); + } + + private ResponseEntity handleExceptionInternal(Exception e, ErrorReasonDTO reason, + HttpHeaders headers, HttpServletRequest request) { + + ApiResponse body = ApiResponse.onFailure(reason.getCode(),reason.getMessage(),null); +// e.printStackTrace(); + + WebRequest webRequest = new ServletWebRequest(request); + return super.handleExceptionInternal( + e, + body, + headers, + reason.getHttpStatus(), + webRequest + ); + } + + private ResponseEntity handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorPoint); + return super.handleExceptionInternal( + e, + body, + headers, + status, + request + ); + } + + private ResponseEntity handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus, + WebRequest request, Map errorArgs) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorArgs); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } + + private ResponseEntity handleExceptionInternalConstraint(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, WebRequest request) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/GeneralException.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/GeneralException.java new file mode 100644 index 0000000..51c6160 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/GeneralException.java @@ -0,0 +1,17 @@ +package umc.practice.apiPayload.code.exception; + +import lombok.AllArgsConstructor; +import umc.practice.apiPayload.code.BaseErrorCode; +import umc.practice.apiPayload.code.ErrorReasonDTO; + +@AllArgsConstructor +public class GeneralException extends RuntimeException{ + private BaseErrorCode code; + + public ErrorReasonDTO getErrorReason(){ + return this.code.getReason(); + } + public ErrorReasonDTO getErrorReasonHttpStatus(){ + return this.code.getReasonHttpStatus(); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/FoodCategoryHandler.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/FoodCategoryHandler.java new file mode 100644 index 0000000..2cf89f2 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/FoodCategoryHandler.java @@ -0,0 +1,10 @@ +package umc.practice.apiPayload.code.exception.handler; + +import umc.practice.apiPayload.code.BaseErrorCode; +import umc.practice.apiPayload.code.exception.GeneralException; + +public class FoodCategoryHandler extends GeneralException { + public FoodCategoryHandler(BaseErrorCode code) { + super(code); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/MissionHandler.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/MissionHandler.java new file mode 100644 index 0000000..77f43a5 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/MissionHandler.java @@ -0,0 +1,10 @@ +package umc.practice.apiPayload.code.exception.handler; + +import umc.practice.apiPayload.code.BaseErrorCode; +import umc.practice.apiPayload.code.exception.GeneralException; + +public class MissionHandler extends GeneralException { + public MissionHandler(BaseErrorCode code) { + super(code); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/TempHandler.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/TempHandler.java new file mode 100644 index 0000000..5e8c391 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/exception/handler/TempHandler.java @@ -0,0 +1,10 @@ +package umc.practice.apiPayload.code.exception.handler; + +import umc.practice.apiPayload.code.BaseErrorCode; +import umc.practice.apiPayload.code.exception.GeneralException; + +public class TempHandler extends GeneralException { + public TempHandler(BaseErrorCode errorCode) { + super(errorCode); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/status/ErrorStatus.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/status/ErrorStatus.java new file mode 100644 index 0000000..d021b35 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/status/ErrorStatus.java @@ -0,0 +1,69 @@ +package umc.practice.apiPayload.code.status; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; +import umc.practice.apiPayload.code.BaseErrorCode; +import umc.practice.apiPayload.code.ErrorReasonDTO; + +@Getter +@AllArgsConstructor +public enum ErrorStatus implements BaseErrorCode { + + //일반적인 exception + _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."), + _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), + + MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST,"MEMBER4001","사용자가 존재하지 않습니다"), + NICKNAME_NOT_EXISTS(HttpStatus.BAD_REQUEST,"MEMBER4002","닉네임은 필수입니다."), + + FOOD_CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND,"FOODCATEGORY4000","해당 카테고리가 존재하지 않습니다."), + + //지역 관련 + REGION_NOT_EXISTS(HttpStatus.NOT_FOUND,"REGION4000","해당 지역이 등록되어있지 않습니다."), + + //가게 관련 + STORE_NOT_EXISTS(HttpStatus.NOT_FOUND,"STORE4000","가게가 존재하지 않습니다"), + + //미션 관련 + MISSION_NOT_EXIST(HttpStatus.NOT_FOUND,"MISSION4000","해당 미션이 존재하지 않습니다."), + MISSION_DATE_NOT_VALID(HttpStatus.BAD_REQUEST,"MISSION4001","시작일과 마감일이 유효하지 않습니다."), + MEMBER_MISSION_DUPLICATED(HttpStatus.BAD_REQUEST,"MISSION4002","이미 도전중이거나 완료한 미션입니다"), + MEMBER_MISSION_NOT_FOUND(HttpStatus.NOT_FOUND,"MISSION4003","도전중인 미션 목록에 존재하지 않습니다"), + + //페이징 관련 + PAGE_NOT_VALID(HttpStatus.BAD_REQUEST,"PAGE4000","잘못된 페이지 번호입니다"), + + //테스트용 + TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "이거는 테스트") + ; + + // 멤버 관련 응답 + + // ~~~ 관련 응답 .... + + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + + + @Override + public ErrorReasonDTO getReason() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .build(); + } + + @Override + public ErrorReasonDTO getReasonHttpStatus() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .httpStatus(httpStatus) + .build(); } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/status/SuccessStatus.java b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/status/SuccessStatus.java new file mode 100644 index 0000000..daa624b --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/apiPayload/code/status/SuccessStatus.java @@ -0,0 +1,27 @@ +package umc.practice.apiPayload.code.status; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; +import umc.practice.apiPayload.code.BaseCode; +import umc.practice.apiPayload.code.ReasonDTO; +@Getter +@AllArgsConstructor +public enum SuccessStatus implements BaseCode { + + _OK(HttpStatus.OK,"2000","OK"); + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + @Override + public ReasonDTO getReason() { + return null; + } + + @Override + public ReasonDTO getReasonHttpStatus() { + return null; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/config/SwaggerConfig.java b/Seoyeon/Mission/src/main/java/umc/practice/config/SwaggerConfig.java new file mode 100644 index 0000000..8093257 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/config/SwaggerConfig.java @@ -0,0 +1,39 @@ +package umc.practice.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI UMCstudyAPI() { + Info info = new Info() + .title("UMC Server WorkBook API") + .description("UMC Server WorkBook API 명세서") + .version("1.0.0"); + + String jwtSchemeName = "JWT TOKEN"; + // API 요청헤더에 인증정보 포함 + SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName); + // SecuritySchemes 등록 + Components components = new Components() + .addSecuritySchemes(jwtSchemeName, new SecurityScheme() + .name(jwtSchemeName) + .type(SecurityScheme.Type.HTTP) // HTTP 방식 + .scheme("bearer") + .bearerFormat("JWT")); + + return new OpenAPI() + .addServersItem(new Server().url("/")) + .info(info) + .addSecurityItem(securityRequirement) + .components(components); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/converter/MemberConverter.java b/Seoyeon/Mission/src/main/java/umc/practice/converter/MemberConverter.java new file mode 100644 index 0000000..c292db6 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/converter/MemberConverter.java @@ -0,0 +1,26 @@ +package umc.practice.converter; + +import umc.practice.domain.Member; +import umc.practice.web.dto.MemberRequestDto; +import umc.practice.web.dto.MemberResponseDto; + +import java.util.ArrayList; + +public class MemberConverter { + public static MemberResponseDto.signUpResponseDto toMemberResponseDto(Member member) { + return MemberResponseDto.signUpResponseDto.builder() + .memberId(member.getId()) + .createdAt(member.getCreatedAt()) + .build(); + } + public static Member toMember(MemberRequestDto.signUpRequestDto requestDto) { + return Member.builder() + .name(requestDto.getName()) + .address(requestDto.getAddress()) + .gender(requestDto.getGender()) + .birthday(requestDto.getBirth()) + .memberFoodPreferList(new ArrayList<>()) + .build(); + } + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/converter/MemberFoodPreferConverter.java b/Seoyeon/Mission/src/main/java/umc/practice/converter/MemberFoodPreferConverter.java new file mode 100644 index 0000000..9d38f90 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/converter/MemberFoodPreferConverter.java @@ -0,0 +1,18 @@ +package umc.practice.converter; + +import umc.practice.domain.FoodCategory; +import umc.practice.domain.mapping.MemberFoodPrefer; + +import java.util.ArrayList; +import java.util.List; + +public class MemberFoodPreferConverter { + public static List toMemberFoodPreferList(List foodCategoryList){ + return foodCategoryList.stream() + .map(category->{ + return MemberFoodPrefer.builder() + .foodCategory(category) + .build(); + }).toList(); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/converter/MissionConverter.java b/Seoyeon/Mission/src/main/java/umc/practice/converter/MissionConverter.java new file mode 100644 index 0000000..454756d --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/converter/MissionConverter.java @@ -0,0 +1,69 @@ +package umc.practice.converter; + +import org.springframework.data.domain.Page; +import umc.practice.domain.Mission; +import umc.practice.domain.enums.MissionStatus; +import umc.practice.domain.mapping.MemberMission; +import umc.practice.web.dto.MissionRequestDto; +import umc.practice.web.dto.MissionResponseDto; + +import java.util.List; + +public class MissionConverter { + public static Mission toMission(MissionRequestDto.AddMissionRequestDto requestDto){ + return Mission.builder() + .reward(requestDto.getReward()) + .minimumPrice(requestDto.getMinimumPrice()) + .startDate(requestDto.getDateRange().getStartDate()) + .endDate(requestDto.getDateRange().getEndDate()) + .build(); + } + public static MissionResponseDto.AddMissionResponseDto toMissionResponseDto(Mission mission){ + return MissionResponseDto.AddMissionResponseDto.builder() + .missionId(mission.getId()) + .createdAt(mission.getCreatedAt()) + .build(); + } + public static MemberMission toNewMemberMission(){ + return MemberMission.builder() + .status(MissionStatus.CHALLENGING) + .build(); + } + public static MissionResponseDto.DoMissionResponseDto toDoMemberMissionDto(MemberMission memberMission){ + return MissionResponseDto.DoMissionResponseDto.builder() + .missionId(memberMission.getMission().getId()) + .id(memberMission.getId()) + .createdAt(memberMission.getCreatedAt()) + .build(); + } + public static MissionResponseDto.MissionPreview toMissionPreview(Mission mission){ + return MissionResponseDto.MissionPreview.builder() + .missionId(mission.getId()) + .storeName(mission.getStore().getStoreName()) + .reward(mission.getReward()) + .minimumPrice(mission.getMinimumPrice()) + .build(); + } + public static MissionResponseDto.MissionPreviewListDto toMissionListDto(Page missionList){ + List missionDtoList=missionList.stream() + .map(mission->{ + return toMissionPreview(mission); + }).toList(); + return MissionResponseDto.MissionPreviewListDto.builder() + .missionList(missionDtoList) + .listSize(missionDtoList.size()) + .isFirst(missionList.isFirst()) + .isLast(missionList.isLast()) + .totalPage(missionList.getTotalPages()) + .totalElement(missionList.getTotalElements()) + .build(); + } + public static MissionResponseDto.CompleteMissionResponseDto toCompleteMissionResponseDto(MemberMission memberMission){ + return MissionResponseDto.CompleteMissionResponseDto.builder() + .missionId(memberMission.getMission().getId()) + .missionStatus(memberMission.getStatus()) + .updatedAt(memberMission.getUpdatedAt()) + .build(); + } + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/converter/ReviewConverter.java b/Seoyeon/Mission/src/main/java/umc/practice/converter/ReviewConverter.java new file mode 100644 index 0000000..29daa6b --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/converter/ReviewConverter.java @@ -0,0 +1,46 @@ +package umc.practice.converter; + +import org.springframework.data.domain.Page; +import umc.practice.domain.Review; +import umc.practice.web.dto.StoreRequestDto; +import umc.practice.web.dto.StoreResponseDto; + +import java.util.List; + +public class ReviewConverter { + public static Review toReview(StoreRequestDto.WriteReviewRequestDto requestDto) { + return Review.builder() + .content(requestDto.getContent()) + .stars(requestDto.getStars()) + .build(); + } + public static StoreResponseDto.WriteReviewResponseDto toWriteReviewResponseDto(Review review) { + return StoreResponseDto.WriteReviewResponseDto.builder() + .reviewId(review.getId()) + .createdAt(review.getCreatedAt()) + .build(); + } + public static StoreResponseDto.ReviewPreview toReviewPreview(Review review) { + return StoreResponseDto.ReviewPreview.builder() + .writerName(review.getWriter().getName()) + .stars(review.getStars()) + .reviewId(review.getId()) + .content(review.getContent()) + .createdAt(review.getCreatedAt()) + .build(); + } + public static StoreResponseDto.ReviewPreviewListDto toReviewListDto(Page reviewList){ + List reviewDtoList=reviewList.stream() + .map(review->{ + return toReviewPreview(review); + }).toList(); + return StoreResponseDto.ReviewPreviewListDto.builder() + .reviewList(reviewDtoList) + .isFirst(reviewList.isFirst()) + .isLast(reviewList.isLast()) + .totalPage(reviewList.getTotalPages()) + .totalElement(reviewList.getTotalElements()) + .listSize(reviewDtoList.size()) + .build(); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/converter/StoreConverter.java b/Seoyeon/Mission/src/main/java/umc/practice/converter/StoreConverter.java new file mode 100644 index 0000000..26bb15d --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/converter/StoreConverter.java @@ -0,0 +1,20 @@ +package umc.practice.converter; + +import umc.practice.domain.Store; +import umc.practice.web.dto.StoreRequestDto; +import umc.practice.web.dto.StoreResponseDto; + +public class StoreConverter { + public static Store toStore(StoreRequestDto.AddStoreRequestDto requestDto) { + return Store.builder() + .storeName(requestDto.getStoreName()) + .address(requestDto.getAddress()) + .build(); + } + public static StoreResponseDto.addStoreResponseDto toStoreResponseDto(Store store) { + return StoreResponseDto.addStoreResponseDto.builder() + .storeId(store.getId()) + .createdAt(store.getCreatedAt()) + .build(); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/FoodCategory.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/FoodCategory.java new file mode 100644 index 0000000..d3851a8 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/FoodCategory.java @@ -0,0 +1,21 @@ +package umc.practice.domain; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import umc.practice.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FoodCategory extends BaseEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column(nullable = false) + private String name; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/Member.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/Member.java new file mode 100644 index 0000000..75e635f --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/Member.java @@ -0,0 +1,69 @@ +package umc.practice.domain; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import umc.practice.domain.common.BaseEntity; +import umc.practice.domain.enums.Gender; +import umc.practice.domain.enums.MemberStatus; +import umc.practice.domain.mapping.MemberFoodPrefer; +import umc.practice.domain.mapping.MemberMission; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@DynamicInsert +@DynamicUpdate +public class Member extends BaseEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @Column(nullable = false) + private String name; + + //@Column(nullable = false) + private String password; + + @Column(columnDefinition = "VARCHAR(10)") + @Enumerated(EnumType.STRING) + private Gender gender; + + private LocalDate birthday; + + @Column + private String address; + + //@Column(nullable = false) + private String email; + + @Enumerated(EnumType.STRING) + @Column(columnDefinition = "VARCHAR(15) DEFAULT 'ACTIVE'") + private MemberStatus status; + + @ColumnDefault("0") + private long points; + + private LocalDate inactivateDate; + + @OneToMany(mappedBy = "member",cascade = CascadeType.ALL) + private List memberMissionList=new ArrayList<>(); + + @OneToMany(mappedBy = "writer",cascade = CascadeType.ALL) + private List reviewList=new ArrayList<>(); + + @OneToMany(mappedBy = "member",cascade = CascadeType.ALL) + private List memberFoodPreferList=new ArrayList<>(); + + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/Mission.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/Mission.java new file mode 100644 index 0000000..1857387 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/Mission.java @@ -0,0 +1,51 @@ +package umc.practice.domain; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import umc.practice.domain.common.BaseEntity; +import umc.practice.domain.mapping.MemberMission; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Mission extends BaseEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private long reward; + + @Column + private long minimumPrice; + + @Column(nullable = false) + private LocalDate startDate; + + @Column(nullable = false) + private LocalDate endDate; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="store_id") + private Store store; + + @OneToMany(mappedBy = "mission",cascade = CascadeType.ALL) + private List memberMissionList=new ArrayList<>(); + + public void setStore(Store store) { + if(store!=null) + store.getMissionList().remove(this); + this.store = store; + if(store!=null) + store.getMissionList().add(this); + } + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/Region.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/Region.java new file mode 100644 index 0000000..1fc6c5d --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/Region.java @@ -0,0 +1,21 @@ +package umc.practice.domain; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import umc.practice.domain.common.BaseEntity; +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Region extends BaseEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String regionName; + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/Review.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/Review.java new file mode 100644 index 0000000..8613695 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/Review.java @@ -0,0 +1,51 @@ +package umc.practice.domain; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import umc.practice.domain.common.BaseEntity; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Review extends BaseEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private int stars; + + @Column(nullable = false) + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="writer_id") + private Member writer; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="store_id") + private Store store; + + public void setWriter(Member writer) { + if(writer!=null) + writer.getReviewList().remove(this); + this.writer = writer; + if(writer!=null) + writer.getReviewList().add(this); + } + public void setStore(Store store) { + if(store!=null) + store.getReviewList().remove(this); + this.store = store; + if(store!=null) + store.getReviewList().add(this); + } + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/Store.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/Store.java new file mode 100644 index 0000000..1360b2d --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/Store.java @@ -0,0 +1,42 @@ +package umc.practice.domain; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import umc.practice.domain.common.BaseEntity; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Store extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String storeName; + + @Column(nullable = false) + private String address; + + @ManyToOne(fetch=FetchType.LAZY) + private Region region; + + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + private List missionList=new ArrayList<>(); + + @OneToMany(mappedBy = "store",cascade = CascadeType.ALL) + private List reviewList=new ArrayList<>(); + + public void setRegion(Region region){ + this.region=region; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/common/BaseEntity.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/common/BaseEntity.java new file mode 100644 index 0000000..84bf9f5 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/common/BaseEntity.java @@ -0,0 +1,21 @@ +package umc.practice.domain.common; + +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public abstract class BaseEntity { + @CreatedDate + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime updatedAt; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/Gender.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/Gender.java new file mode 100644 index 0000000..526b72d --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/Gender.java @@ -0,0 +1,5 @@ +package umc.practice.domain.enums; + +public enum Gender { + MALE, FEMALE +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/MemberStatus.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/MemberStatus.java new file mode 100644 index 0000000..fe1458d --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/MemberStatus.java @@ -0,0 +1,5 @@ +package umc.practice.domain.enums; + +public enum MemberStatus { + ACTIVE, INACTIVE, DELETED +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/MissionStatus.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/MissionStatus.java new file mode 100644 index 0000000..1336324 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/enums/MissionStatus.java @@ -0,0 +1,5 @@ +package umc.practice.domain.enums; + +public enum MissionStatus { + CHALLENGING,COMPLETED +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/mapping/MemberFoodPrefer.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/mapping/MemberFoodPrefer.java new file mode 100644 index 0000000..74f82e7 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/mapping/MemberFoodPrefer.java @@ -0,0 +1,40 @@ +package umc.practice.domain.mapping; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import umc.practice.domain.FoodCategory; +import umc.practice.domain.Member; +import umc.practice.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberFoodPrefer extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="member_id") + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="food_category_id") + private FoodCategory foodCategory; + + public void setMember(Member member) { + if(member!=null) + member.getMemberFoodPreferList().remove(this); + this.member = member; + if(member!=null) + member.getMemberFoodPreferList().add(this); + } + public void setFoodCategory(FoodCategory foodCategory) { + this.foodCategory = foodCategory; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/domain/mapping/MemberMission.java b/Seoyeon/Mission/src/main/java/umc/practice/domain/mapping/MemberMission.java new file mode 100644 index 0000000..4d60619 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/domain/mapping/MemberMission.java @@ -0,0 +1,56 @@ +package umc.practice.domain.mapping; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import umc.practice.domain.Mission; +import umc.practice.domain.Member; +import umc.practice.domain.common.BaseEntity; +import umc.practice.domain.enums.MissionStatus; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@DynamicInsert +@DynamicUpdate +public class MemberMission extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(columnDefinition = "VARCHAR(15) DEFAULT 'CHALLENGING'") + @Enumerated(EnumType.STRING) + private MissionStatus status; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="member_id") + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="mission_id") + private Mission mission; + + public void setMember(Member member) { + if(member!=null) + member.getMemberMissionList().remove(this); + this.member=member; + if(member!=null) + member.getMemberMissionList().add(this); + } + public void setMission(Mission mission) { + if(mission!=null) + mission.getMemberMissionList().remove(this); + this.mission=mission; + if(mission!=null) + mission.getMemberMissionList().add(this); + } + public void changeStatus(MissionStatus status) { + this.status=status; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/repository/FoodCategoryRepository.java b/Seoyeon/Mission/src/main/java/umc/practice/repository/FoodCategoryRepository.java new file mode 100644 index 0000000..4d29c19 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/repository/FoodCategoryRepository.java @@ -0,0 +1,7 @@ +package umc.practice.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.practice.domain.FoodCategory; + +public interface FoodCategoryRepository extends JpaRepository { +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/repository/MemberMissionRepository.java b/Seoyeon/Mission/src/main/java/umc/practice/repository/MemberMissionRepository.java new file mode 100644 index 0000000..2418883 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/repository/MemberMissionRepository.java @@ -0,0 +1,12 @@ +package umc.practice.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import umc.practice.domain.Member; +import umc.practice.domain.Mission; +import umc.practice.domain.mapping.MemberMission; +@Repository +public interface MemberMissionRepository extends JpaRepository { + boolean existsByMissionIdAndMemberId(Long missionId, Long memberId); + MemberMission findByMissionIdAndMemberId(Long missionId, Long memberId); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/repository/MemberRepository.java b/Seoyeon/Mission/src/main/java/umc/practice/repository/MemberRepository.java new file mode 100644 index 0000000..8a58c01 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/repository/MemberRepository.java @@ -0,0 +1,7 @@ +package umc.practice.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.practice.domain.Member; + +public interface MemberRepository extends JpaRepository { +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/repository/MissionRepository.java b/Seoyeon/Mission/src/main/java/umc/practice/repository/MissionRepository.java new file mode 100644 index 0000000..3427aec --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/repository/MissionRepository.java @@ -0,0 +1,14 @@ +package umc.practice.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; +import umc.practice.domain.Mission; +import umc.practice.domain.Store; + +import java.util.List; + +public interface MissionRepository extends JpaRepository { + public Page findAllByStore(Store store, PageRequest pageRequest); + public Page findAllByIdIn(List ids, PageRequest pageRequest); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/repository/RegionRepository.java b/Seoyeon/Mission/src/main/java/umc/practice/repository/RegionRepository.java new file mode 100644 index 0000000..721831e --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/repository/RegionRepository.java @@ -0,0 +1,9 @@ +package umc.practice.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.practice.domain.Region; + +public interface RegionRepository extends JpaRepository { + public Region findByRegionName(String regionName); + public Boolean existsByRegionName(String regionName); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/repository/ReviewRepository.java b/Seoyeon/Mission/src/main/java/umc/practice/repository/ReviewRepository.java new file mode 100644 index 0000000..a32c207 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/repository/ReviewRepository.java @@ -0,0 +1,14 @@ +package umc.practice.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import umc.practice.domain.Member; +import umc.practice.domain.Review; +import umc.practice.domain.Store; +@Repository +public interface ReviewRepository extends JpaRepository { + Page findAllByStore(Store store, PageRequest pageRequest); + Page findAllByWriter(Member member, PageRequest pageRequest); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/repository/StoreRepository.java b/Seoyeon/Mission/src/main/java/umc/practice/repository/StoreRepository.java new file mode 100644 index 0000000..d940154 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/repository/StoreRepository.java @@ -0,0 +1,8 @@ +package umc.practice.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.practice.domain.Store; + +public interface StoreRepository extends JpaRepository { + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/FoodCategoryQueryService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/FoodCategoryQueryService.java new file mode 100644 index 0000000..1caa8b8 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/FoodCategoryQueryService.java @@ -0,0 +1,5 @@ +package umc.practice.service; + +public interface FoodCategoryQueryService { + public boolean existsCategory(Long id); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/FoodCategoryQueryServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/FoodCategoryQueryServiceImpl.java new file mode 100644 index 0000000..6c2a6a0 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/FoodCategoryQueryServiceImpl.java @@ -0,0 +1,17 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.practice.repository.FoodCategoryRepository; + +@RequiredArgsConstructor +@Service +@Transactional +public class FoodCategoryQueryServiceImpl implements FoodCategoryQueryService{ + private final FoodCategoryRepository foodCategoryRepository; + @Override + public boolean existsCategory(Long id) { + return foodCategoryRepository.existsById(id); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MemberCommandService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberCommandService.java new file mode 100644 index 0000000..28a10df --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberCommandService.java @@ -0,0 +1,8 @@ +package umc.practice.service; + +import umc.practice.domain.Member; +import umc.practice.web.dto.MemberRequestDto; + +public interface MemberCommandService { + public Member signUp(MemberRequestDto.signUpRequestDto requestDto); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MemberCommandServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberCommandServiceImpl.java new file mode 100644 index 0000000..f440bb8 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberCommandServiceImpl.java @@ -0,0 +1,42 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import umc.practice.converter.MemberConverter; +import umc.practice.converter.MemberFoodPreferConverter; +import umc.practice.domain.FoodCategory; +import umc.practice.domain.Member; +import umc.practice.domain.mapping.MemberFoodPrefer; +import umc.practice.repository.FoodCategoryRepository; +import umc.practice.repository.MemberRepository; +import umc.practice.web.dto.MemberRequestDto; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Transactional +public class MemberCommandServiceImpl implements MemberCommandService{ + @Autowired + private MemberRepository memberRepository; + @Autowired + private FoodCategoryRepository foodCategoryRepository; + + @Override + @Transactional + public Member signUp(MemberRequestDto.signUpRequestDto requestDto) { + Member member= MemberConverter.toMember(requestDto); + + List foodCategoryList=requestDto.getFavorList().stream() //foodCategory id를 가지고 FoodCategory list 생성 + .map(category->{ + return foodCategoryRepository.findById(category).get(); + }).toList(); + + List memberFoodPreferList= MemberFoodPreferConverter.toMemberFoodPreferList(foodCategoryList); + memberFoodPreferList.forEach(memberFoodPrefer -> {memberFoodPrefer.setMember(member);}); //member 와의 양방향 매핑관계 설정 + return memberRepository.save(member); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MemberQueryService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberQueryService.java new file mode 100644 index 0000000..d66ef65 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberQueryService.java @@ -0,0 +1,5 @@ +package umc.practice.service; + +public interface MemberQueryService { + public boolean existById(Long id); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MemberQueryServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberQueryServiceImpl.java new file mode 100644 index 0000000..7f736e1 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MemberQueryServiceImpl.java @@ -0,0 +1,17 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.practice.repository.MemberRepository; + +@Service +@Transactional +@RequiredArgsConstructor +public class MemberQueryServiceImpl implements MemberQueryService { + private final MemberRepository memberRepository; + @Override + public boolean existById(Long id) { + return memberRepository.existsById(id); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MissionCommandService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionCommandService.java new file mode 100644 index 0000000..c66e263 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionCommandService.java @@ -0,0 +1,12 @@ +package umc.practice.service; + +import umc.practice.domain.Mission; +import umc.practice.domain.mapping.MemberMission; +import umc.practice.web.dto.MissionRequestDto; + +public interface MissionCommandService { + public Mission addMission(MissionRequestDto.AddMissionRequestDto requestDto); + public MemberMission doMission(MissionRequestDto.DoMissionRequestDto requestDto); + public boolean checkMissionChallenging(Long missionId,Long memberId); + public MemberMission completeMission(MissionRequestDto.CompleteMissionRequestDto requestDto); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MissionCommandServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionCommandServiceImpl.java new file mode 100644 index 0000000..d6838f8 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionCommandServiceImpl.java @@ -0,0 +1,65 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.practice.converter.MissionConverter; +import umc.practice.domain.Member; +import umc.practice.domain.Mission; +import umc.practice.domain.Store; +import umc.practice.domain.enums.MissionStatus; +import umc.practice.domain.mapping.MemberMission; +import umc.practice.repository.MemberMissionRepository; +import umc.practice.repository.MemberRepository; +import umc.practice.repository.MissionRepository; +import umc.practice.repository.StoreRepository; +import umc.practice.web.dto.MissionRequestDto; + +@Service +@RequiredArgsConstructor +@Transactional +public class MissionCommandServiceImpl implements MissionCommandService{ + private final MissionRepository missionRepository; + private final StoreRepository storeRepository; + private final MemberRepository memberRepository; + private final MemberMissionRepository memberMissionRepository; + + @Override + public Mission addMission(MissionRequestDto.AddMissionRequestDto requestDto) { + Mission mission= MissionConverter.toMission(requestDto); + Store store = storeRepository.findById(requestDto.getStoreId()).get(); + mission.setStore(store); + + return missionRepository.save(mission); + } + + @Override + public MemberMission doMission(MissionRequestDto.DoMissionRequestDto requestDto) { + Member member=memberRepository.findById(requestDto.getMemberMission().getMemberId()).get(); + Mission mission=missionRepository.findById(requestDto.getMemberMission().getMissionId()).get(); + + MemberMission memberMission=MissionConverter.toNewMemberMission(); //memberMission 객체 생성 + + memberMission.setMember(member); //memberMission 객체에 member 설정하기 + memberMission.setMission(mission); + +// missionRepository.save(mission); //mission 저장(업데이트) -> memberMission 저장됨!! +// memberRepository.save(member); //member 저장(업데이트) + //return memberMissionRepository.save(memberMission); + return memberMission; + } + + @Override + public boolean checkMissionChallenging(Long missionId, Long memberId) { + return memberMissionRepository.existsByMissionIdAndMemberId(missionId,memberId); + } + + @Override + public MemberMission completeMission(MissionRequestDto.CompleteMissionRequestDto requestDto) { + MemberMission memberMission=memberMissionRepository.findByMissionIdAndMemberId(requestDto.getCompleteMemberMission().getMissionId(), requestDto.getCompleteMemberMission().getMemberId()); + memberMission.changeStatus(MissionStatus.COMPLETED); + return memberMission; + } + + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MissionQueryService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionQueryService.java new file mode 100644 index 0000000..4f3d866 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionQueryService.java @@ -0,0 +1,11 @@ +package umc.practice.service; + +import org.springframework.data.domain.Page; +import umc.practice.domain.Mission; +import umc.practice.domain.Store; + +public interface MissionQueryService { + public Page getMissionList(Long storeId, int page); + public Page getChallengingMissionList(Long memberId, int page); + public boolean existMemberMission(Long memberId, Long missionId); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/MissionQueryServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionQueryServiceImpl.java new file mode 100644 index 0000000..99f906e --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/MissionQueryServiceImpl.java @@ -0,0 +1,59 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import umc.practice.domain.Member; +import umc.practice.domain.Mission; +import umc.practice.domain.Store; +import umc.practice.domain.enums.MissionStatus; +import umc.practice.domain.mapping.MemberMission; +import umc.practice.repository.MemberMissionRepository; +import umc.practice.repository.MemberRepository; +import umc.practice.repository.MissionRepository; + +import java.util.ArrayList; +import java.util.List; + +@RequiredArgsConstructor +@Service +@Transactional +public class MissionQueryServiceImpl implements MissionQueryService{ + private final MissionRepository missionRepository; + private final StoreQueryService storeQueryService; + private final MemberRepository memberRepository; + private final MemberMissionRepository memberMissionRepository; + + @Override + public Page getMissionList(Long storeId, int page) { + Store store=storeQueryService.findById(storeId).get(); + return missionRepository.findAllByStore(store, PageRequest.of(page,10)); + } + + @Override + public Page getChallengingMissionList(Long memberId, int page) { + Member member=memberRepository.findById(memberId).get(); + List memberMissionList=member.getMemberMissionList(); + List missionList=memberMissionList.stream() + .filter(memberMission->memberMission.getStatus() == MissionStatus.CHALLENGING) + .map(memberMission-> { + return memberMission.getMission(); + }).toList(); + + PageRequest pageRequest=PageRequest.of(page,10); + int start=(int)pageRequest.getOffset(); + int end=Math.min(start+pageRequest.getPageSize(),missionList.size()); + List missionSubList=missionList.subList(start,end); + + return new PageImpl<>(missionSubList,pageRequest,missionList.size()); + } + + @Override + public boolean existMemberMission(Long memberId, Long missionId) { + return memberMissionRepository.existsByMissionIdAndMemberId(missionId,memberId); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/RegionQueryService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/RegionQueryService.java new file mode 100644 index 0000000..fd5ff78 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/RegionQueryService.java @@ -0,0 +1,5 @@ +package umc.practice.service; + +public interface RegionQueryService { + public boolean existsByName(String regionName); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/RegionQueryServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/RegionQueryServiceImpl.java new file mode 100644 index 0000000..4b9ddd4 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/RegionQueryServiceImpl.java @@ -0,0 +1,17 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.practice.repository.RegionRepository; + +@Service +@Transactional +@RequiredArgsConstructor +public class RegionQueryServiceImpl implements RegionQueryService{ + private final RegionRepository regionRepository; + @Override + public boolean existsByName(String regionName) { + return regionRepository.existsByRegionName(regionName); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/StoreCommandService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreCommandService.java new file mode 100644 index 0000000..89fe352 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreCommandService.java @@ -0,0 +1,11 @@ +package umc.practice.service; + +import umc.practice.domain.Region; +import umc.practice.domain.Review; +import umc.practice.domain.Store; +import umc.practice.web.dto.StoreRequestDto; + +public interface StoreCommandService { + public Store addStore(StoreRequestDto.AddStoreRequestDto requestDto); + public Review writeReview(StoreRequestDto.WriteReviewRequestDto request); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/StoreCommandServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreCommandServiceImpl.java new file mode 100644 index 0000000..561ca71 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreCommandServiceImpl.java @@ -0,0 +1,46 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.practice.converter.ReviewConverter; +import umc.practice.converter.StoreConverter; +import umc.practice.domain.Member; +import umc.practice.domain.Region; +import umc.practice.domain.Review; +import umc.practice.domain.Store; +import umc.practice.repository.MemberRepository; +import umc.practice.repository.RegionRepository; +import umc.practice.repository.ReviewRepository; +import umc.practice.repository.StoreRepository; +import umc.practice.web.dto.StoreRequestDto; + +@Service +@RequiredArgsConstructor +@Transactional +public class StoreCommandServiceImpl implements StoreCommandService{ + private final RegionRepository regionRepository; + private final StoreRepository storeRepository; + private final MemberRepository memberRepository; + private final ReviewRepository reviewRepository; + + @Override + public Store addStore(StoreRequestDto.AddStoreRequestDto requestDto) { + Store store= StoreConverter.toStore(requestDto); + Region region=regionRepository.findByRegionName(requestDto.getRegion()); //region 설정 + store.setRegion(region); + return storeRepository.save(store); + } + + @Override + public Review writeReview(StoreRequestDto.WriteReviewRequestDto request) { + Review review= ReviewConverter.toReview(request); + + Member writer = memberRepository.findById(request.getWriterId()).get(); + Store store = storeRepository.findById(request.getStoreId()).get(); + review.setStore(store); + review.setWriter(writer); + + return reviewRepository.save(review); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/StoreQueryService.java b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreQueryService.java new file mode 100644 index 0000000..83aa375 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreQueryService.java @@ -0,0 +1,14 @@ +package umc.practice.service; + +import org.springframework.data.domain.Page; +import umc.practice.domain.Review; +import umc.practice.domain.Store; + +import java.util.Optional; + +public interface StoreQueryService { + public boolean existsById(Long id); + public Optional findById(Long id); + Page getReviewList(Long storeId, int page); + Page getMemberReviewList(Long memberId,int page); +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/service/StoreQueryServiceImpl.java b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreQueryServiceImpl.java new file mode 100644 index 0000000..9bfde00 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/service/StoreQueryServiceImpl.java @@ -0,0 +1,47 @@ +package umc.practice.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import umc.practice.domain.Member; +import umc.practice.domain.Review; +import umc.practice.domain.Store; +import umc.practice.repository.MemberRepository; +import umc.practice.repository.ReviewRepository; +import umc.practice.repository.StoreRepository; + +import java.util.Optional; + +@RequiredArgsConstructor +@Service +@Transactional +public class StoreQueryServiceImpl implements StoreQueryService { + private final StoreRepository storeRepository; + private final ReviewRepository reviewRepository; + private final MemberRepository memberRepository; + + @Override + public boolean existsById(Long id) { + return storeRepository.existsById(id); + } + + @Override + public Optional findById(Long id) { + return storeRepository.findById(id); + } + + @Override + public Page getReviewList(Long storeId, int page) { + Store store=findById(storeId).get(); + return reviewRepository.findAllByStore(store, PageRequest.of(page,10)); + } + + @Override + public Page getMemberReviewList(Long memberId, int page) { + Member member=memberRepository.findById(memberId).get(); + return reviewRepository.findAllByWriter(member,PageRequest.of(page,10)); + } + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/CheckPage.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/CheckPage.java new file mode 100644 index 0000000..baadb87 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/CheckPage.java @@ -0,0 +1,17 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.CheckPageValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = CheckPageValidator.class) +@Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface CheckPage { + String message() default "페이지 번호가 적절하지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistCategories.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistCategories.java new file mode 100644 index 0000000..96105c0 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistCategories.java @@ -0,0 +1,17 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.CategoriesExistValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = CategoriesExistValidator.class) +@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistCategories { + String message() default "해당하는 카테고리가 존재하지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistMember.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistMember.java new file mode 100644 index 0000000..b05d017 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistMember.java @@ -0,0 +1,17 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.MemberExistsValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = MemberExistsValidator.class) +@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistMember { + String message() default "멤버가 존재하지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistMission.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistMission.java new file mode 100644 index 0000000..1dd2522 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistMission.java @@ -0,0 +1,17 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.MissionExistsValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = MissionExistsValidator.class ) +@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistMission { + String message() default "미션이 존재하지 않습니다"; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistRegion.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistRegion.java new file mode 100644 index 0000000..423b3e5 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistRegion.java @@ -0,0 +1,18 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.CategoriesExistValidator; +import umc.practice.validation.validator.RegionExistValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = RegionExistValidator.class) +@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistRegion { + String message() default "해당하는 지역이 등록되어있지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistStore.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistStore.java new file mode 100644 index 0000000..485f435 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistStore.java @@ -0,0 +1,17 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.StoreExistsValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = StoreExistsValidator.class) +@Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistStore { + String message() default "가게가 존재하지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistsMemberMission.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistsMemberMission.java new file mode 100644 index 0000000..c26d27d --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ExistsMemberMission.java @@ -0,0 +1,17 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.MemberMissionExistsValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = MemberMissionExistsValidator.class) +@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistsMemberMission { + String message() default "진행중인 미션 목록에 존재하지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/NotExistsMemberMission.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/NotExistsMemberMission.java new file mode 100644 index 0000000..b3e6975 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/NotExistsMemberMission.java @@ -0,0 +1,17 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.MemberMissionNotExistValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = MemberMissionNotExistValidator.class) +@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface NotExistsMemberMission { + String message() default "미션이 이미 도전중이거나 완료하였습니다"; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ValidMissionDate.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ValidMissionDate.java new file mode 100644 index 0000000..b522c36 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/annotation/ValidMissionDate.java @@ -0,0 +1,18 @@ +package umc.practice.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import umc.practice.validation.validator.MissionDateValidator; + +import java.lang.annotation.*; +import java.time.LocalDate; + +@Documented +@Constraint(validatedBy = MissionDateValidator.class) +@Target({ElementType.TYPE,ElementType.PARAMETER,ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidMissionDate { + String message() default "유효하지 않은 날짜입니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/CategoriesExistValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/CategoriesExistValidator.java new file mode 100644 index 0000000..674a12a --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/CategoriesExistValidator.java @@ -0,0 +1,33 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.repository.FoodCategoryRepository; +import umc.practice.service.FoodCategoryQueryService; +import umc.practice.validation.annotation.ExistCategories; + +import java.util.List; +@Component +@RequiredArgsConstructor +public class CategoriesExistValidator implements ConstraintValidator> { + private final FoodCategoryQueryService foodCategoryQueryService; + + @Override + public void initialize(ExistCategories constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(List values, ConstraintValidatorContext constraintValidatorContext) { + boolean isValid=values.stream() + .allMatch(value->foodCategoryQueryService.existsCategory(value)); + if(!isValid){ + constraintValidatorContext.disableDefaultConstraintViolation(); + constraintValidatorContext.buildConstraintViolationWithTemplate(ErrorStatus.FOOD_CATEGORY_NOT_FOUND.toString()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/CheckPageValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/CheckPageValidator.java new file mode 100644 index 0000000..782d33b --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/CheckPageValidator.java @@ -0,0 +1,24 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.validation.annotation.CheckPage; + +public class CheckPageValidator implements ConstraintValidator { + @Override + public void initialize(CheckPage constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Integer page, ConstraintValidatorContext context) { + boolean isValid=page>=0; + + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.PAGE_NOT_VALID.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberExistsValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberExistsValidator.java new file mode 100644 index 0000000..f11b97e --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberExistsValidator.java @@ -0,0 +1,30 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.repository.MemberRepository; +import umc.practice.service.MemberQueryService; +import umc.practice.validation.annotation.ExistMember; + +@Component +@RequiredArgsConstructor +public class MemberExistsValidator implements ConstraintValidator { + private final MemberQueryService memberQueryService; + @Override + public void initialize(ExistMember constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Long id, ConstraintValidatorContext context) { + boolean isValid= memberQueryService.existById(id); + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.MEMBER_NOT_FOUND.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberMissionExistsValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberMissionExistsValidator.java new file mode 100644 index 0000000..155fc12 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberMissionExistsValidator.java @@ -0,0 +1,30 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.service.MissionCommandService; +import umc.practice.service.MissionQueryService; +import umc.practice.validation.annotation.ExistsMemberMission; +import umc.practice.web.dto.MissionRequestDto; +@Component +@RequiredArgsConstructor +public class MemberMissionExistsValidator implements ConstraintValidator { + private final MissionQueryService missionQueryService; + @Override + public void initialize(ExistsMemberMission constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(MissionRequestDto.CompleteMemberMissionDto completeMemberMissionDto, ConstraintValidatorContext context) { + boolean isValid= missionQueryService.existMemberMission(completeMemberMissionDto.getMemberId(), completeMemberMissionDto.getMissionId()); + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.MEMBER_NOT_FOUND.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberMissionNotExistValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberMissionNotExistValidator.java new file mode 100644 index 0000000..2287405 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MemberMissionNotExistValidator.java @@ -0,0 +1,29 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.service.MissionCommandService; +import umc.practice.validation.annotation.NotExistsMemberMission; +import umc.practice.web.dto.MissionRequestDto; +@Component +@RequiredArgsConstructor +public class MemberMissionNotExistValidator implements ConstraintValidator { + private final MissionCommandService missionCommandService; + @Override + public void initialize(NotExistsMemberMission constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(MissionRequestDto.MemberMissionDto memberMissionDto, ConstraintValidatorContext context) { + boolean isValid= !missionCommandService.checkMissionChallenging(memberMissionDto.getMissionId(), memberMissionDto.getMemberId()); + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.MEMBER_MISSION_DUPLICATED.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MissionDateValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MissionDateValidator.java new file mode 100644 index 0000000..62ce249 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MissionDateValidator.java @@ -0,0 +1,36 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.validation.annotation.ValidMissionDate; +import umc.practice.web.dto.MissionRequestDto; + +import java.time.LocalDate; + + +@RequiredArgsConstructor +@Component +public class MissionDateValidator implements ConstraintValidator { + + @Override + public void initialize(ValidMissionDate constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(MissionRequestDto.DateRangeDto dateRangeDto, ConstraintValidatorContext constraintValidatorContext) { + LocalDate startDate = dateRangeDto.getStartDate(); + LocalDate endDate = dateRangeDto.getEndDate(); + boolean isValid=startDate.isBefore(endDate) || startDate.isEqual(endDate); + if(!isValid){ + constraintValidatorContext.disableDefaultConstraintViolation(); + constraintValidatorContext.buildConstraintViolationWithTemplate(ErrorStatus.MISSION_DATE_NOT_VALID.getMessage()).addConstraintViolation(); + } + return isValid; + } + + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MissionExistsValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MissionExistsValidator.java new file mode 100644 index 0000000..9ec66cd --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/MissionExistsValidator.java @@ -0,0 +1,29 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.repository.MissionRepository; +import umc.practice.validation.annotation.ExistMission; + +@Component +@RequiredArgsConstructor +public class MissionExistsValidator implements ConstraintValidator { + private final MissionRepository missionRepository; + @Override + public void initialize(ExistMission constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Long missionId, ConstraintValidatorContext context) { + boolean isValid= missionRepository.existsById(missionId); + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.MISSION_NOT_EXIST.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/RegionExistValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/RegionExistValidator.java new file mode 100644 index 0000000..3329a5c --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/RegionExistValidator.java @@ -0,0 +1,31 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.repository.RegionRepository; +import umc.practice.service.RegionQueryService; +import umc.practice.validation.annotation.ExistRegion; + +@Component +@RequiredArgsConstructor +public class RegionExistValidator implements ConstraintValidator { + private final RegionQueryService regionQueryService; + + @Override + public void initialize(ExistRegion constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(String regionName, ConstraintValidatorContext context) { + boolean isValid= regionQueryService.existsByName(regionName); + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.REGION_NOT_EXISTS.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/StoreExistsValidator.java b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/StoreExistsValidator.java new file mode 100644 index 0000000..2db25e4 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/validation/validator/StoreExistsValidator.java @@ -0,0 +1,31 @@ +package umc.practice.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import umc.practice.apiPayload.code.status.ErrorStatus; +import umc.practice.repository.StoreRepository; +import umc.practice.service.StoreQueryService; +import umc.practice.validation.annotation.ExistStore; + +@Component +@RequiredArgsConstructor +public class StoreExistsValidator implements ConstraintValidator { + private final StoreQueryService storeQueryService; + + @Override + public void initialize(ExistStore constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Long storeId, ConstraintValidatorContext context) { + boolean isValid=storeQueryService.existsById(storeId); + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.STORE_NOT_EXISTS.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/controller/MemberController.java b/Seoyeon/Mission/src/main/java/umc/practice/web/controller/MemberController.java new file mode 100644 index 0000000..eab5d2a --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/controller/MemberController.java @@ -0,0 +1,27 @@ +package umc.practice.web.controller; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import umc.practice.apiPayload.ApiResponse; +import umc.practice.converter.MemberConverter; +import umc.practice.domain.Member; +import umc.practice.service.MemberCommandService; +import umc.practice.web.dto.MemberRequestDto; +import umc.practice.web.dto.MemberResponseDto; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/members") +public class MemberController { + + public final MemberCommandService memberCommandService; + @PostMapping("/sign-up") + public ApiResponse signUp(@RequestBody @Valid MemberRequestDto.signUpRequestDto request){ + Member member=memberCommandService.signUp(request); + return ApiResponse.onSuccess(MemberConverter.toMemberResponseDto(member)); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/controller/MissionController.java b/Seoyeon/Mission/src/main/java/umc/practice/web/controller/MissionController.java new file mode 100644 index 0000000..c2a8837 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/controller/MissionController.java @@ -0,0 +1,100 @@ +package umc.practice.web.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; +import umc.practice.apiPayload.ApiResponse; +import umc.practice.converter.MissionConverter; +import umc.practice.domain.Mission; +import umc.practice.domain.mapping.MemberMission; +import umc.practice.service.MissionCommandService; +import umc.practice.service.MissionQueryService; +import umc.practice.validation.annotation.CheckPage; +import umc.practice.validation.annotation.ExistMember; +import umc.practice.validation.annotation.ExistStore; +import umc.practice.web.dto.MissionRequestDto; +import umc.practice.web.dto.MissionResponseDto; + + +@RestController +@RequiredArgsConstructor +@Slf4j +@RequestMapping("/missions") +public class MissionController { + private final MissionCommandService missionCommandService; + private final MissionQueryService missionQueryService; + + @PostMapping("/store") + public ApiResponse addMission( + @RequestBody @Valid MissionRequestDto.AddMissionRequestDto requestDto) { + Mission mission=missionCommandService.addMission(requestDto); + return ApiResponse.onSuccess(MissionConverter.toMissionResponseDto(mission)); + } + + @PostMapping("/member") + public ApiResponse doMission(@RequestBody @Valid MissionRequestDto.DoMissionRequestDto requestDto){ + MemberMission memberMission=missionCommandService.doMission(requestDto); + return ApiResponse.onSuccess(MissionConverter.toDoMemberMissionDto(memberMission)); + } + + @GetMapping("/stores/{storeId}") + @Operation(summary = "특정 가게의 미션 목록 조회 api",description = "query string으로 page 번호를 주세요") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH003", description = "access 토큰을 주세요!",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "acess 토큰 만료",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "acess 토큰 모양이 이상함",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + @Parameters({ + @Parameter(name = "storeId",description = "가게의 id, path variable입니다."), + @Parameter(name="page",description = "페이지번호, 0번이 1페이지입니다.") + }) + public ApiResponse getMissionList( + @ExistStore @PathVariable(name="storeId") Long storeId, + @CheckPage @RequestParam(name="page") int page + ){ + Page missionPage=missionQueryService.getMissionList(storeId,page); + return ApiResponse.onSuccess(MissionConverter.toMissionListDto(missionPage)); + } + @GetMapping("/member/{memberId}") + @Operation(summary = "특정 멤버가 진행중인 미션 목록 조회 api",description = "query string으로 page 번호를 주세요") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH003", description = "access 토큰을 주세요!",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "acess 토큰 만료",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "acess 토큰 모양이 이상함",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + @Parameters({ + @Parameter(name = "memberId",description = "사용자의 id, path variable입니다."), + @Parameter(name="page",description = "페이지번호, 0번이 1페이지입니다.") + }) + public ApiResponse getChallengingMissionList( + @ExistMember @PathVariable(name="memberId") Long memberId, + @CheckPage @RequestParam(name="page") int page + ){ + Page missionPage=missionQueryService.getChallengingMissionList(memberId,page); + return ApiResponse.onSuccess(MissionConverter.toMissionListDto(missionPage)); + } + @PatchMapping("/member/complete") + @Operation(summary = "진행중인 미션을 완료 상태로 변경") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH003", description = "access 토큰을 주세요!",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "acess 토큰 만료",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "acess 토큰 모양이 이상함",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + public ApiResponse completeMission( + @RequestBody @Valid MissionRequestDto.CompleteMissionRequestDto requestDto + ){ + MemberMission memberMission=missionCommandService.completeMission(requestDto); + return ApiResponse.onSuccess(MissionConverter.toCompleteMissionResponseDto(memberMission)); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/controller/StoreController.java b/Seoyeon/Mission/src/main/java/umc/practice/web/controller/StoreController.java new file mode 100644 index 0000000..2e3c852 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/controller/StoreController.java @@ -0,0 +1,83 @@ +package umc.practice.web.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; +import umc.practice.apiPayload.ApiResponse; +import umc.practice.converter.ReviewConverter; +import umc.practice.converter.StoreConverter; +import umc.practice.domain.Review; +import umc.practice.domain.Store; +import umc.practice.service.StoreCommandService; +import umc.practice.service.StoreQueryService; +import umc.practice.validation.annotation.CheckPage; +import umc.practice.validation.annotation.ExistMember; +import umc.practice.validation.annotation.ExistStore; +import umc.practice.web.dto.StoreRequestDto; +import umc.practice.web.dto.StoreResponseDto; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/stores") +public class StoreController { + private final StoreCommandService storeCommandService; + private final StoreQueryService storeQueryService; + + @PostMapping + public ApiResponse addStore(@RequestBody @Valid StoreRequestDto.AddStoreRequestDto request){ + Store store=storeCommandService.addStore(request); + return ApiResponse.onSuccess(StoreConverter.toStoreResponseDto(store)); + } + + @PostMapping("/reviews") + public ApiResponse writeReview(@RequestBody @Valid StoreRequestDto.WriteReviewRequestDto requestDto){ + Review review = storeCommandService.writeReview(requestDto); + return ApiResponse.onSuccess(ReviewConverter.toWriteReviewResponseDto(review)); + } + + @GetMapping("/{storeId}/reviews") + @Operation(summary = "특정 가게에 대한 리뷰 목록 조회",description = "query string으로 page 번호를 주세요") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH003", description = "access 토큰을 주세요!",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "acess 토큰 만료",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "acess 토큰 모양이 이상함",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + @Parameters({ + @Parameter(name = "storeId", description = "가게의 아이디, path variable입니다"), + @Parameter(name = "page", description = "페이지 번호, 0번이 1 페이지 입니다.") + }) + public ApiResponse getReviewList( + @ExistStore @PathVariable(name="storeId") Long storeId, + @CheckPage @RequestParam(name="page") int page){ + Page reviewPage=storeQueryService.getReviewList(storeId,page); + + return ApiResponse.onSuccess(ReviewConverter.toReviewListDto(reviewPage)); + } + @GetMapping("/members/{memberId}") + @Operation(summary = "내가 쓴 리뷰 목록 조회",description = "query string으로 page 번호를 주세요") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH003", description = "access 토큰을 주세요!",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "acess 토큰 만료",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "acess 토큰 모양이 이상함",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + @Parameters({ + @Parameter(name = "memberId"), + @Parameter(name = "page", description = "페이지 번호, 0번이 1 페이지 입니다.") + }) + public ApiResponse getMemberReviewList( + @PathVariable(name="memberId") @ExistMember Long memberId, + @RequestParam @CheckPage int page + ){ + Page reviewPage=storeQueryService.getMemberReviewList(memberId,page); + return ApiResponse.onSuccess(ReviewConverter.toReviewListDto(reviewPage)); + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MemberRequestDto.java b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MemberRequestDto.java new file mode 100644 index 0000000..3e92af4 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MemberRequestDto.java @@ -0,0 +1,30 @@ +package umc.practice.web.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.NonNull; +import umc.practice.domain.enums.Gender; +import umc.practice.validation.annotation.ExistCategories; + +import java.sql.Time; +import java.time.LocalDate; +import java.util.List; + +public class MemberRequestDto { + @Getter + public static class signUpRequestDto { + @NotBlank + String name; + @NotNull(message = "성별은 null이면 안됩니다.") + Gender gender; + @NotNull(message = "생일은 null이면 안됩니다.") + LocalDate birth; + @Size(min=5,max=20) + String address; + @ExistCategories + List favorList; + } + +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MemberResponseDto.java b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MemberResponseDto.java new file mode 100644 index 0000000..f3084e8 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MemberResponseDto.java @@ -0,0 +1,19 @@ +package umc.practice.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +public class MemberResponseDto { + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class signUpResponseDto { + Long memberId; + LocalDateTime createdAt; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MissionRequestDto.java b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MissionRequestDto.java new file mode 100644 index 0000000..0bc0975 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MissionRequestDto.java @@ -0,0 +1,68 @@ +package umc.practice.web.dto; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import umc.practice.validation.annotation.*; + +import java.time.LocalDate; + +public class MissionRequestDto { + @Getter + public static class AddMissionRequestDto { + @NotNull + private Long reward; + @NotNull + private Long minimumPrice; + @NotNull + @ValidMissionDate + @Valid + private DateRangeDto dateRange; + @NotNull + @ExistStore + private Long storeId; + } + + @Getter + public static class DateRangeDto{ + @NotNull + @FutureOrPresent(message = "지난 날짜는 지정이 불가능합니다") + private LocalDate startDate; + @NotNull + @FutureOrPresent(message = "지난 날짜는 지정이 불가능합니다") + private LocalDate endDate; + } + @Getter + public static class DoMissionRequestDto{ + @NotNull + @Valid + @NotExistsMemberMission + private MemberMissionDto memberMission; + } + @Getter + public static class MemberMissionDto{ + @ExistMember + @NotNull + private Long memberId; + @ExistMission + @NotNull + private Long missionId; + } + @Getter + public static class CompleteMissionRequestDto{ + @NotNull + @Valid + @ExistsMemberMission + CompleteMemberMissionDto completeMemberMission; + } + @Getter + public static class CompleteMemberMissionDto{ + @ExistMember + @NotNull + Long memberId; + @ExistMission + @NotNull + Long missionId; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MissionResponseDto.java b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MissionResponseDto.java new file mode 100644 index 0000000..731317a --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/MissionResponseDto.java @@ -0,0 +1,65 @@ +package umc.practice.web.dto; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import umc.practice.domain.enums.MissionStatus; + +import java.time.LocalDateTime; +import java.util.List; + +public class MissionResponseDto { + @Builder + @Getter + @AllArgsConstructor + @NoArgsConstructor + public static class AddMissionResponseDto { + private Long missionId; + private LocalDateTime createdAt; + } + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class DoMissionResponseDto { + @NotNull + private Long id; + @NotNull + private Long missionId; + @NotNull + private LocalDateTime createdAt; + } + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class MissionPreviewListDto { + List missionList; + int listSize; + int totalPage; + Long totalElement; + boolean isFirst; + boolean isLast; + } + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class MissionPreview{ + Long missionId; + String storeName; + Long reward; + Long minimumPrice; + } + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class CompleteMissionResponseDto { + Long missionId; + MissionStatus missionStatus; + LocalDateTime updatedAt; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/dto/StoreRequestDto.java b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/StoreRequestDto.java new file mode 100644 index 0000000..2eb9c8b --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/StoreRequestDto.java @@ -0,0 +1,35 @@ +package umc.practice.web.dto; + +import jakarta.validation.constraints.*; +import lombok.Getter; +import umc.practice.validation.annotation.ExistMember; +import umc.practice.validation.annotation.ExistRegion; +import umc.practice.validation.annotation.ExistStore; + +public class StoreRequestDto { + @Getter + public static class AddStoreRequestDto{ + @NotBlank + String storeName; + @NotBlank + String address; + @ExistRegion + String region; + } + + @Getter + public static class WriteReviewRequestDto { + @NotNull + @Max(5)@Min(1) + private int stars; + @NotBlank + @Size(max=200) + private String content; + @NotNull + @ExistMember + private Long writerId; + @NotNull + @ExistStore + private Long storeId; + } +} diff --git a/Seoyeon/Mission/src/main/java/umc/practice/web/dto/StoreResponseDto.java b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/StoreResponseDto.java new file mode 100644 index 0000000..f844f88 --- /dev/null +++ b/Seoyeon/Mission/src/main/java/umc/practice/web/dto/StoreResponseDto.java @@ -0,0 +1,55 @@ +package umc.practice.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +public class StoreResponseDto { + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class addStoreResponseDto { + Long storeId; + LocalDateTime createdAt; + } + + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class WriteReviewResponseDto { + private Long reviewId; + private LocalDateTime createdAt; + } + + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class ReviewPreviewListDto { + List reviewList; + int listSize; + int totalPage; + Long totalElement; + boolean isFirst; + boolean isLast; + } + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class ReviewPreview{ + Long reviewId; + String writerName; + int stars; + String content; + LocalDateTime createdAt; + } + +} diff --git a/Seoyeon/Mission/src/main/resources/application.properties b/Seoyeon/Mission/src/main/resources/application.properties new file mode 100644 index 0000000..9661635 --- /dev/null +++ b/Seoyeon/Mission/src/main/resources/application.properties @@ -0,0 +1,4 @@ +spring.application.name=practice + +spring.profiles.include=secret +spring.jpa.hibernate.ddl-auto=update \ No newline at end of file diff --git a/Seoyeon/Mission/src/test/java/umc/practice/PracticeApplicationTests.java b/Seoyeon/Mission/src/test/java/umc/practice/PracticeApplicationTests.java new file mode 100644 index 0000000..7914442 --- /dev/null +++ b/Seoyeon/Mission/src/test/java/umc/practice/PracticeApplicationTests.java @@ -0,0 +1,13 @@ +package umc.practice; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class PracticeApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/Seoyeon/README.md.txt b/Seoyeon/README.md.txt new file mode 100644 index 0000000..9ec477f --- /dev/null +++ b/Seoyeon/README.md.txt @@ -0,0 +1 @@ +seoyeon \ No newline at end of file