diff --git a/build.gradle b/build.gradle index d312f28..d1f30c7 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,13 @@ dependencies { 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.3.0' + + // 에러관련 의존성 주입 + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'jakarta.validation:jakarta.validation-api:3.0.2' + // QueryDsl implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" @@ -51,5 +58,4 @@ sourceSets { tasks.named('test') { useJUnitPlatform() -} - +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/Umc7thMissionApplication.java b/src/main/java/javalab/umc7th_mission/Umc7thMissionApplication.java index bd55412..9dead6d 100644 --- a/src/main/java/javalab/umc7th_mission/Umc7thMissionApplication.java +++ b/src/main/java/javalab/umc7th_mission/Umc7thMissionApplication.java @@ -2,10 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication -@EnableJpaRepositories +// @EnableJpaRepositories -> 보통 springBoot가 알아서 리포지토리 추가시켜줌 +@EnableJpaAuditing //생성일 및 업데이트일 자동 입력 public class Umc7thMissionApplication { public static void main(String[] args) { diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/ApiResponse.java b/src/main/java/javalab/umc7th_mission/apiPayload/ApiResponse.java new file mode 100644 index 0000000..4aa3cfb --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/ApiResponse.java @@ -0,0 +1,39 @@ +package javalab.umc7th_mission.apiPayload; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import javalab.umc7th_mission.apiPayload.code.status.SuccessStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@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() , SuccessStatus._OK.getMessage(), result); + } + + public static ApiResponse of(BaseCode code, T result){ + return new ApiResponse<>(true, code.getReasonHttpStatus().getCode() , code.getReasonHttpStatus().getMessage(), result); + } + + + // 실패한 경우 응답 생성 + public static ApiResponse onFailure(String code, String message, T data){ + return new ApiResponse<>(false, code, message, data); + } +} diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/BaseCode.java b/src/main/java/javalab/umc7th_mission/apiPayload/BaseCode.java new file mode 100644 index 0000000..4763af7 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/BaseCode.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.apiPayload; + +//해당 인터페이스의 역할 -> 구체화 하는 Status에서 +// 두개의 메소드를 반드시 오버라이드할 것을 강제하는 역할 +public interface BaseCode { + ReasonDTO getReason(); + ReasonDTO getReasonHttpStatus(); +} diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/BaseErrorCode.java b/src/main/java/javalab/umc7th_mission/apiPayload/BaseErrorCode.java new file mode 100644 index 0000000..9e8d9a6 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/BaseErrorCode.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.apiPayload; + +public interface BaseErrorCode { + + ErrorReasonDTO getReason(); + + ErrorReasonDTO getReasonHttpStatus(); +} diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/ErrorReasonDTO.java b/src/main/java/javalab/umc7th_mission/apiPayload/ErrorReasonDTO.java new file mode 100644 index 0000000..add3309 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/ErrorReasonDTO.java @@ -0,0 +1,18 @@ +package javalab.umc7th_mission.apiPayload; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@Builder +public class ErrorReasonDTO { + + private HttpStatus httpStatus; + + private final boolean isSuccess; + private final String code; + private final String message; + + public boolean getIsSuccess(){return isSuccess;} +} diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/ReasonDTO.java b/src/main/java/javalab/umc7th_mission/apiPayload/ReasonDTO.java new file mode 100644 index 0000000..3400b52 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/ReasonDTO.java @@ -0,0 +1,18 @@ +package javalab.umc7th_mission.apiPayload; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@Builder +public class ReasonDTO { + + private HttpStatus httpStatus; + + private final boolean isSuccess; + private final String code; + private final String message; + + public boolean getIsSuccess(){return isSuccess;} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/code/status/ErrorStatus.java b/src/main/java/javalab/umc7th_mission/apiPayload/code/status/ErrorStatus.java new file mode 100644 index 0000000..34ffb08 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/code/status/ErrorStatus.java @@ -0,0 +1,62 @@ +package javalab.umc7th_mission.apiPayload.code.status; + +import javalab.umc7th_mission.apiPayload.BaseErrorCode; +import javalab.umc7th_mission.apiPayload.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ErrorStatus implements BaseErrorCode { + + // 가장 일반적인 응답 + _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), + _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."), + _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."), + _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), + + //임시 + TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "테스트용 에러코드"), + + // 멤버 관련 에러 + MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "MEMBER4001", "사용자가 없습니다."), + NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST, "MEMBER4002", "닉네임은 필수 입니다."), + + // 미션 관련 에러 + MISSION_NOT_FOUND(HttpStatus.BAD_REQUEST, "MISSION4001", "미션이 없습니다."), + MISSION_ALREADY_IN_PROGRESS(HttpStatus.CONFLICT, "MISSION4091", "이미 진행중인 미션입니다."), + + STORE_NOT_FOUND(HttpStatus.BAD_REQUEST, "STORE4001", "상점이 없습니다."), + // 예시,,, + ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."), + + //해당 지역 혹은 카테고리 없음 + FOOD_CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "FOOD4001", "해당 음식 카테고리가 없습니다."), + REGION_NOT_FOUND(HttpStatus.NOT_FOUND, "REGION4001", "해당 지역이 없습니다."); + + + 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/src/main/java/javalab/umc7th_mission/apiPayload/code/status/SuccessStatus.java b/src/main/java/javalab/umc7th_mission/apiPayload/code/status/SuccessStatus.java new file mode 100644 index 0000000..ee3531f --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/code/status/SuccessStatus.java @@ -0,0 +1,45 @@ +package javalab.umc7th_mission.apiPayload.code.status; + +import javalab.umc7th_mission.apiPayload.BaseCode; +import javalab.umc7th_mission.apiPayload.ReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum SuccessStatus implements BaseCode { + + // 일반적인 응답 + _OK(HttpStatus.OK, "COMMON200", "성공입니다."); + + //맴버 관련 응답 + + // ~~~ 관련 응답 + + //성공응답 추가시 ENUM 형식으로 계속 밑에 추가하면 된다. + private final HttpStatus httpStatus; + private final String code; + private final String message; + + @Override + public ReasonDTO getReason() { + return ReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(true) + .build(); + } + + @Override + public ReasonDTO getReasonHttpStatus() { + return ReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(true) + .httpStatus(httpStatus) + .build() + ; + } +} + diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/ExceptionAdvice.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/ExceptionAdvice.java new file mode 100644 index 0000000..192fe7e --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/ExceptionAdvice.java @@ -0,0 +1,237 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.apiPayload.ErrorReasonDTO; +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +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.ErrorResponse; +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 java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@RestControllerAdvice(annotations = {RestController.class}) +public class ExceptionAdvice extends ResponseEntityExceptionHandler { + + + @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); + } + + @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); + } + + //FoodCatoryNotFoundException에 대한 에러 처리 + @ExceptionHandler(FoodCategoryNotFoundException.class) + public ResponseEntity handleFoodCategoryNotFoundException(FoodCategoryNotFoundException e, HttpServletRequest request) { + WebRequest webRequest = new ServletWebRequest(request); + + ApiResponse body = ApiResponse.onFailure( + ErrorStatus.FOOD_CATEGORY_NOT_FOUND.getCode(), + ErrorStatus.FOOD_CATEGORY_NOT_FOUND.getMessage(), + null + ); + + return super.handleExceptionInternal( + e, + body, + new HttpHeaders(), + ErrorStatus.FOOD_CATEGORY_NOT_FOUND.getHttpStatus(), + webRequest + ); + } + + //RegionNotFoundException에 대한 에러 처리 + @ExceptionHandler(RegionNotFoundException.class) + public ResponseEntity handleRegionNotFoundException(RegionNotFoundException e, HttpServletRequest request) { + WebRequest webRequest = new ServletWebRequest(request); + + ApiResponse body = ApiResponse.onFailure( + ErrorStatus.REGION_NOT_FOUND.getCode(), + ErrorStatus.REGION_NOT_FOUND.getMessage(), + null + ); + + return super.handleExceptionInternal( + e, + body, + new HttpHeaders(), + ErrorStatus.REGION_NOT_FOUND.getHttpStatus(), + webRequest + ); + } + + @ExceptionHandler(MissionNotFoundException.class) + public ResponseEntity handleMissionNotFoundException(MissionNotFoundException e, HttpServletRequest request) { + WebRequest webRequest = new ServletWebRequest(request); + + ApiResponse body = ApiResponse.onFailure( + ErrorStatus.MISSION_NOT_FOUND.getCode(), + ErrorStatus.MISSION_NOT_FOUND.getMessage(), + null + ); + + return super.handleExceptionInternal( + e, + body, + new HttpHeaders(), + ErrorStatus.MISSION_NOT_FOUND.getHttpStatus(), + webRequest + ); + } + + + @ExceptionHandler(MissionAlreadyInProgressException.class) + public ResponseEntity handleMissionAlreadyInProgressException(MissionAlreadyInProgressException e, HttpServletRequest request) { + WebRequest webRequest = new ServletWebRequest(request); + + ApiResponse body = ApiResponse.onFailure( + ErrorStatus.MISSION_ALREADY_IN_PROGRESS.getCode(), + ErrorStatus.MISSION_ALREADY_IN_PROGRESS.getMessage(), + null + ); + + return super.handleExceptionInternal( + e, + body, + new HttpHeaders(), + ErrorStatus.MISSION_ALREADY_IN_PROGRESS.getHttpStatus(), + webRequest + ); + } + + @ExceptionHandler(MemberNotFoundException.class) + public ResponseEntity handleMemberNotFoundException(MemberNotFoundException e, HttpServletRequest request) { + WebRequest webRequest = new ServletWebRequest(request); + + ApiResponse body = ApiResponse.onFailure( + ErrorStatus.MEMBER_NOT_FOUND.getCode(), + ErrorStatus.MEMBER_NOT_FOUND.getMessage(), + null + ); + + return super.handleExceptionInternal( + e, + body, + new HttpHeaders(), + ErrorStatus.MEMBER_NOT_FOUND.getHttpStatus(), + webRequest + ); + } + + @ExceptionHandler(StoreNotFoundException.class) + public ResponseEntity handleStoreNotFoundException(StoreNotFoundException e, HttpServletRequest request) { + WebRequest webRequest = new ServletWebRequest(request); + + ApiResponse body = ApiResponse.onFailure( + ErrorStatus.STORE_NOT_FOUND.getCode(), + ErrorStatus.STORE_NOT_FOUND.getMessage(), + null + ); + + return super.handleExceptionInternal( + e, + body, + new HttpHeaders(), + ErrorStatus.STORE_NOT_FOUND.getHttpStatus(), + webRequest + ); + } + + 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 + ); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/FoodCategoryNotFoundException.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/FoodCategoryNotFoundException.java new file mode 100644 index 0000000..42f7fe4 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/FoodCategoryNotFoundException.java @@ -0,0 +1,16 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import org.springframework.http.HttpStatus; + +public class FoodCategoryNotFoundException extends RuntimeException { + private final HttpStatus status = HttpStatus.NOT_FOUND; + + public FoodCategoryNotFoundException(ErrorStatus errorStatus) { + super(errorStatus.getMessage()); + } + + public HttpStatus getStatus() { + return status; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/GeneralException.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/GeneralException.java new file mode 100644 index 0000000..6c713b9 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/GeneralException.java @@ -0,0 +1,21 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import javalab.umc7th_mission.apiPayload.BaseErrorCode; +import javalab.umc7th_mission.apiPayload.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@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/src/main/java/javalab/umc7th_mission/apiPayload/exception/MemberNotFoundException.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/MemberNotFoundException.java new file mode 100644 index 0000000..7b503b3 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/MemberNotFoundException.java @@ -0,0 +1,16 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import org.springframework.http.HttpStatus; + +public class MemberNotFoundException extends RuntimeException { + private final HttpStatus status = HttpStatus.BAD_REQUEST; + + public MemberNotFoundException(ErrorStatus errorStatus) { + super(errorStatus.getMessage()); + } + + public HttpStatus getStatus() { + return status; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/MissionAlreadyInProgressException.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/MissionAlreadyInProgressException.java new file mode 100644 index 0000000..0b601ac --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/MissionAlreadyInProgressException.java @@ -0,0 +1,16 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import org.springframework.http.HttpStatus; + +public class MissionAlreadyInProgressException extends RuntimeException { + private final HttpStatus status = HttpStatus.CONFLICT; + + public MissionAlreadyInProgressException(ErrorStatus errorStatus) { + super(errorStatus.getMessage()); + } + + public HttpStatus getStatus() { + return status; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/MissionNotFoundException.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/MissionNotFoundException.java new file mode 100644 index 0000000..7a02771 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/MissionNotFoundException.java @@ -0,0 +1,16 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import org.springframework.http.HttpStatus; + +public class MissionNotFoundException extends RuntimeException { + private final HttpStatus status = HttpStatus.BAD_REQUEST; + + public MissionNotFoundException(ErrorStatus errorStatus) { + super(errorStatus.getMessage()); + } + + public HttpStatus getStatus() { + return status; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/RegionNotFoundException.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/RegionNotFoundException.java new file mode 100644 index 0000000..9f4abf8 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/RegionNotFoundException.java @@ -0,0 +1,16 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import org.springframework.http.HttpStatus; + +public class RegionNotFoundException extends RuntimeException { + private final HttpStatus status = HttpStatus.NOT_FOUND; + + public RegionNotFoundException(ErrorStatus errorStatus) { + super(errorStatus.getMessage()); + } + + public HttpStatus getStatus() { + return status; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/StoreNotFoundException.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/StoreNotFoundException.java new file mode 100644 index 0000000..5738eed --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/StoreNotFoundException.java @@ -0,0 +1,16 @@ +package javalab.umc7th_mission.apiPayload.exception; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import org.springframework.http.HttpStatus; + +public class StoreNotFoundException extends RuntimeException { + private final HttpStatus status = HttpStatus.BAD_REQUEST; + + public StoreNotFoundException(ErrorStatus errorStatus) { + super(errorStatus.getMessage()); + } + + public HttpStatus getStatus() { + return status; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/apiPayload/exception/handler/TempHandler.java b/src/main/java/javalab/umc7th_mission/apiPayload/exception/handler/TempHandler.java new file mode 100644 index 0000000..f65148f --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/apiPayload/exception/handler/TempHandler.java @@ -0,0 +1,10 @@ +package javalab.umc7th_mission.apiPayload.exception.handler; + +import javalab.umc7th_mission.apiPayload.BaseErrorCode; +import javalab.umc7th_mission.apiPayload.exception.GeneralException; + +public class TempHandler extends GeneralException { + public TempHandler(BaseErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/javalab/umc7th_mission/config/SwaggerConfig.java b/src/main/java/javalab/umc7th_mission/config/SwaggerConfig.java new file mode 100644 index 0000000..6af2cb5 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/SwaggerConfig.java @@ -0,0 +1,39 @@ +package javalab.umc7th_mission.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); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/MemberConverter.java b/src/main/java/javalab/umc7th_mission/converter/MemberConverter.java new file mode 100644 index 0000000..839fc0c --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/MemberConverter.java @@ -0,0 +1,60 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Region; +import javalab.umc7th_mission.domain.enums.Gender; +import javalab.umc7th_mission.domain.mapping.MemberAddress; +import javalab.umc7th_mission.repository.RegionRepository.RegionRepository; +import javalab.umc7th_mission.web.dto.MemberRequestDTO; +import javalab.umc7th_mission.web.dto.MemberResponseDTO; +import java.time.LocalDateTime; +import java.util.ArrayList; + +public class MemberConverter { + + //Member객체를 MemberResponseDTO중에 JoinResultDTO에 알맞은 객체로 변환후 반환 + public static MemberResponseDTO.JoinResultDTO toJoinResultDTO(Member member) { + return new MemberResponseDTO.JoinResultDTO( + member.getId(), + member.getCreatedAt() + ); + } + + //DTO객체를 다시 Member객체로 변환시 사용 주로 쓰기 영역에서 많이 사용한다. + public static Member toMember(MemberRequestDTO.JoinDto request) { + Gender gender = null; + switch (request.getGender().getValue()) { + case 1: + gender = Gender.MALE; + break; + case 2: + gender = Gender.FEMALE; + break; + case 3: + gender = Gender.OTHER; + break; + case 4: + gender = Gender.UNKNOWN; + break; + } + //member 생성 (주소는 개별) + return Member.builder() + .gender(gender) + .name(request.getName()) + .nickname(request.getNickname()) + .phoneNumber(request.getPhoneNumber()) + .email(request.getEmail()) + .memberPreferList(new ArrayList<>()) + .point(0) + .build(); + } + + public static MemberAddress toMemberAddress(Member member, Region region, MemberRequestDTO.JoinDto request) { + return MemberAddress.builder() + .member(member) + .region(region) + .detailAddress(request.getDetailedAddress()) + .zipCode(request.getZipcode()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/MemberMissionConverter.java b/src/main/java/javalab/umc7th_mission/converter/MemberMissionConverter.java new file mode 100644 index 0000000..79749ec --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/MemberMissionConverter.java @@ -0,0 +1,28 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Mission; +import javalab.umc7th_mission.domain.enums.MissionStatus; +import javalab.umc7th_mission.domain.mapping.MemberMission; +import javalab.umc7th_mission.web.dto.MemberMissionRequestDTO; +import javalab.umc7th_mission.web.dto.MemberMissionResponseDTO; +import javalab.umc7th_mission.web.dto.MissionRequestDTO; + +public class MemberMissionConverter { + public static MemberMissionResponseDTO.AddResultDTO toAddResultDTO(MemberMission memberMission) { + return new MemberMissionResponseDTO.AddResultDTO( + memberMission.getId(), + memberMission.getCreatedAt() + ); + } + + public static MemberMission toMemberMission(Member member, Mission mission, MemberMissionRequestDTO.AddDTO request) { + return MemberMission.builder() + .member(member) + .mission(mission) + .startDate(request.getStartDate()) + .endDate(request.getEndDate()) + .status(MissionStatus.CHALLENGING) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/MemberPreferConverter.java b/src/main/java/javalab/umc7th_mission/converter/MemberPreferConverter.java new file mode 100644 index 0000000..f526260 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/MemberPreferConverter.java @@ -0,0 +1,20 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.domain.FoodCategory; +import javalab.umc7th_mission.domain.mapping.MemberPrefer; + +import java.util.List; +import java.util.stream.Collectors; + +public class MemberPreferConverter { + + public static List toMemberPreferList(List foodCategoryList){ + + return foodCategoryList.stream() + .map(foodCategory -> + MemberPrefer.builder() + .foodCategory(foodCategory) + .build() + ).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/MissionConverter.java b/src/main/java/javalab/umc7th_mission/converter/MissionConverter.java new file mode 100644 index 0000000..5935b8d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/MissionConverter.java @@ -0,0 +1,27 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.domain.Mission; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.web.dto.MissionRequestDTO; +import javalab.umc7th_mission.web.dto.MissionResponseDTO; + +public class MissionConverter { + + public static MissionResponseDTO.AddResultDTO toAddResultDTO(Mission mission) { + return new MissionResponseDTO.AddResultDTO( + mission.getId(), + mission.getCreatedAt() + ); + } + + public static Mission toMission(Store store, MissionRequestDTO.AddDTO request) { + return Mission.builder() + .store(store) + .name(request.getName()) + .description(request.getDescription()) + .startDate(request.getStartDate()) + .endDate(request.getEndDate()) + .reward(request.getReward()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/ReviewConverter.java b/src/main/java/javalab/umc7th_mission/converter/ReviewConverter.java new file mode 100644 index 0000000..7c6fa00 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/ReviewConverter.java @@ -0,0 +1,27 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Review; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.web.dto.ReviewRequestDTO; +import javalab.umc7th_mission.web.dto.ReviewResponseDTO; + +public class ReviewConverter { + + public static ReviewResponseDTO.AddResultDTO toAddResultDTO(Review review) { + return new ReviewResponseDTO.AddResultDTO( + review.getId(), + review.getCreatedAt() + ); + } + + public static Review toReview(Member member, Store store, ReviewRequestDTO.AddDTO request) { + return Review.builder() + .member(member) + .store(store) + .content(request.getContent()) + .rating(request.getRating()) + .reviewImageList(request.getReviewImageList()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/StoreCategoryConverter.java b/src/main/java/javalab/umc7th_mission/converter/StoreCategoryConverter.java new file mode 100644 index 0000000..bca00d7 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/StoreCategoryConverter.java @@ -0,0 +1,19 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.domain.FoodCategory; +import javalab.umc7th_mission.domain.mapping.StoreCategory; + +import java.util.List; +import java.util.stream.Collectors; + +public class StoreCategoryConverter { + public static List toStoreCategoryList(List foodCategoryList){ + + return foodCategoryList.stream() + .map(foodCategory -> + StoreCategory.builder() + .foodCategory(foodCategory) + .build() + ).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/StoreConverter.java b/src/main/java/javalab/umc7th_mission/converter/StoreConverter.java new file mode 100644 index 0000000..0a14bc0 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/StoreConverter.java @@ -0,0 +1,38 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Region; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.domain.mapping.StoreAddress; +import javalab.umc7th_mission.web.dto.MemberRequestDTO; +import javalab.umc7th_mission.web.dto.StoreRequestDTO; +import javalab.umc7th_mission.web.dto.StoreResponseDTO; + +public class StoreConverter { + + public static StoreResponseDTO.AddResultDTO toAddResultDTO(Store store) { + return new StoreResponseDTO.AddResultDTO( + store.getId(), + store.getCreatedAt() + ); + } + + public static Store toStore(StoreRequestDTO.AddDto request) { + return Store.builder() + .name(request.getName()) + .phoneNumber(request.getPhoneNumber()) + .description(request.getDescription()) + .openingHours(request.getOpeningHours()) + .closingHours(request.getClosingHours()) + .build(); + } + + public static StoreAddress toStoreAddress(Store store, Region region, StoreRequestDTO.AddDto request) { + return StoreAddress.builder() + .region(region) + .store(store) + .detailAddress(request.getDetailedAddress()) + .zipCode(request.getZipcode()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/converter/TempConverter.java b/src/main/java/javalab/umc7th_mission/converter/TempConverter.java new file mode 100644 index 0000000..a00cfdc --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/converter/TempConverter.java @@ -0,0 +1,18 @@ +package javalab.umc7th_mission.converter; + +import javalab.umc7th_mission.web.dto.TempResponse; + +public class TempConverter { + + public static TempResponse.TempTestDTO toTempTestDTO(){ + return TempResponse.TempTestDTO.builder() + .testString("This is Test!") + .build(); + } + + public static TempResponse.TempExceptionDTO toTempExceptionDTO(Integer flag){ + return TempResponse.TempExceptionDTO.builder() + .flag(flag) + .build(); + } +} diff --git a/src/main/java/javalab/umc7th_mission/domain/Member.java b/src/main/java/javalab/umc7th_mission/domain/Member.java index 6974030..1dcea5a 100644 --- a/src/main/java/javalab/umc7th_mission/domain/Member.java +++ b/src/main/java/javalab/umc7th_mission/domain/Member.java @@ -10,6 +10,7 @@ import lombok.*; import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.Columns; +import org.springframework.boot.context.properties.bind.DefaultValue; import java.time.LocalDate; import java.util.ArrayList; @@ -17,6 +18,8 @@ @Entity @Getter +//24.11.20 @Setter 추가 +@Setter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @@ -48,11 +51,15 @@ public class Member extends BaseEntity { @Column(nullable = false, unique = true, length = 50) private String email; + //24.11.20 point = 0 -> @ColumDefault, api에서 null문제가 꾸준히 발생하여 변경함 @Column(nullable = false) - private Integer point = 0; + @ColumnDefault("0") + private Integer point; - @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List addressList = new ArrayList<>(); + //24.11.21 fix/#7 + @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "address_id") + private MemberAddress address; @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List memberAgreeList = new ArrayList<>(); @@ -65,4 +72,4 @@ public class Member extends BaseEntity { @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List memberMissionList = new ArrayList<>(); -} \ No newline at end of file +} diff --git a/src/main/java/javalab/umc7th_mission/domain/ReviewImage.java b/src/main/java/javalab/umc7th_mission/domain/ReviewImage.java index 1d9c054..1b857ea 100644 --- a/src/main/java/javalab/umc7th_mission/domain/ReviewImage.java +++ b/src/main/java/javalab/umc7th_mission/domain/ReviewImage.java @@ -1,5 +1,6 @@ package javalab.umc7th_mission.domain; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import javalab.umc7th_mission.domain.common.BaseEntity; import lombok.*; @@ -26,5 +27,6 @@ public class ReviewImage extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "review_id") + @JsonIgnore //순환참조 방지 private Review review; -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/domain/Store.java b/src/main/java/javalab/umc7th_mission/domain/Store.java index 53d0ed9..7dc0201 100644 --- a/src/main/java/javalab/umc7th_mission/domain/Store.java +++ b/src/main/java/javalab/umc7th_mission/domain/Store.java @@ -1,5 +1,6 @@ package javalab.umc7th_mission.domain; import jakarta.persistence.*; +import javalab.umc7th_mission.domain.common.BaseEntity; import javalab.umc7th_mission.domain.mapping.StoreAddress; import javalab.umc7th_mission.domain.mapping.StoreCategory; import lombok.*; @@ -15,7 +16,8 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder -public class Store { +//24.11.20 BaseEntity 놓친거 추가 +public class Store extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -36,9 +38,11 @@ public class Store { @Column(nullable = false, length = 255) private String closingHours; - @OneToMany(mappedBy = "store", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List addressList = new ArrayList<>(); + //24.11.20 StoreAddress와의 관계 재설정!! + @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "address_id") + private StoreAddress address; @OneToMany(mappedBy = "store", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List categoryList = new ArrayList<>(); -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/domain/enums/Gender.java b/src/main/java/javalab/umc7th_mission/domain/enums/Gender.java index b04b95b..315b867 100644 --- a/src/main/java/javalab/umc7th_mission/domain/enums/Gender.java +++ b/src/main/java/javalab/umc7th_mission/domain/enums/Gender.java @@ -1,5 +1,24 @@ package javalab.umc7th_mission.domain.enums; +//24.11.19 MemberConverter에서 스위치문을 위해 정수 값 매핑 추가 public enum Gender { - MALE, FEMALE, OTHER, UNKNOWN; + MALE(1), FEMALE(2), OTHER(3), UNKNOWN(4); + + private final int value; + + Gender(int value) { + this.value = value; + } + public int getValue() { + return value; + } + + public static Gender fromValue(int value) { + for (Gender gender : Gender.values()) { + if (gender.getValue() == value) { + return gender; + } + } + throw new IllegalArgumentException("잘못된 Gender의 값: " + value); + } } diff --git a/src/main/java/javalab/umc7th_mission/domain/enums/MissionStatus.java b/src/main/java/javalab/umc7th_mission/domain/enums/MissionStatus.java index ee8669b..ac114b2 100644 --- a/src/main/java/javalab/umc7th_mission/domain/enums/MissionStatus.java +++ b/src/main/java/javalab/umc7th_mission/domain/enums/MissionStatus.java @@ -1,5 +1,5 @@ package javalab.umc7th_mission.domain.enums; public enum MissionStatus { - PENDING,CHALLENGING, COMPLETE -} + PENDING, CHALLENGING, COMPLETE +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/domain/mapping/MemberAddress.java b/src/main/java/javalab/umc7th_mission/domain/mapping/MemberAddress.java index 3fd6336..5ceca6f 100644 --- a/src/main/java/javalab/umc7th_mission/domain/mapping/MemberAddress.java +++ b/src/main/java/javalab/umc7th_mission/domain/mapping/MemberAddress.java @@ -23,8 +23,8 @@ public class MemberAddress extends BaseEntity { @JoinColumn(name = "region_id", referencedColumnName = "id") private Region region; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id", referencedColumnName = "id") + //24.11.21 fix/#7 + @OneToOne(mappedBy = "address",fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Member member; @Column(nullable = false, length = 100) @@ -33,4 +33,4 @@ public class MemberAddress extends BaseEntity { @Column(nullable = false, length = 40) private String zipCode; -} \ No newline at end of file +} diff --git a/src/main/java/javalab/umc7th_mission/domain/mapping/MemberPrefer.java b/src/main/java/javalab/umc7th_mission/domain/mapping/MemberPrefer.java index 6dd90a8..0a4dacb 100644 --- a/src/main/java/javalab/umc7th_mission/domain/mapping/MemberPrefer.java +++ b/src/main/java/javalab/umc7th_mission/domain/mapping/MemberPrefer.java @@ -25,4 +25,16 @@ public class MemberPrefer extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "category_id", referencedColumnName = "id") private FoodCategory foodCategory; -} + + //24.11.20 setMember & setFoodCategory add + public void setMember(Member member){ + if(this.member != null) + member.getMemberPreferList().remove(this); + this.member = member; + member.getMemberPreferList().add(this); + } + + public void setFoodCategory(FoodCategory foodCategory){ + this.foodCategory = foodCategory; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/domain/mapping/StoreAddress.java b/src/main/java/javalab/umc7th_mission/domain/mapping/StoreAddress.java index 358179c..8f475c9 100644 --- a/src/main/java/javalab/umc7th_mission/domain/mapping/StoreAddress.java +++ b/src/main/java/javalab/umc7th_mission/domain/mapping/StoreAddress.java @@ -23,8 +23,7 @@ public class StoreAddress extends BaseEntity { @JoinColumn(name = "region_id", referencedColumnName = "id") private Region region; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "store_id", referencedColumnName = "id") + @OneToOne(mappedBy = "address",fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Store store; @Column(nullable = false, length = 100) @@ -32,4 +31,4 @@ public class StoreAddress extends BaseEntity { @Column(nullable = false, length = 40) private String zipCode; -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/FoodCategoryRepository/FoodCategoryRepository.java b/src/main/java/javalab/umc7th_mission/repository/FoodCategoryRepository/FoodCategoryRepository.java new file mode 100644 index 0000000..90a0447 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/FoodCategoryRepository/FoodCategoryRepository.java @@ -0,0 +1,9 @@ +package javalab.umc7th_mission.repository.FoodCategoryRepository; + +import javalab.umc7th_mission.domain.FoodCategory; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface FoodCategoryRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepository.java b/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepository.java new file mode 100644 index 0000000..8cd53b8 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepository.java @@ -0,0 +1,9 @@ +package javalab.umc7th_mission.repository.MemberAddressRepository; + +import javalab.umc7th_mission.domain.mapping.MemberAddress; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MemberAddressRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepositoryCustom.java b/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepositoryCustom.java new file mode 100644 index 0000000..8c916b4 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepositoryCustom.java @@ -0,0 +1,9 @@ +package javalab.umc7th_mission.repository.MemberAddressRepository; + +import javalab.umc7th_mission.domain.mapping.MemberAddress; + +import java.util.List; + +public interface MemberAddressRepositoryCustom { + List findAllAddressByMemberId(Long memberId); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepositoryImpl.java new file mode 100644 index 0000000..b5d1362 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/MemberAddressRepository/MemberAddressRepositoryImpl.java @@ -0,0 +1,25 @@ +package javalab.umc7th_mission.repository.MemberAddressRepository; + + +import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; +import javalab.umc7th_mission.domain.mapping.MemberAddress; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class MemberAddressRepositoryImpl implements MemberAddressRepositoryCustom { + private final EntityManager entityManager; + //JPQL을 사용해 MemberAddress 엔티티에서 특정 member의 주소 조회 + @Override + public List findAllAddressByMemberId(Long memberId) { + String jpql = "SELECT ma FROM MemberAddress ma WHERE ma.member.id = :memberId"; + TypedQuery query = entityManager.createQuery(jpql, MemberAddress.class); + query.setParameter("memberId", memberId); + + return query.getResultList(); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepository.java b/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepository.java index ec30e9c..ead83ae 100644 --- a/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepository.java +++ b/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepository.java @@ -1,8 +1,12 @@ package javalab.umc7th_mission.repository.MemberMissionRepository; +import javalab.umc7th_mission.domain.enums.MissionStatus; import javalab.umc7th_mission.domain.mapping.MemberMission; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface MemberMissionRepository extends JpaRepository, MemberMissionRepositoryCustom { -} + boolean existsByMemberIdAndMissionIdAndStatus(Long memberId, Long missionId, MissionStatus status); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryCustom.java b/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryCustom.java index 70952c2..c9ce8a6 100644 --- a/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryCustom.java +++ b/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryCustom.java @@ -12,4 +12,4 @@ public interface MemberMissionRepositoryCustom { List findChallengingMissionByMember(Long memberId, Pageable pageable); List findCompletedMissionByMember(Long memberId, Pageable pageable); Long countCompletedMissionByMember(Long memberId, String regionName); -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryImpl.java index de0e4d1..9d5badf 100644 --- a/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryImpl.java +++ b/src/main/java/javalab/umc7th_mission/repository/MemberMissionRepository/MemberMissionRepositoryImpl.java @@ -78,7 +78,7 @@ public Long countCompletedMissionByMember(Long memberId, String regionName) { .from(memberMission) .join(memberMission.mission, mission) .join(mission.store, store) - .join(store.addressList, storeAddress) + .join(store.address, storeAddress) .where( memberMission.member.id.eq(memberId), memberMission.status.eq(MissionStatus.COMPLETE), @@ -87,4 +87,4 @@ public Long countCompletedMissionByMember(Long memberId, String regionName) { .fetchOne(); } -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberPreferRepository/MemberPreferRepository.java b/src/main/java/javalab/umc7th_mission/repository/MemberPreferRepository/MemberPreferRepository.java new file mode 100644 index 0000000..34c0a6a --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/MemberPreferRepository/MemberPreferRepository.java @@ -0,0 +1,9 @@ +package javalab.umc7th_mission.repository.MemberPreferRepository; + +import javalab.umc7th_mission.domain.mapping.MemberPrefer; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MemberPreferRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepository.java b/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepository.java index c98e5af..9b3d5bb 100644 --- a/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepository.java +++ b/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepository.java @@ -2,6 +2,9 @@ import javalab.umc7th_mission.domain.Member; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; -public interface MemberRepository extends JpaRepository { -} +//24.11.19 -> to , @Repository add +@Repository +public interface MemberRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryCustom.java b/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryCustom.java index 0d6472f..c96396d 100644 --- a/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryCustom.java +++ b/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryCustom.java @@ -9,4 +9,4 @@ @Repository public interface MemberRepositoryCustom { MemberInfoDto findMemberInfoById(Long memberId); -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryImpl.java index b2eb68f..71ad4d6 100644 --- a/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryImpl.java +++ b/src/main/java/javalab/umc7th_mission/repository/MemberRepository/MemberRepositoryImpl.java @@ -29,4 +29,4 @@ public MemberInfoDto findMemberInfoById(Long memberId) { .where(member.id.eq(memberId)) .fetchOne(); } -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/MissionRepository/MissionRepository.java b/src/main/java/javalab/umc7th_mission/repository/MissionRepository/MissionRepository.java new file mode 100644 index 0000000..4af0e67 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/MissionRepository/MissionRepository.java @@ -0,0 +1,9 @@ +package javalab.umc7th_mission.repository.MissionRepository; + +import javalab.umc7th_mission.domain.Mission; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MissionRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepository.java b/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepository.java new file mode 100644 index 0000000..220bfff --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepository.java @@ -0,0 +1,12 @@ +package javalab.umc7th_mission.repository.RegionRepository; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import javalab.umc7th_mission.domain.Region; + +import java.util.Optional; + +@Repository +public interface RegionRepository extends JpaRepository { + // 추가로 지역 이름으로 검색할 수 있는 메서드 + Region findByName(String name); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepositoryCustom.java b/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepositoryCustom.java new file mode 100644 index 0000000..c71f84d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepositoryCustom.java @@ -0,0 +1,4 @@ +package javalab.umc7th_mission.repository.RegionRepository; + +public interface RegionRepositoryCustom { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepositoryImpl.java new file mode 100644 index 0000000..6087a9c --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/RegionRepository/RegionRepositoryImpl.java @@ -0,0 +1,4 @@ +package javalab.umc7th_mission.repository.RegionRepository; + +public class RegionRepositoryImpl implements RegionRepositoryCustom { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepository.java b/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepository.java index 1936109..df0d29a 100644 --- a/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepository.java +++ b/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepository.java @@ -6,9 +6,12 @@ import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; import java.math.BigDecimal; +//24.11.19 @Repository add +@Repository public interface ReviewRepository extends JpaRepository { @Modifying @@ -19,4 +22,4 @@ void insertReview(@Param("memberId") Long memberId, @Param("content") String content, @Param("rating") BigDecimal rating ); -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryCustom.java b/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryCustom.java index 6b2ae58..0caaef4 100644 --- a/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryCustom.java +++ b/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryCustom.java @@ -7,4 +7,4 @@ public interface ReviewRepositoryCustom { public Long save(Member member, Store store, String content, BigDecimal rating); -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryImpl.java index 85bb848..960b941 100644 --- a/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryImpl.java +++ b/src/main/java/javalab/umc7th_mission/repository/ReviewRepository/ReviewRepositoryImpl.java @@ -25,4 +25,4 @@ public Long save(Member member, Store store, String content, BigDecimal rating) .values(member, store, content, rating) .execute(); } -} \ No newline at end of file +} diff --git a/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepository.java b/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepository.java new file mode 100644 index 0000000..45b32a4 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepository.java @@ -0,0 +1,9 @@ +package javalab.umc7th_mission.repository.StoreAddressRepository; + +import javalab.umc7th_mission.domain.mapping.StoreAddress; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface StoreAddressRepository extends JpaRepository, StoreAddressRepositoryCustom { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepositoryCustom.java b/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepositoryCustom.java new file mode 100644 index 0000000..3f58bb1 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepositoryCustom.java @@ -0,0 +1,4 @@ +package javalab.umc7th_mission.repository.StoreAddressRepository; + +public interface StoreAddressRepositoryCustom { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepositoryImpl.java new file mode 100644 index 0000000..45a9181 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/repository/StoreAddressRepository/StoreAddressRepositoryImpl.java @@ -0,0 +1,4 @@ +package javalab.umc7th_mission.repository.StoreAddressRepository; + +public class StoreAddressRepositoryImpl implements StoreAddressRepositoryCustom { +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepository.java b/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepository.java index 6eef78b..bcea3eb 100644 --- a/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepository.java +++ b/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepository.java @@ -2,6 +2,9 @@ import javalab.umc7th_mission.domain.Store; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +//24.11.19 @Repository add +@Repository public interface StoreRepository extends JpaRepository, StoreRepositoryCustom { -} \ No newline at end of file +} diff --git a/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryCustom.java b/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryCustom.java index 4b89a08..452f4fc 100644 --- a/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryCustom.java +++ b/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryCustom.java @@ -6,4 +6,4 @@ public interface StoreRepositoryCustom { List dynamicQueryWithBooleanBuilder(String name, Float score); -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryImpl.java index 4f93dfb..d1c6061 100644 --- a/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryImpl.java +++ b/src/main/java/javalab/umc7th_mission/repository/StoreRepository/StoreRepositoryImpl.java @@ -29,4 +29,4 @@ public List dynamicQueryWithBooleanBuilder(String name, Float score) { .where(predicate) .fetch(); } -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/FoodCategoryService/FoodCategoryService.java b/src/main/java/javalab/umc7th_mission/service/FoodCategoryService/FoodCategoryService.java new file mode 100644 index 0000000..43ec2d8 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/FoodCategoryService/FoodCategoryService.java @@ -0,0 +1,7 @@ +package javalab.umc7th_mission.service.FoodCategoryService; + +import java.util.List; + +public interface FoodCategoryService { + boolean allCategoriesExist(List values); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/FoodCategoryService/FoodCategoryServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/FoodCategoryService/FoodCategoryServiceImpl.java new file mode 100644 index 0000000..478405e --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/FoodCategoryService/FoodCategoryServiceImpl.java @@ -0,0 +1,20 @@ +package javalab.umc7th_mission.service.FoodCategoryService; + +import javalab.umc7th_mission.repository.FoodCategoryRepository.FoodCategoryRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class FoodCategoryServiceImpl implements FoodCategoryService { + + FoodCategoryRepository foodCategoryRepository; + + @Override + public boolean allCategoriesExist(List values) { + return values.stream() + .allMatch(id -> foodCategoryRepository.existsById(id)); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/MemberMissionCommandService/MemberMissionCommandService.java b/src/main/java/javalab/umc7th_mission/service/MemberMissionCommandService/MemberMissionCommandService.java new file mode 100644 index 0000000..65564a0 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/MemberMissionCommandService/MemberMissionCommandService.java @@ -0,0 +1,10 @@ +package javalab.umc7th_mission.service.MemberMissionCommandService; + +import javalab.umc7th_mission.domain.mapping.MemberMission; +import javalab.umc7th_mission.web.dto.MemberMissionRequestDTO; + +public interface MemberMissionCommandService { + MemberMission addMemberMission(MemberMissionRequestDTO.AddDTO request); + + boolean isMissionInProgress(Long memberId, Long missionId); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/MemberMissionCommandService/MemberMissionCommandServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/MemberMissionCommandService/MemberMissionCommandServiceImpl.java new file mode 100644 index 0000000..19b694a --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/MemberMissionCommandService/MemberMissionCommandServiceImpl.java @@ -0,0 +1,45 @@ +package javalab.umc7th_mission.service.MemberMissionCommandService; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.apiPayload.exception.MemberNotFoundException; +import javalab.umc7th_mission.apiPayload.exception.MissionNotFoundException; +import javalab.umc7th_mission.converter.MemberMissionConverter; +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Mission; +import javalab.umc7th_mission.domain.enums.MissionStatus; +import javalab.umc7th_mission.domain.mapping.MemberMission; +import javalab.umc7th_mission.repository.MemberMissionRepository.MemberMissionRepository; +import javalab.umc7th_mission.repository.MemberRepository.MemberRepository; +import javalab.umc7th_mission.repository.MissionRepository.MissionRepository; +import javalab.umc7th_mission.web.dto.MemberMissionRequestDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class MemberMissionCommandServiceImpl implements MemberMissionCommandService { + private final MemberRepository memberRepository; + private final MissionRepository missionRepository; + private final MemberMissionRepository memberMissionRepository; + + @Override + public MemberMission addMemberMission(MemberMissionRequestDTO.AddDTO request) { + //멤버 파악 + Member member = memberRepository.findById(request.getMemberId()) + .orElseThrow(() -> new MemberNotFoundException(ErrorStatus.MEMBER_NOT_FOUND)); + + // + Mission mission = missionRepository.findById(request.getMissionId()) + .orElseThrow(() -> new MissionNotFoundException(ErrorStatus.MISSION_NOT_FOUND)); + + MemberMission memberMission = MemberMissionConverter.toMemberMission(member, mission, request); + + return memberMissionRepository.save(memberMission); + } + + @Override + public boolean isMissionInProgress(Long memberId, Long missionId) { + return memberMissionRepository.existsByMemberIdAndMissionIdAndStatus(memberId, missionId, MissionStatus.CHALLENGING); + } + +} diff --git a/src/main/java/javalab/umc7th_mission/service/MemberService/MemberCommandService.java b/src/main/java/javalab/umc7th_mission/service/MemberService/MemberCommandService.java new file mode 100644 index 0000000..54622bb --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/MemberService/MemberCommandService.java @@ -0,0 +1,12 @@ +package javalab.umc7th_mission.service.MemberService; + +import jakarta.validation.Valid; +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.web.dto.MemberRequestDTO; +import javalab.umc7th_mission.web.dto.MemberResponseDTO; +import org.springframework.web.bind.annotation.RequestBody; + +public interface MemberCommandService { + Member joinMember(MemberRequestDTO.JoinDto request); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/MemberService/MemberCommandServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/MemberService/MemberCommandServiceImpl.java new file mode 100644 index 0000000..021419e --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/MemberService/MemberCommandServiceImpl.java @@ -0,0 +1,69 @@ +package javalab.umc7th_mission.service.MemberService; + +import jakarta.transaction.Transactional; +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.apiPayload.exception.FoodCategoryNotFoundException; +import javalab.umc7th_mission.apiPayload.exception.RegionNotFoundException; +import javalab.umc7th_mission.converter.MemberConverter; +import javalab.umc7th_mission.converter.MemberPreferConverter; +import javalab.umc7th_mission.domain.FoodCategory; +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Region; +import javalab.umc7th_mission.domain.mapping.MemberAddress; +import javalab.umc7th_mission.domain.mapping.MemberPrefer; +import javalab.umc7th_mission.repository.FoodCategoryRepository.FoodCategoryRepository; +import javalab.umc7th_mission.repository.MemberAddressRepository.MemberAddressRepository; +import javalab.umc7th_mission.repository.MemberRepository.MemberRepository; +import javalab.umc7th_mission.repository.RegionRepository.RegionRepository; +import javalab.umc7th_mission.web.dto.MemberRequestDTO; +import javalab.umc7th_mission.web.dto.MemberResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class MemberCommandServiceImpl implements MemberCommandService { + private final MemberRepository memberRepository; + private final RegionRepository regionRepository; + private final MemberAddressRepository memberAddressRepository; + private final FoodCategoryRepository foodCategoryRepository; + + @Override + @Transactional //트렌잭션 어노테이션 + public Member joinMember(MemberRequestDTO.JoinDto request) { + Region region = regionRepository.findByName(request.getRegion()); + if (region == null) { + throw new RegionNotFoundException(ErrorStatus.REGION_NOT_FOUND); + } + + //member 생성 및 저장 + Member newMember = MemberConverter.toMember(request); + //foodCategory list 조회 + List foodCategoryList = request.getPreferCategory().stream() + .map(category -> { + return foodCategoryRepository.findById(category).orElseThrow(() -> new FoodCategoryNotFoundException(ErrorStatus.FOOD_CATEGORY_NOT_FOUND)); + }).collect(Collectors.toList()); + + //list 생성 및 Member와 연결 + List memberPreferList = MemberPreferConverter.toMemberPreferList(foodCategoryList); + memberPreferList.forEach(memberPrefer -> {memberPrefer.setMember(newMember);}); + newMember.setMemberPreferList(memberPreferList); + + //24.11.21 fix/#7 + //memberAddress 생성 및 연결 + MemberAddress memberAddress = MemberConverter.toMemberAddress(newMember, region, request); + + + memberAddress.setMember(newMember); + newMember.setAddress(memberAddress); + + memberAddressRepository.save(memberAddress); + + return memberRepository.save(newMember); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/MissionCommandService/MissionCommandService.java b/src/main/java/javalab/umc7th_mission/service/MissionCommandService/MissionCommandService.java new file mode 100644 index 0000000..273a8f3 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/MissionCommandService/MissionCommandService.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.service.MissionCommandService; + +import javalab.umc7th_mission.domain.Mission; +import javalab.umc7th_mission.web.dto.MissionRequestDTO; + +public interface MissionCommandService { + Mission addMission(MissionRequestDTO.AddDTO request); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/MissionCommandService/MissionCommandServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/MissionCommandService/MissionCommandServiceImpl.java new file mode 100644 index 0000000..56e0263 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/MissionCommandService/MissionCommandServiceImpl.java @@ -0,0 +1,28 @@ +package javalab.umc7th_mission.service.MissionCommandService; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.apiPayload.exception.StoreNotFoundException; +import javalab.umc7th_mission.converter.MissionConverter; +import javalab.umc7th_mission.domain.Mission; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.repository.MissionRepository.MissionRepository; +import javalab.umc7th_mission.repository.StoreRepository.StoreRepository; +import javalab.umc7th_mission.web.dto.MissionRequestDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class MissionCommandServiceImpl implements MissionCommandService { + private final StoreRepository storeRepository; + private final MissionRepository missionRepository; + + @Override + public Mission addMission(MissionRequestDTO.AddDTO request) { + Store store = storeRepository.findById(request.getStoreId()) + .orElseThrow(() -> new StoreNotFoundException(ErrorStatus.STORE_NOT_FOUND)); + + Mission newMission = MissionConverter.toMission(store, request); + return missionRepository.save(newMission); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/ReviewCommandService/ReviewCommandService.java b/src/main/java/javalab/umc7th_mission/service/ReviewCommandService/ReviewCommandService.java new file mode 100644 index 0000000..89150fb --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/ReviewCommandService/ReviewCommandService.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.service.ReviewCommandService; + +import javalab.umc7th_mission.domain.Review; +import javalab.umc7th_mission.web.dto.ReviewRequestDTO; + +public interface ReviewCommandService { + Review addReview(ReviewRequestDTO.AddDTO request); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/ReviewCommandService/ReviewCommandServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/ReviewCommandService/ReviewCommandServiceImpl.java new file mode 100644 index 0000000..ed175d8 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/ReviewCommandService/ReviewCommandServiceImpl.java @@ -0,0 +1,38 @@ +package javalab.umc7th_mission.service.ReviewCommandService; + +import jakarta.transaction.Transactional; +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.apiPayload.exception.MemberNotFoundException; +import javalab.umc7th_mission.apiPayload.exception.StoreNotFoundException; +import javalab.umc7th_mission.converter.ReviewConverter; +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Review; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.repository.MemberRepository.MemberRepository; +import javalab.umc7th_mission.repository.ReviewRepository.ReviewRepository; +import javalab.umc7th_mission.repository.StoreRepository.StoreRepository; +import javalab.umc7th_mission.web.dto.ReviewRequestDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReviewCommandServiceImpl implements ReviewCommandService { + private final ReviewRepository reviewRepository; + private final MemberRepository memberRepository; + private final StoreRepository storeRepository; + + @Transactional + @Override + public Review addReview(ReviewRequestDTO.AddDTO request) { + Member member = memberRepository.findById(request.getMemberId()) + .orElseThrow(() -> new MemberNotFoundException(ErrorStatus.MEMBER_NOT_FOUND)); + + Store store = storeRepository.findById(request.getStoreId()) + .orElseThrow(() -> new StoreNotFoundException(ErrorStatus.STORE_NOT_FOUND)); + + Review newReview = ReviewConverter.toReview(member, store, request); + + return reviewRepository.save(newReview); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/StoreCommandService/StoreCommandService.java b/src/main/java/javalab/umc7th_mission/service/StoreCommandService/StoreCommandService.java new file mode 100644 index 0000000..8cfd8fc --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/StoreCommandService/StoreCommandService.java @@ -0,0 +1,9 @@ +package javalab.umc7th_mission.service.StoreCommandService; + +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.web.dto.StoreRequestDTO; + +public interface StoreCommandService { + // 가게 저장 + Store addStore(StoreRequestDTO.AddDto request); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/StoreCommandService/StoreCommandServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/StoreCommandService/StoreCommandServiceImpl.java new file mode 100644 index 0000000..f2ebb2c --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/StoreCommandService/StoreCommandServiceImpl.java @@ -0,0 +1,62 @@ +package javalab.umc7th_mission.service.StoreCommandService; + +import jakarta.transaction.Transactional; +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.apiPayload.exception.FoodCategoryNotFoundException; +import javalab.umc7th_mission.apiPayload.exception.RegionNotFoundException; +import javalab.umc7th_mission.converter.StoreCategoryConverter; +import javalab.umc7th_mission.converter.StoreConverter; +import javalab.umc7th_mission.domain.FoodCategory; +import javalab.umc7th_mission.domain.Region; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.domain.mapping.StoreAddress; +import javalab.umc7th_mission.domain.mapping.StoreCategory; +import javalab.umc7th_mission.repository.FoodCategoryRepository.FoodCategoryRepository; +import javalab.umc7th_mission.repository.RegionRepository.RegionRepository; +import javalab.umc7th_mission.repository.StoreAddressRepository.StoreAddressRepository; +import javalab.umc7th_mission.repository.StoreRepository.StoreRepository; +import javalab.umc7th_mission.web.dto.StoreRequestDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class StoreCommandServiceImpl implements StoreCommandService { + private final StoreRepository storeRepository; + private final StoreAddressRepository storeAddressRepository; + private final RegionRepository regionRepository; + private final FoodCategoryRepository foodCategoryRepository; + + @Override + @Transactional + public Store addStore(StoreRequestDTO.AddDto request) { + Region region = regionRepository.findByName(request.getRegion()); + if (region == null) { + throw new RegionNotFoundException(ErrorStatus.REGION_NOT_FOUND); + } + + + Store newStore = StoreConverter.toStore(request); + StoreAddress storeAddress = StoreConverter.toStoreAddress(newStore, region, request); + + //StoreCategory 생성필요 + //foodCategory list 조회 + List foodCategoryList = request.getStoreCategory().stream() + .map(category -> { + return foodCategoryRepository.findById(category).orElseThrow(() -> new FoodCategoryNotFoundException(ErrorStatus.FOOD_CATEGORY_NOT_FOUND)); + }).collect(Collectors.toList()); + + List storeCategoryList = StoreCategoryConverter.toStoreCategoryList(foodCategoryList); + storeCategoryList.forEach(memberPrefer -> {memberPrefer.setStore(newStore);}); + + newStore.setCategoryList(storeCategoryList); + storeAddress.setStore(newStore); + newStore.setAddress(storeAddress); + + storeAddressRepository.save(storeAddress); + return storeRepository.save(newStore); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/StoreValidationService/StoreValidationService.java b/src/main/java/javalab/umc7th_mission/service/StoreValidationService/StoreValidationService.java new file mode 100644 index 0000000..5280b9a --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/StoreValidationService/StoreValidationService.java @@ -0,0 +1,5 @@ +package javalab.umc7th_mission.service.StoreValidationService; + +public interface StoreValidationService { + boolean isStoreExist(Long id); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/StoreValidationService/StoreValidationServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/StoreValidationService/StoreValidationServiceImpl.java new file mode 100644 index 0000000..2cf72ae --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/StoreValidationService/StoreValidationServiceImpl.java @@ -0,0 +1,16 @@ +package javalab.umc7th_mission.service.StoreValidationService; + +import javalab.umc7th_mission.repository.StoreRepository.StoreRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class StoreValidationServiceImpl implements StoreValidationService { + private final StoreRepository storeRepository; + + @Override + public boolean isStoreExist(Long id) { + return storeRepository.existsById(id); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/TempService/TempCommandService.java b/src/main/java/javalab/umc7th_mission/service/TempService/TempCommandService.java new file mode 100644 index 0000000..871d625 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/TempService/TempCommandService.java @@ -0,0 +1,5 @@ +package javalab.umc7th_mission.service.TempService; + +public interface TempCommandService { + +} diff --git a/src/main/java/javalab/umc7th_mission/service/TempService/TempCommandServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/TempService/TempCommandServiceImpl.java new file mode 100644 index 0000000..2aae4ee --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/TempService/TempCommandServiceImpl.java @@ -0,0 +1,11 @@ +package umc.study.service.TempService; + +import javalab.umc7th_mission.service.TempService.TempCommandService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TempCommandServiceImpl implements TempCommandService { + +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/TempService/TempQueryService.java b/src/main/java/javalab/umc7th_mission/service/TempService/TempQueryService.java new file mode 100644 index 0000000..03bc4ae --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/TempService/TempQueryService.java @@ -0,0 +1,6 @@ +package javalab.umc7th_mission.service.TempService; + +public interface TempQueryService { + + void CheckFlag(Integer flag); +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/service/TempService/TempQueryServiceImpl.java b/src/main/java/javalab/umc7th_mission/service/TempService/TempQueryServiceImpl.java new file mode 100644 index 0000000..365ae50 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/service/TempService/TempQueryServiceImpl.java @@ -0,0 +1,17 @@ +package javalab.umc7th_mission.service.TempService; + +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.apiPayload.exception.handler.TempHandler; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TempQueryServiceImpl implements TempQueryService{ + + @Override + public void CheckFlag(Integer flag) { + if (flag == 1) + throw new TempHandler(ErrorStatus.TEMP_EXCEPTION); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/validation/annotation/ExistCategories.java b/src/main/java/javalab/umc7th_mission/validation/annotation/ExistCategories.java new file mode 100644 index 0000000..dcaa56d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/validation/annotation/ExistCategories.java @@ -0,0 +1,18 @@ +package javalab.umc7th_mission.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import javalab.umc7th_mission.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 {}; +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/validation/annotation/ExistStore.java b/src/main/java/javalab/umc7th_mission/validation/annotation/ExistStore.java new file mode 100644 index 0000000..8f7c042 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/validation/annotation/ExistStore.java @@ -0,0 +1,18 @@ +package javalab.umc7th_mission.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import javalab.umc7th_mission.validation.validator.StoreExistValidator; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = StoreExistValidator.class) +@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistStore { + + String message() default "해당하는 상점이 존재하지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/validation/annotation/MissionNotInProgress.java b/src/main/java/javalab/umc7th_mission/validation/annotation/MissionNotInProgress.java new file mode 100644 index 0000000..94297d0 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/validation/annotation/MissionNotInProgress.java @@ -0,0 +1,19 @@ +package javalab.umc7th_mission.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import javalab.umc7th_mission.repository.MemberMissionRepository.MemberMissionRepository; +import javalab.umc7th_mission.validation.validator.MissionNotInProgressValidator; + + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = MissionNotInProgressValidator.class) +@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface MissionNotInProgress { + String message() default "해당 하는 미션이 이미 진행중입니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/validation/validator/CategoriesExistValidator.java b/src/main/java/javalab/umc7th_mission/validation/validator/CategoriesExistValidator.java new file mode 100644 index 0000000..a295a8d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/validation/validator/CategoriesExistValidator.java @@ -0,0 +1,35 @@ +package javalab.umc7th_mission.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.service.FoodCategoryService.FoodCategoryService; +import javalab.umc7th_mission.validation.annotation.ExistCategories; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +public class CategoriesExistValidator implements ConstraintValidator> { + private final FoodCategoryService foodCategoryService; + + @Override + public void initialize(ExistCategories constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(List values, ConstraintValidatorContext context) { + //개선점: 리포지토리는 "반드시" 서비스단에서만 접근해야됨 -> 간접 접근으로 변경 + boolean isValid = foodCategoryService.allCategoriesExist(values); + + if (!isValid) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.FOOD_CATEGORY_NOT_FOUND.toString()).addConstraintViolation(); + } + + return isValid; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/validation/validator/MissionNotInProgressValidator.java b/src/main/java/javalab/umc7th_mission/validation/validator/MissionNotInProgressValidator.java new file mode 100644 index 0000000..b251902 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/validation/validator/MissionNotInProgressValidator.java @@ -0,0 +1,42 @@ +package javalab.umc7th_mission.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.repository.MemberMissionRepository.MemberMissionRepository; +import javalab.umc7th_mission.service.MemberMissionCommandService.MemberMissionCommandService; +import javalab.umc7th_mission.validation.annotation.ExistStore; +import javalab.umc7th_mission.validation.annotation.MissionNotInProgress; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + + +@Component +@RequiredArgsConstructor +public class MissionNotInProgressValidator implements ConstraintValidator { + private final MemberMissionCommandService memberMissionCommandService; + @Override + public void initialize(MissionNotInProgress constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Long missionId, ConstraintValidatorContext context) { + if (missionId == null) { + return true; // 미션 ID가 없으면 검증을 통과시킴 + } + + //원래 현재 로그인한 사용자의 ID를 가져와야됨 + //현재는 로그인 기능이 없으니 하드코딩 + Long memberId = 1L; + + // 특정 회원이 해당 미션을 진행 중인지 확인 + boolean isInProgress = memberMissionCommandService.isMissionInProgress(memberId, missionId); + if (isInProgress) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.MISSION_ALREADY_IN_PROGRESS.toString()) + .addConstraintViolation(); + } + return !isInProgress; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/validation/validator/StoreExistValidator.java b/src/main/java/javalab/umc7th_mission/validation/validator/StoreExistValidator.java new file mode 100644 index 0000000..2ebc60b --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/validation/validator/StoreExistValidator.java @@ -0,0 +1,38 @@ +package javalab.umc7th_mission.validation.validator; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import javalab.umc7th_mission.apiPayload.code.status.ErrorStatus; +import javalab.umc7th_mission.service.StoreValidationService.StoreValidationService; +import javalab.umc7th_mission.validation.annotation.ExistCategories; +import javalab.umc7th_mission.validation.annotation.ExistStore; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + + +@Component +@RequiredArgsConstructor +public class StoreExistValidator implements ConstraintValidator { + private final StoreValidationService storeValidationService; + + @Override + public void initialize(ExistStore constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Long storeId, ConstraintValidatorContext context) { + if (storeId == null) { + return false; + } + + boolean isValid = storeValidationService.isStoreExist(storeId); + + if (!isValid) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.STORE_NOT_FOUND.toString()).addConstraintViolation(); + } + + return isValid; + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/controller/MemberMissionRestController.java b/src/main/java/javalab/umc7th_mission/web/controller/MemberMissionRestController.java new file mode 100644 index 0000000..57d6a20 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/controller/MemberMissionRestController.java @@ -0,0 +1,28 @@ +package javalab.umc7th_mission.web.controller; + +import jakarta.validation.Valid; +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.converter.MemberConverter; +import javalab.umc7th_mission.converter.MemberMissionConverter; +import javalab.umc7th_mission.domain.mapping.MemberMission; +import javalab.umc7th_mission.service.MemberMissionCommandService.MemberMissionCommandService; +import javalab.umc7th_mission.web.dto.MemberMissionRequestDTO; +import javalab.umc7th_mission.web.dto.MemberMissionResponseDTO; +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; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/memberMissions") +public class MemberMissionRestController { + private final MemberMissionCommandService memberMissionCommandService; + + @PostMapping("/") + public ApiResponse join(@RequestBody @Valid MemberMissionRequestDTO.AddDTO resquest) { + MemberMission memberMission = memberMissionCommandService.addMemberMission(resquest); + return ApiResponse.onSuccess(MemberMissionConverter.toAddResultDTO(memberMission)); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/controller/MemberRestController.java b/src/main/java/javalab/umc7th_mission/web/controller/MemberRestController.java new file mode 100644 index 0000000..01146e4 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/controller/MemberRestController.java @@ -0,0 +1,27 @@ +package javalab.umc7th_mission.web.controller; + +import jakarta.validation.Valid; +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.converter.MemberConverter; +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.service.MemberService.MemberCommandService; +import javalab.umc7th_mission.web.dto.MemberRequestDTO; +import javalab.umc7th_mission.web.dto.MemberResponseDTO; +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; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/members") +public class MemberRestController { + private final MemberCommandService memberCommandService; + + @PostMapping("/") + public ApiResponse join(@RequestBody @Valid MemberRequestDTO.JoinDto request){ + Member member = memberCommandService.joinMember(request); + return ApiResponse.onSuccess(MemberConverter.toJoinResultDTO(member)); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/controller/MissionRestController.java b/src/main/java/javalab/umc7th_mission/web/controller/MissionRestController.java new file mode 100644 index 0000000..2f95de4 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/controller/MissionRestController.java @@ -0,0 +1,58 @@ +package javalab.umc7th_mission.web.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.converter.MemberConverter; +import javalab.umc7th_mission.converter.MissionConverter; +import javalab.umc7th_mission.converter.ReviewConverter; +import javalab.umc7th_mission.domain.Member; +import javalab.umc7th_mission.domain.Mission; +import javalab.umc7th_mission.domain.Review; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.service.MissionCommandService.MissionCommandService; +import javalab.umc7th_mission.web.dto.*; +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; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/missions") +public class MissionRestController { + private final MissionCommandService missionCommandService; + + @PostMapping("/") + @Operation( + summary = "예시 미션 추가", + description = "새로운 미션을 가게에 추가합니다.", + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = MissionRequestDTO.AddDTO.class), + examples = @ExampleObject( + name = "미션 추가 예시", + value = """ + { + "storeId": 1, + "name": "첫 방문 포인트 이벤트", + "description": "가게 방문 시 +500점 추가 혜택", + "startDate": "2024-11-21", + "endDate": "2024-12-30", + "reward": 1000 + } + """ + ) + ) + ) + ) + public ApiResponse add(@RequestBody @Valid MissionRequestDTO.AddDTO request) { + Mission mission = missionCommandService.addMission(request); + return ApiResponse.onSuccess(MissionConverter.toAddResultDTO(mission)); + } +} diff --git a/src/main/java/javalab/umc7th_mission/web/controller/ReviewRestController.java b/src/main/java/javalab/umc7th_mission/web/controller/ReviewRestController.java new file mode 100644 index 0000000..620632d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/controller/ReviewRestController.java @@ -0,0 +1,27 @@ +package javalab.umc7th_mission.web.controller; + +import jakarta.validation.Valid; +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.converter.ReviewConverter; +import javalab.umc7th_mission.domain.Review; +import javalab.umc7th_mission.service.ReviewCommandService.ReviewCommandService; +import javalab.umc7th_mission.web.dto.ReviewRequestDTO; +import javalab.umc7th_mission.web.dto.ReviewResponseDTO; +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; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/reviews") +public class ReviewRestController { + private final ReviewCommandService reviewCommandService; + + @PostMapping("/") + public ApiResponse add(@RequestBody @Valid ReviewRequestDTO.AddDTO request) { + Review review = reviewCommandService.addReview(request); + return ApiResponse.onSuccess(ReviewConverter.toAddResultDTO(review)); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/controller/StoreRestController.java b/src/main/java/javalab/umc7th_mission/web/controller/StoreRestController.java new file mode 100644 index 0000000..c7e07f6 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/controller/StoreRestController.java @@ -0,0 +1,28 @@ +package javalab.umc7th_mission.web.controller; + +import jakarta.validation.Valid; +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.converter.StoreConverter; +import javalab.umc7th_mission.domain.Store; +import javalab.umc7th_mission.service.StoreCommandService.StoreCommandService; +import javalab.umc7th_mission.web.dto.StoreRequestDTO; +import javalab.umc7th_mission.web.dto.StoreResponseDTO; +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; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/stores") +public class StoreRestController { + private final StoreCommandService storeCommandService; + + @PostMapping("/") + public ApiResponse join(@RequestBody @Valid StoreRequestDTO.AddDto request){ + + Store store = storeCommandService.addStore(request); + return ApiResponse.onSuccess(StoreConverter.toAddResultDTO(store)); + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/controller/TempRestController.java b/src/main/java/javalab/umc7th_mission/web/controller/TempRestController.java new file mode 100644 index 0000000..bb533d2 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/controller/TempRestController.java @@ -0,0 +1,31 @@ +package javalab.umc7th_mission.web.controller; + +import javalab.umc7th_mission.apiPayload.ApiResponse; +import javalab.umc7th_mission.converter.TempConverter; +import javalab.umc7th_mission.service.TempService.TempQueryService; +import javalab.umc7th_mission.web.dto.TempResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/temp") +@RequiredArgsConstructor +public class TempRestController { + + private final TempQueryService tempQueryService; + + @GetMapping("/test") + public ApiResponse testAPI(){ + + return ApiResponse.onSuccess(TempConverter.toTempTestDTO()); + } + + @GetMapping("/exception") + public ApiResponse exceptionAPI(@RequestParam Integer flag){ + tempQueryService.CheckFlag(flag); + return null; + } +} diff --git a/src/main/java/javalab/umc7th_mission/web/dto/MemberInfoDto.java b/src/main/java/javalab/umc7th_mission/web/dto/MemberInfoDto.java index 447391f..913b888 100644 --- a/src/main/java/javalab/umc7th_mission/web/dto/MemberInfoDto.java +++ b/src/main/java/javalab/umc7th_mission/web/dto/MemberInfoDto.java @@ -10,4 +10,4 @@ public class MemberInfoDto { private String email; private Integer points; private String phoneNumber; -} +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/MemberMissionRequestDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/MemberMissionRequestDTO.java new file mode 100644 index 0000000..ef1c8eb --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/MemberMissionRequestDTO.java @@ -0,0 +1,42 @@ +package javalab.umc7th_mission.web.dto; + +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.NotNull; +import javalab.umc7th_mission.validation.annotation.MissionNotInProgress; +import lombok.Getter; + +import java.time.LocalDate; + +public class MemberMissionRequestDTO { + + @Getter + public static class AddDTO { + @NotNull(message = "회원 ID는 필수입니다.") + private final Long memberId; + + @NotNull(message = "미션 ID는 필수입니다.") + @MissionNotInProgress + private final Long missionId; + + @NotNull(message = "시작 날짜는 필수 항목입니다.") + @FutureOrPresent(message = "시작 날짜는 오늘 이후여야 합니다.") + private LocalDate startDate; + + @NotNull(message = "종료 날짜는 필수 항목입니다.") + @Future(message = "종료 날짜는 오늘 이후여야 합니다.") + private LocalDate endDate; + + public AddDTO( + Long memberId, + Long missionId, + LocalDate startDate, + LocalDate endDate + ) { + this.memberId = memberId; + this.missionId = missionId; + this.startDate = startDate; + this.endDate = endDate; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/MemberMissionResponseDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/MemberMissionResponseDTO.java new file mode 100644 index 0000000..ef190df --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/MemberMissionResponseDTO.java @@ -0,0 +1,18 @@ +package javalab.umc7th_mission.web.dto; + +import java.time.LocalDateTime; + +public class MemberMissionResponseDTO { + public static class AddResultDTO{ + private final Long memberMissionId; + private final LocalDateTime createdAt; + + public AddResultDTO(Long memberMissionId, LocalDateTime createdAt) { + this.memberMissionId = memberMissionId; + this.createdAt = createdAt; + } + + public Long getMemberMissionId() { return memberMissionId; } + public LocalDateTime getCreatedAt() { return createdAt; } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/MemberRequestDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/MemberRequestDTO.java new file mode 100644 index 0000000..cd4a666 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/MemberRequestDTO.java @@ -0,0 +1,82 @@ +package javalab.umc7th_mission.web.dto; + +import jakarta.validation.constraints.*; +import javalab.umc7th_mission.domain.enums.Gender; +import javalab.umc7th_mission.validation.annotation.ExistCategories; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + + +public class MemberRequestDTO { + + //회원 가입 시 사용하는 DTO + //빌더를 안쓰고 생성자 주입방식 이용 + @Getter + public static class JoinDto { + @NotBlank(message = "이름은 필수 항목입니다.") + @Size(max = 20, message = "이름은 최대 20자까지 가능합니다.") + private final String name; + + @NotBlank(message = "닉네임은 필수 항목입니다.") + @Size(max = 20, message = "닉네임은 최대 20자까지 가능합니다.") + private final String nickname; + + @NotBlank(message = "전화번호는 필수 항목입니다.") + //전화번호 형식 검증 정규식 + @Pattern(regexp = "^(02|0\\d{2})-\\d{3,4}-\\d{4}$", message = "전화번호 형식이 올바르지 않습니다.") + private final String phoneNumber; + + @NotNull(message = "성별은 필수 항목입니다.") + private final Gender gender; + + @NotBlank(message = "이메일은 필수 항목입니다.") + @Email(message = "이메일 형식이 올바르지 않습니다.") + @Size(max = 50, message = "이메일은 최대 50자까지 가능합니다.") + private final String email; + + //24.11.21 fix/#7 + @NotBlank(message = "지역명은 필수 항목입니다.") + @Size(max = 50, message = "지역명은 최대 50자까지 가능합니다.") + private final String region; + + @NotBlank(message = "세부 주소는 필수 항목입니다.") + @Size(max = 100, message = "세부 주소는 최대 100자까지 가능합니다.") + private final String detailedAddress; + + @NotBlank(message = "우편번호는 필수 항목입니다.") + @Size(max = 40, message = "우편번호는 최대 40자까지 가능합니다.") + private final String zipcode; + + @ExistCategories + List preferCategory; + + /* + 24.11.21 fix/#7 -> remove @ + 유효성 검증은 객체 생성 이후에 처리되도록 설계 -> 생성자에서 어노테이션을 적용할 이유 없음 + */ + public JoinDto( + String name, + String nickname, + String phoneNumber, + Gender gender, + String email, + String region, + String detailedAddress, + String zipcode, + List preferCategory + ) { + this.name = name; + this.nickname = nickname; + this.phoneNumber = phoneNumber; + this.gender = gender; + this.email = email; + this.region = region; + this.detailedAddress = detailedAddress; + this.zipcode = zipcode; + this.preferCategory = preferCategory; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/MemberResponseDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/MemberResponseDTO.java new file mode 100644 index 0000000..cb6bf19 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/MemberResponseDTO.java @@ -0,0 +1,33 @@ +package javalab.umc7th_mission.web.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.mapping.Join; + +import java.time.LocalDateTime; + + +// @NoArgsConstructor -> 불변성 유지를 위해 생성자 여러개 제공 방지 +public class MemberResponseDTO { + public static class JoinResultDTO { + private final Long memberId; + private final LocalDateTime createdAt; + + public JoinResultDTO(Long memberId, LocalDateTime createdAt) { + this.memberId = memberId; + this.createdAt = createdAt; + } + + // 명시적 Getter (Jackson 직렬화를 위해 필요) + public Long getMemberId() { + return memberId; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/MissionRequestDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/MissionRequestDTO.java new file mode 100644 index 0000000..7519774 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/MissionRequestDTO.java @@ -0,0 +1,53 @@ +package javalab.umc7th_mission.web.dto; + +import jakarta.validation.constraints.*; +import javalab.umc7th_mission.validation.annotation.ExistStore; +import lombok.Getter; + +import java.time.LocalDate; + +public class MissionRequestDTO { + + @Getter + public static class AddDTO { + @ExistStore + private Long storeId; + + @NotBlank(message = "미션 이름은 필수 항목입니다.") + @Size(max = 100, message = "미션 이름은 최대 100자까지 입력 가능합니다.") + private String name; + + + @NotBlank(message = "미션 설명은 필수 항목입니다.") + @Size(max = 500, message = "미션 설명은 최대 500자까지 입력 가능합니다.") + private String description; + + @NotNull(message = "시작 날짜는 필수 항목입니다.") + @FutureOrPresent(message = "시작 날짜는 오늘 이후여야 합니다.") + private LocalDate startDate; + + @NotNull(message = "종료 날짜는 필수 항목입니다.") + @Future(message = "종료 날짜는 오늘 이후여야 합니다.") + private LocalDate endDate; + + @NotNull(message = "보상 포인트는 필수 항목입니다.") + @Min(value = 0, message = "보상 포인트는 0 이상이어야 합니다.") + private Integer reward; + + public AddDTO( + Long storeId, + String name, + String description, + LocalDate startDate, + LocalDate endDate, + Integer reward + ) { + this.storeId = storeId; + this.name = name; + this.description = description; + this.startDate = startDate; + this.endDate = endDate; + this.reward = reward; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/MissionResponseDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/MissionResponseDTO.java new file mode 100644 index 0000000..9912fd6 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/MissionResponseDTO.java @@ -0,0 +1,24 @@ +package javalab.umc7th_mission.web.dto; + +import java.time.LocalDateTime; + +public class MissionResponseDTO { + public static class AddResultDTO { + private final Long missionId; + private final LocalDateTime createdAt; + + public AddResultDTO(Long missionId, LocalDateTime createdAt) { + this.missionId = missionId; + this.createdAt = createdAt; + } + + // 명시적 Getter (Jackson 직렬화를 위해 필요) + public Long getMissionId() { + return missionId; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/ReviewRequestDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/ReviewRequestDTO.java new file mode 100644 index 0000000..6c8836c --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/ReviewRequestDTO.java @@ -0,0 +1,45 @@ +package javalab.umc7th_mission.web.dto; + +import jakarta.validation.constraints.*; +import javalab.umc7th_mission.domain.ReviewImage; +import javalab.umc7th_mission.validation.annotation.ExistStore; +import lombok.Getter; + +import java.math.BigDecimal; +import java.util.List; + +public class ReviewRequestDTO { + + @Getter + public static class AddDTO { + @ExistStore + private final Long storeId; + + @NotNull(message = "회원 ID는 필수입니다.") + private final Long memberId; + + @Size(max = 500, message = "리뷰 내용은 최대 500자까지 작성 가능합니다.") + private final String content; + + @DecimalMin(value = "0.0", inclusive = true, message = "별점은 0.0 이상이어야 합니다.") + @DecimalMax(value = "5.0", inclusive = true, message = "별점은 5.0 이하이어야 합니다.") + private final BigDecimal rating; + + private final List reviewImageList; + + public AddDTO( + Long storeId, + Long memberId, + String content, + BigDecimal rating, + List reviewImageList + ) { + this.storeId = storeId; + this.memberId = memberId; + this.content = content; + this.rating = rating; + this.reviewImageList = reviewImageList; + } + + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/ReviewResponseDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/ReviewResponseDTO.java new file mode 100644 index 0000000..fb28952 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/ReviewResponseDTO.java @@ -0,0 +1,24 @@ +package javalab.umc7th_mission.web.dto; + +import java.time.LocalDateTime; + +public class ReviewResponseDTO { + public static class AddResultDTO { + private final Long reviewId; + private final LocalDateTime createdAt; + + public AddResultDTO(Long reviewId, LocalDateTime createdAt) { + this.reviewId = reviewId; + this.createdAt = createdAt; + } + + // 명시적 Getter (Jackson 직렬화를 위해 필요) + public Long getReviewId() { + return reviewId; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/StoreRequestDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/StoreRequestDTO.java new file mode 100644 index 0000000..0dff5b1 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/StoreRequestDTO.java @@ -0,0 +1,74 @@ +package javalab.umc7th_mission.web.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import javalab.umc7th_mission.validation.annotation.ExistCategories; +import lombok.Getter; + +import java.util.List; + +public class StoreRequestDTO { + + @Getter + public static class AddDto { + @NotBlank(message = "가게 이름은 필수 항목입니다.") + @Size(max = 30, message = "최대 30자까지 입력 가능합니다.") + private final String name; + + @NotBlank(message = "전화번호는 필수 항목입니다.") + //전화번호 형식 검증 정규식 + @Pattern(regexp = "^(02|0\\d{2})-\\d{3,4}-\\d{4}$", message = "전화번호 형식이 올바르지 않습니다.") + private final String phoneNumber; + + @NotBlank(message = "가게 설명은 필수 항목입니다.") + @Size(max = 500, message = "최대 500자까지 입력 가능합니다.") + private final String description; + + @NotBlank(message = "오픈 시간은 필수 항목입니다.") + @Size(max = 255, message = "최대 255자까지 입력 가능하니다.") + @Pattern( + regexp = "^([01]?[0-9]|2[0-3]):[0-5][0-9]$", + message = "오픈 시간은 'HH:mm' 형식이어야 합니다. (예: 09:00, 23:59)" + ) + private final String openingHours; + + @NotBlank(message = "마감 시간은 필수 항목입니다.") + @Size(max = 255, message = "최대 255자까지 입력 가능하니다.") + @Pattern( + regexp = "^([01]?[0-9]|2[0-3]):[0-5][0-9]$", + message = "마감 시간은 'HH:mm' 형식이어야 합니다. (예: 09:00, 23:59)" + ) + private final String closingHours; + + private final String region; + private final String detailedAddress; + private final String zipcode; + + @ExistCategories + private final List storeCategory; + + public AddDto( + String name, + String phoneNumber, + String description, + String openingHours, + String closingHours, + + String region, + String detailedAddress, + String zipcode, + List storeCategory + ) { + this.name = name; + this.phoneNumber = phoneNumber; + this.description = description; + this.openingHours = openingHours; + this.closingHours = closingHours; + this.region = region; + this.detailedAddress = detailedAddress; + this.zipcode = zipcode; + this.storeCategory = storeCategory; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/StoreResponseDTO.java b/src/main/java/javalab/umc7th_mission/web/dto/StoreResponseDTO.java new file mode 100644 index 0000000..59b1092 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/StoreResponseDTO.java @@ -0,0 +1,24 @@ +package javalab.umc7th_mission.web.dto; + +import java.time.LocalDateTime; + +public class StoreResponseDTO { + public static class AddResultDTO { + private final Long storeId; + private final LocalDateTime createdAt; + + public AddResultDTO(Long storeId, LocalDateTime createdAt) { + this.storeId = storeId; + this.createdAt = createdAt; + } + + // 명시적 Getter (Jackson 직렬화를 위해 필요) + public Long getStoreId() { + return storeId; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + } +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/web/dto/TempRequest.java b/src/main/java/javalab/umc7th_mission/web/dto/TempRequest.java new file mode 100644 index 0000000..f01fd3a --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/TempRequest.java @@ -0,0 +1,4 @@ +package javalab.umc7th_mission.web.dto; + +public class TempRequest { +} diff --git a/src/main/java/javalab/umc7th_mission/web/dto/TempResponse.java b/src/main/java/javalab/umc7th_mission/web/dto/TempResponse.java new file mode 100644 index 0000000..310105d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/web/dto/TempResponse.java @@ -0,0 +1,25 @@ +package javalab.umc7th_mission.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class TempResponse { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class TempTestDTO{ + String testString; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class TempExceptionDTO{ + Integer flag; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 12f39ad..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=UMC7th_Mission diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..d7745c5 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,19 @@ +spring: + datasource: + url: jdbc:mysql://localhost:3306/study + username: root + password: 425805 + driver-class-name: com.mysql.cj.jdbc.Driver + sql: + init: + mode: never + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + show_sql: true + format_sql: true + use_sql_comments: true + hbm2ddl: + auto: update + default_batch_fetch_size: 1000 \ No newline at end of file