From 3f03735fb9dea0a705c66c862f36ddc2de0fc91b Mon Sep 17 00:00:00 2001 From: tmdcheol Date: Fri, 22 Nov 2024 13:52:37 +0900 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프로젝트 정리 - 패키지 변경 - 불필요한 코드 정리 --- .../config/apipayload/ApiResponse.java | 37 ++++++ .../config/apipayload/code/BaseCode.java | 8 ++ .../config/apipayload/code/BaseErrorCode.java | 8 ++ .../apipayload/code/ErrorReasonDTO.java | 20 +++ .../config/apipayload/code/ReasonDTO.java | 20 +++ .../apipayload/code/status/ErrorStatus.java | 52 ++++++++ .../apipayload/code/status/SuccessStatus.java | 37 ++++++ .../apipayload/exception/ExceptionAdvice.java | 121 ++++++++++++++++++ .../exception/GeneralException.java | 22 ++++ .../domain/foodcategory/FoodCategory.java | 2 +- .../umc7th_mission/domain/member/Member.java | 2 +- .../repository/CustomMemberRepository.java | 10 -- .../CustomMemberRepositoryImpl.java | 29 ----- .../domain/memberagree/MemberAgree.java | 6 +- .../domain/membermission/MemberMission.java | 8 +- .../domain/memberprefer/MemberPrefer.java | 6 +- .../domain/mission/Mission.java | 4 +- .../domain/mission/MissionStatus.java | 1 + .../repository/CustomMissionRepository.java | 13 -- .../MissionCustomRepositoryImpl.java | 68 ---------- .../umc7th_mission/domain/region/Region.java | 2 +- .../umc7th_mission/domain/review/Review.java | 6 +- .../domain/review/ReviewImage.java | 3 +- .../umc7th_mission/domain/store/Store.java | 4 +- .../repository/CustomStoreRepository.java | 9 -- .../store/repository/StoreRepositoryImpl.java | 37 ------ .../umc7th_mission/domain/terms/Terms.java | 2 +- 27 files changed, 349 insertions(+), 188 deletions(-) create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/ApiResponse.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/code/BaseCode.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/code/BaseErrorCode.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/code/ErrorReasonDTO.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/code/ReasonDTO.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/code/status/SuccessStatus.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java create mode 100644 src/main/java/javalab/umc7th_mission/config/apipayload/exception/GeneralException.java delete mode 100644 src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepository.java delete mode 100644 src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepositoryImpl.java delete mode 100644 src/main/java/javalab/umc7th_mission/domain/mission/repository/CustomMissionRepository.java delete mode 100644 src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionCustomRepositoryImpl.java delete mode 100644 src/main/java/javalab/umc7th_mission/domain/store/repository/CustomStoreRepository.java delete mode 100644 src/main/java/javalab/umc7th_mission/domain/store/repository/StoreRepositoryImpl.java diff --git a/src/main/java/javalab/umc7th_mission/config/apipayload/ApiResponse.java b/src/main/java/javalab/umc7th_mission/config/apipayload/ApiResponse.java new file mode 100644 index 0000000..60727b1 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/ApiResponse.java @@ -0,0 +1,37 @@ +package javalab.umc7th_mission.config.apipayload; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import javalab.umc7th_mission.config.apipayload.code.BaseCode; +import javalab.umc7th_mission.config.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/config/apipayload/code/BaseCode.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/BaseCode.java new file mode 100644 index 0000000..2090a1e --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/BaseCode.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.config.apipayload.code; + +public interface BaseCode { + + ReasonDTO getReason(); + + ReasonDTO getReasonHttpStatus(); +} diff --git a/src/main/java/javalab/umc7th_mission/config/apipayload/code/BaseErrorCode.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/BaseErrorCode.java new file mode 100644 index 0000000..c849f85 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/BaseErrorCode.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.config.apipayload.code; + +public interface BaseErrorCode { + + ErrorReasonDTO getReason(); + + ErrorReasonDTO getReasonHttpStatus(); +} diff --git a/src/main/java/javalab/umc7th_mission/config/apipayload/code/ErrorReasonDTO.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/ErrorReasonDTO.java new file mode 100644 index 0000000..086205d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/ErrorReasonDTO.java @@ -0,0 +1,20 @@ +package javalab.umc7th_mission.config.apipayload.code; + +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/config/apipayload/code/ReasonDTO.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/ReasonDTO.java new file mode 100644 index 0000000..5acbff4 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/ReasonDTO.java @@ -0,0 +1,20 @@ +package javalab.umc7th_mission.config.apipayload.code; + +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; + } +} diff --git a/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java new file mode 100644 index 0000000..e24598f --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java @@ -0,0 +1,52 @@ +package javalab.umc7th_mission.config.apipayload.code.status; + +import javalab.umc7th_mission.config.apipayload.code.BaseErrorCode; +import javalab.umc7th_mission.config.apipayload.code.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", "금지된 요청입니다."), + + // For test + TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "이거는 테스트"), + + // Member Error + MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "MEMBER4001", "사용자가 없습니다."), + NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST, "MEMBER4002", "닉네임은 필수 입니다."), + + // Article Error + ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."); + + 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/config/apipayload/code/status/SuccessStatus.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/SuccessStatus.java new file mode 100644 index 0000000..d3eb955 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/SuccessStatus.java @@ -0,0 +1,37 @@ +package javalab.umc7th_mission.config.apipayload.code.status; + +import javalab.umc7th_mission.config.apipayload.code.BaseCode; +import javalab.umc7th_mission.config.apipayload.code.ReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum SuccessStatus implements BaseCode { + + _OK(HttpStatus.OK, "COMMON200", "성공입니다."); + + 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/config/apipayload/exception/ExceptionAdvice.java b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java new file mode 100644 index 0000000..ef6089a --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java @@ -0,0 +1,121 @@ +package javalab.umc7th_mission.config.apipayload.exception; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; +import javalab.umc7th_mission.config.apipayload.ApiResponse; +import javalab.umc7th_mission.config.apipayload.code.ErrorReasonDTO; +import javalab.umc7th_mission.config.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.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; + +@Slf4j +@RestControllerAdvice(annotations = {RestController.class}) +public class ExceptionAdvice extends ResponseEntityExceptionHandler { + + @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); + } + + 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/config/apipayload/exception/GeneralException.java b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/GeneralException.java new file mode 100644 index 0000000..4fb0f1b --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/GeneralException.java @@ -0,0 +1,22 @@ +package javalab.umc7th_mission.config.apipayload.exception; + +import javalab.umc7th_mission.config.apipayload.code.BaseErrorCode; +import javalab.umc7th_mission.config.apipayload.code.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GeneralException extends RuntimeException { + + private BaseErrorCode code; + + public ErrorReasonDTO getErrorReason() { + return code.getReason(); + } + + public ErrorReasonDTO getErrorReasonHttpStatus() { + return code.getReasonHttpStatus(); + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/foodcategory/FoodCategory.java b/src/main/java/javalab/umc7th_mission/domain/foodcategory/FoodCategory.java index b0af23a..56c6928 100644 --- a/src/main/java/javalab/umc7th_mission/domain/foodcategory/FoodCategory.java +++ b/src/main/java/javalab/umc7th_mission/domain/foodcategory/FoodCategory.java @@ -6,11 +6,11 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import javalab.umc7th_mission.domain.common.BaseEntity; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/member/Member.java b/src/main/java/javalab/umc7th_mission/domain/member/Member.java index cf66e17..30b2fc5 100644 --- a/src/main/java/javalab/umc7th_mission/domain/member/Member.java +++ b/src/main/java/javalab/umc7th_mission/domain/member/Member.java @@ -10,10 +10,10 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import java.time.LocalDate; +import javalab.umc7th_mission.domain.common.BaseEntity; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; @Getter @Entity diff --git a/src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepository.java b/src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepository.java deleted file mode 100644 index 4e71adb..0000000 --- a/src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package javalab.umc7th_mission.domain.member.repository; - -import com.querydsl.core.Tuple; -import com.querydsl.jpa.impl.JPAQuery; - -public interface CustomMemberRepository { - - JPAQuery missionFour(Long userId); - -} diff --git a/src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepositoryImpl.java deleted file mode 100644 index aeffe83..0000000 --- a/src/main/java/javalab/umc7th_mission/domain/member/repository/CustomMemberRepositoryImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package javalab.umc7th_mission.domain.member.repository; - - -import static umc.umcjpaproject.domain.member.QMember.member; - -import com.querydsl.core.Tuple; -import com.querydsl.jpa.impl.JPAQuery; -import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; - -@RequiredArgsConstructor -@Repository -public class CustomMemberRepositoryImpl implements CustomMemberRepository { - - private final JPAQueryFactory queryFactory; - - @Override - public JPAQuery missionFour(Long userId) { - return queryFactory - .select(member.id, member.name, member.email, member.point) - .from(member) - .join(point).on(point.user.id.eq(user.id)) - .where(user.id.eq(userId).and(user.phoneNumber.isNotNull())) - .orderBy(point.id.asc()) - .limit(1); - } - -} diff --git a/src/main/java/javalab/umc7th_mission/domain/memberagree/MemberAgree.java b/src/main/java/javalab/umc7th_mission/domain/memberagree/MemberAgree.java index a74b6af..1d7dbbc 100644 --- a/src/main/java/javalab/umc7th_mission/domain/memberagree/MemberAgree.java +++ b/src/main/java/javalab/umc7th_mission/domain/memberagree/MemberAgree.java @@ -9,13 +9,13 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import javalab.umc7th_mission.domain.common.BaseEntity; +import javalab.umc7th_mission.domain.member.Member; +import javalab.umc7th_mission.domain.terms.Terms; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; -import umc.umcjpaproject.domain.member.Member; -import umc.umcjpaproject.domain.terms.Terms; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/membermission/MemberMission.java b/src/main/java/javalab/umc7th_mission/domain/membermission/MemberMission.java index 59c563b..63b39a9 100644 --- a/src/main/java/javalab/umc7th_mission/domain/membermission/MemberMission.java +++ b/src/main/java/javalab/umc7th_mission/domain/membermission/MemberMission.java @@ -11,14 +11,14 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import javalab.umc7th_mission.domain.common.BaseEntity; +import javalab.umc7th_mission.domain.member.Member; +import javalab.umc7th_mission.domain.mission.Mission; +import javalab.umc7th_mission.domain.mission.MissionStatus; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; -import umc.umcjpaproject.domain.member.Member; -import umc.umcjpaproject.domain.mission.Mission; -import umc.umcjpaproject.domain.mission.MissionStatus; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPrefer.java b/src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPrefer.java index 3aeb18e..23c8bb0 100644 --- a/src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPrefer.java +++ b/src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPrefer.java @@ -9,13 +9,13 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import javalab.umc7th_mission.domain.common.BaseEntity; +import javalab.umc7th_mission.domain.foodcategory.FoodCategory; +import javalab.umc7th_mission.domain.member.Member; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; -import umc.umcjpaproject.domain.foodcategory.FoodCategory; -import umc.umcjpaproject.domain.member.Member; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/Mission.java b/src/main/java/javalab/umc7th_mission/domain/mission/Mission.java index b63e570..81ab898 100644 --- a/src/main/java/javalab/umc7th_mission/domain/mission/Mission.java +++ b/src/main/java/javalab/umc7th_mission/domain/mission/Mission.java @@ -11,12 +11,12 @@ import jakarta.persistence.Lob; import jakarta.persistence.ManyToOne; import java.time.LocalDateTime; +import javalab.umc7th_mission.domain.common.BaseEntity; +import javalab.umc7th_mission.domain.store.Store; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; -import umc.umcjpaproject.domain.store.Store; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/MissionStatus.java b/src/main/java/javalab/umc7th_mission/domain/mission/MissionStatus.java index 515eebd..c633454 100644 --- a/src/main/java/javalab/umc7th_mission/domain/mission/MissionStatus.java +++ b/src/main/java/javalab/umc7th_mission/domain/mission/MissionStatus.java @@ -1,6 +1,7 @@ package javalab.umc7th_mission.domain.mission; public enum MissionStatus { + CHALLENGING, COMPLETE } diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/repository/CustomMissionRepository.java b/src/main/java/javalab/umc7th_mission/domain/mission/repository/CustomMissionRepository.java deleted file mode 100644 index 1bf5687..0000000 --- a/src/main/java/javalab/umc7th_mission/domain/mission/repository/CustomMissionRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package javalab.umc7th_mission.domain.mission.repository; - -import com.querydsl.core.Tuple; -import java.util.List; - -public interface CustomMissionRepository { - - List missionOne(Long userId, int limit, int offset); - - List missionThree(Long regionId, int limit, int offset); - -} - diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionCustomRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionCustomRepositoryImpl.java deleted file mode 100644 index 07db7c6..0000000 --- a/src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionCustomRepositoryImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package javalab.umc7th_mission.domain.mission.repository; - - -import static umc.umcjpaproject.domain.membermission.QMemberMission.memberMission; -import static umc.umcjpaproject.domain.mission.QMission.mission; -import static umc.umcjpaproject.domain.store.QStore.store; - -import com.querydsl.core.Tuple; -import com.querydsl.jpa.impl.JPAQueryFactory; -import java.time.LocalDateTime; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; - -@RequiredArgsConstructor -@Repository -public class MissionCustomRepositoryImpl implements CustomMissionRepository { - - private final JPAQueryFactory queryFactory; - - @Override - public List missionOne(Long userId, int limit, int offset) { - return queryFactory - .select( - mission.missionSpec, - mission.reward, - memberMission.createdAt) - .from(mission) - .join(mission.store, store) - .join(memberMission).on(mission.id.eq(memberMission.mission.id)) - .where( - memberMission.member.id.eq(userId) - .and(memberMission.status.in(MissionStatus.CHALLENGING, - MissionStatus.COMPLETE)) - ) - .orderBy(memberMission.createdAt.desc(), mission.id.asc(), - memberMission.member.id.asc()) - .limit(limit) - .offset(offset) - .fetch(); - } - - @Override - public List missionThree(Long regionId, int limit, int offset) { - return queryFactory - .select( - store.name, - store.address, - mission.missionSpec, - mission.reward, - mission.deadLine) - .from(mission) - .join(mission.store, store) - .leftJoin(memberMission).on(mission.id.eq(memberMission.mission.id)) - .where(memberMission.member.id.isNull() - .and(store.region.id.eq(regionId)) - .and(mission.deadLine.after(LocalDateTime.now()))) - .orderBy(memberMission.createdAt.asc(), mission.id.asc(), - memberMission.member.id.asc()) - .limit(limit) - .offset(offset) - .fetch(); - } - - -} - - diff --git a/src/main/java/javalab/umc7th_mission/domain/region/Region.java b/src/main/java/javalab/umc7th_mission/domain/region/Region.java index 962a698..d40ade5 100644 --- a/src/main/java/javalab/umc7th_mission/domain/region/Region.java +++ b/src/main/java/javalab/umc7th_mission/domain/region/Region.java @@ -7,10 +7,10 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import javalab.umc7th_mission.domain.common.BaseEntity; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/review/Review.java b/src/main/java/javalab/umc7th_mission/domain/review/Review.java index deec301..9e31b49 100644 --- a/src/main/java/javalab/umc7th_mission/domain/review/Review.java +++ b/src/main/java/javalab/umc7th_mission/domain/review/Review.java @@ -10,13 +10,13 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.Lob; import jakarta.persistence.ManyToOne; +import javalab.umc7th_mission.domain.common.BaseEntity; +import javalab.umc7th_mission.domain.member.Member; +import javalab.umc7th_mission.domain.store.Store; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; -import umc.umcjpaproject.domain.member.Member; -import umc.umcjpaproject.domain.store.Store; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/review/ReviewImage.java b/src/main/java/javalab/umc7th_mission/domain/review/ReviewImage.java index 78cc069..aa79e16 100644 --- a/src/main/java/javalab/umc7th_mission/domain/review/ReviewImage.java +++ b/src/main/java/javalab/umc7th_mission/domain/review/ReviewImage.java @@ -10,10 +10,10 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import javalab.umc7th_mission.domain.common.BaseEntity; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; @Getter @Entity @@ -37,4 +37,5 @@ public ReviewImage(String imageUrl, Review review) { this.imageUrl = imageUrl; this.review = review; } + } diff --git a/src/main/java/javalab/umc7th_mission/domain/store/Store.java b/src/main/java/javalab/umc7th_mission/domain/store/Store.java index b7669ec..80d3886 100644 --- a/src/main/java/javalab/umc7th_mission/domain/store/Store.java +++ b/src/main/java/javalab/umc7th_mission/domain/store/Store.java @@ -10,11 +10,11 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import javalab.umc7th_mission.domain.common.BaseEntity; +import javalab.umc7th_mission.domain.region.Region; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; -import umc.umcjpaproject.domain.region.Region; @Entity @Getter diff --git a/src/main/java/javalab/umc7th_mission/domain/store/repository/CustomStoreRepository.java b/src/main/java/javalab/umc7th_mission/domain/store/repository/CustomStoreRepository.java deleted file mode 100644 index 6ec8b16..0000000 --- a/src/main/java/javalab/umc7th_mission/domain/store/repository/CustomStoreRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package javalab.umc7th_mission.domain.store.repository; - -import java.util.List; -import umc.umcjpaproject.domain.store.Store; - -public interface CustomStoreRepository { - - List dynamicQueryWithBooleanBuilder(String name, Float score); -} diff --git a/src/main/java/javalab/umc7th_mission/domain/store/repository/StoreRepositoryImpl.java b/src/main/java/javalab/umc7th_mission/domain/store/repository/StoreRepositoryImpl.java deleted file mode 100644 index 0e3a804..0000000 --- a/src/main/java/javalab/umc7th_mission/domain/store/repository/StoreRepositoryImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package javalab.umc7th_mission.domain.store.repository; - -import com.querydsl.core.BooleanBuilder; -import com.querydsl.jpa.impl.JPAQueryFactory; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; -import umc.umcjpaproject.domain.store.QStore; -import umc.umcjpaproject.domain.store.Store; - -@Repository -@RequiredArgsConstructor -public class StoreRepositoryImpl implements CustomStoreRepository { - - private final JPAQueryFactory jpaQueryFactory; - private final QStore store = QStore.store; - - @Override - public List dynamicQueryWithBooleanBuilder(String name, Float score) { - BooleanBuilder predicate = new BooleanBuilder(); - - if (name != null) { - predicate.and(store.name.eq(name)); - } - - if (score != null) { - predicate.and(store.score.goe(4.0f)); - } - - return jpaQueryFactory - .selectFrom(store) - .where(predicate) - .fetch(); - } -} - - diff --git a/src/main/java/javalab/umc7th_mission/domain/terms/Terms.java b/src/main/java/javalab/umc7th_mission/domain/terms/Terms.java index 0f3f7c3..32e63d0 100644 --- a/src/main/java/javalab/umc7th_mission/domain/terms/Terms.java +++ b/src/main/java/javalab/umc7th_mission/domain/terms/Terms.java @@ -7,11 +7,11 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Lob; +import javalab.umc7th_mission.domain.common.BaseEntity; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.umcjpaproject.domain.common.BaseEntity; @Entity @Getter From 049aed5670f35a1120781154fb32bcf80c1df6ca Mon Sep 17 00:00:00 2001 From: tmdcheol Date: Fri, 22 Nov 2024 14:11:52 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20application.yml=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 파일 형식 properties -> yml으로 변경 --- src/main/resources/application.properties | 1 - src/main/resources/application.yml | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) delete mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/application.yml 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..ad03659 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:h2:tcp://localhost/~/project/localrdb/umc-study-db + username: sa + password: + driver-class-name: org.h2.Driver + + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + format_sql: true + +logging.level: + org.hibernate.SQL: debug From 301b0825479d0ca5e25f3356e009e73dcaa8dfba Mon Sep 17 00:00:00 2001 From: tmdcheol Date: Fri, 22 Nov 2024 14:58:16 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apipayload/code/status/ErrorStatus.java | 12 +++--- .../repository/FoodCategoryRepository.java | 11 ++++++ .../service/FoodCategoryService.java | 21 ++++++++++ .../umc7th_mission/domain/member/Gender.java | 13 ++++++- .../umc7th_mission/domain/member/Member.java | 2 +- .../member/controller/MemberController.java | 27 +++++++++++++ .../domain/member/dto/MemberConverter.java | 29 ++++++++++++++ .../domain/member/dto/MemberRequest.java | 24 ++++++++++++ .../domain/member/dto/MemberResponse.java | 17 ++++++++ .../member/repository/MemberRepository.java | 8 ++++ .../domain/member/service/MemberService.java | 10 +++++ .../member/service/MemberServiceImpl.java | 39 +++++++++++++++++++ .../memberprefer/MemberPreferConverter.java | 21 ++++++++++ .../repository/MemberPreferRepository.java | 8 ++++ .../service/MemberPreferService.java | 25 ++++++++++++ 15 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 src/main/java/javalab/umc7th_mission/domain/foodcategory/repository/FoodCategoryRepository.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/foodcategory/service/FoodCategoryService.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/member/dto/MemberConverter.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/member/dto/MemberResponse.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/member/repository/MemberRepository.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/member/service/MemberService.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/member/service/MemberServiceImpl.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPreferConverter.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/memberprefer/repository/MemberPreferRepository.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/memberprefer/service/MemberPreferService.java diff --git a/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java index e24598f..f4c59d3 100644 --- a/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java @@ -11,17 +11,15 @@ 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", "금지된 요청입니다."), - - // For test - TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "이거는 테스트"), + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), + BAD_REQUEST(HttpStatus.BAD_REQUEST, "COMMON400", "잘못된 요청입니다."), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "COMMON401", "인증이 필요합니다."), + FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), // Member Error MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "MEMBER4001", "사용자가 없습니다."), NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST, "MEMBER4002", "닉네임은 필수 입니다."), + GENDER_INVALID_DATA(HttpStatus.BAD_REQUEST, "MEMBER4003", "존재하지 않는 성별입니다."), // Article Error ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."); diff --git a/src/main/java/javalab/umc7th_mission/domain/foodcategory/repository/FoodCategoryRepository.java b/src/main/java/javalab/umc7th_mission/domain/foodcategory/repository/FoodCategoryRepository.java new file mode 100644 index 0000000..40a72a7 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/foodcategory/repository/FoodCategoryRepository.java @@ -0,0 +1,11 @@ +package javalab.umc7th_mission.domain.foodcategory.repository; + +import java.util.List; +import javalab.umc7th_mission.domain.foodcategory.FoodCategory; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FoodCategoryRepository extends JpaRepository { + + List findByIdIn(List ids); + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/foodcategory/service/FoodCategoryService.java b/src/main/java/javalab/umc7th_mission/domain/foodcategory/service/FoodCategoryService.java new file mode 100644 index 0000000..16a5ac1 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/foodcategory/service/FoodCategoryService.java @@ -0,0 +1,21 @@ +package javalab.umc7th_mission.domain.foodcategory.service; + +import java.util.List; +import javalab.umc7th_mission.domain.foodcategory.FoodCategory; +import javalab.umc7th_mission.domain.foodcategory.repository.FoodCategoryRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class FoodCategoryService { + + private final FoodCategoryRepository repository; + + public List getByIds(List ids) { + return repository.findByIdIn(ids); + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/member/Gender.java b/src/main/java/javalab/umc7th_mission/domain/member/Gender.java index 0c2e343..0f3fcd9 100644 --- a/src/main/java/javalab/umc7th_mission/domain/member/Gender.java +++ b/src/main/java/javalab/umc7th_mission/domain/member/Gender.java @@ -1,7 +1,18 @@ package javalab.umc7th_mission.domain.member; +import javalab.umc7th_mission.config.apipayload.code.status.ErrorStatus; +import javalab.umc7th_mission.config.apipayload.exception.GeneralException; + public enum Gender { - FEMALE, MALE + FEMALE, MALE; + + public static Gender to(String value) { + try { + return Gender.valueOf(value); + } catch (IllegalArgumentException e) { + throw new GeneralException(ErrorStatus.GENDER_INVALID_DATA); + } + } } diff --git a/src/main/java/javalab/umc7th_mission/domain/member/Member.java b/src/main/java/javalab/umc7th_mission/domain/member/Member.java index 30b2fc5..f9dc0bf 100644 --- a/src/main/java/javalab/umc7th_mission/domain/member/Member.java +++ b/src/main/java/javalab/umc7th_mission/domain/member/Member.java @@ -49,7 +49,7 @@ public class Member extends BaseEntity { @Enumerated(STRING) private SocialType socialType; - @Column(nullable = false, length = 50) + @Column(length = 50) private String email; private Integer point; diff --git a/src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java b/src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java new file mode 100644 index 0000000..a0b4134 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java @@ -0,0 +1,27 @@ +package javalab.umc7th_mission.domain.member.controller; + +import javalab.umc7th_mission.domain.member.dto.MemberRequest.JoinDTO; +import javalab.umc7th_mission.domain.member.dto.MemberResponse.JoinResultDTO; +import javalab.umc7th_mission.domain.member.service.MemberService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +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 MemberController { + + private final MemberService service; + + @PostMapping("/") + public JoinResultDTO join( + @RequestBody @Validated JoinDTO request + ){ + return service.join(request); + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberConverter.java b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberConverter.java new file mode 100644 index 0000000..db4178e --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberConverter.java @@ -0,0 +1,29 @@ +package javalab.umc7th_mission.domain.member.dto; + +import java.time.LocalDateTime; +import javalab.umc7th_mission.domain.member.Gender; +import javalab.umc7th_mission.domain.member.Member; + +public final class MemberConverter { + + private MemberConverter() { + } + + public static MemberResponse.JoinResultDTO to(Member member) { + return new MemberResponse.JoinResultDTO( + member.getId(), + LocalDateTime.now() + ); + } + + public static Member to(MemberRequest.JoinDTO request) { + return Member.builder() + .address(request.address()) + .specAddress(request.specAddress()) + .gender(Gender.to(request.gender())) + .name(request.name()) + .age(request.age()) + .build(); + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java new file mode 100644 index 0000000..c8267a6 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java @@ -0,0 +1,24 @@ +package javalab.umc7th_mission.domain.member.dto; + +import java.util.List; + +public final class MemberRequest { + + private MemberRequest() { + } + + public record JoinDTO( + String name, + String gender, + Integer age, + Integer birthYear, + Integer birthMonth, + Integer birthDay, + String address, + String specAddress, + List preferCategoryIds + ) { + + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberResponse.java b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberResponse.java new file mode 100644 index 0000000..d2891bf --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberResponse.java @@ -0,0 +1,17 @@ +package javalab.umc7th_mission.domain.member.dto; + +import java.time.LocalDateTime; + +public final class MemberResponse { + + private MemberResponse() { + } + + public record JoinResultDTO( + Long memberId, + LocalDateTime createdAt + ) { + + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/member/repository/MemberRepository.java b/src/main/java/javalab/umc7th_mission/domain/member/repository/MemberRepository.java new file mode 100644 index 0000000..1f063d6 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/member/repository/MemberRepository.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.domain.member.repository; + +import javalab.umc7th_mission.domain.member.Member; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/domain/member/service/MemberService.java b/src/main/java/javalab/umc7th_mission/domain/member/service/MemberService.java new file mode 100644 index 0000000..c04356d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/member/service/MemberService.java @@ -0,0 +1,10 @@ +package javalab.umc7th_mission.domain.member.service; + +import javalab.umc7th_mission.domain.member.dto.MemberRequest; +import javalab.umc7th_mission.domain.member.dto.MemberResponse; + +public interface MemberService { + + MemberResponse.JoinResultDTO join(MemberRequest.JoinDTO request); + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/member/service/MemberServiceImpl.java b/src/main/java/javalab/umc7th_mission/domain/member/service/MemberServiceImpl.java new file mode 100644 index 0000000..319fa6d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/member/service/MemberServiceImpl.java @@ -0,0 +1,39 @@ +package javalab.umc7th_mission.domain.member.service; + +import java.util.List; +import javalab.umc7th_mission.domain.foodcategory.FoodCategory; +import javalab.umc7th_mission.domain.foodcategory.service.FoodCategoryService; +import javalab.umc7th_mission.domain.member.Member; +import javalab.umc7th_mission.domain.member.dto.MemberConverter; +import javalab.umc7th_mission.domain.member.dto.MemberRequest.JoinDTO; +import javalab.umc7th_mission.domain.member.dto.MemberResponse; +import javalab.umc7th_mission.domain.member.repository.MemberRepository; +import javalab.umc7th_mission.domain.memberprefer.service.MemberPreferService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberServiceImpl implements MemberService { + + private final MemberRepository memberRepository; + private final MemberPreferService memberPreferService; + private final FoodCategoryService foodCategoryService; + + @Override + @Transactional + public MemberResponse.JoinResultDTO join(JoinDTO request) { + Member member = MemberConverter.to(request); + memberRepository.save(member); + + List foodCategories = foodCategoryService + .getByIds(request.preferCategoryIds()); + + memberPreferService.saveMemberPrefers(member, foodCategories); + + return MemberConverter.to(member); + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPreferConverter.java b/src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPreferConverter.java new file mode 100644 index 0000000..023ac4c --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/memberprefer/MemberPreferConverter.java @@ -0,0 +1,21 @@ +package javalab.umc7th_mission.domain.memberprefer; + +import java.util.List; +import javalab.umc7th_mission.domain.foodcategory.FoodCategory; +import javalab.umc7th_mission.domain.member.Member; + +public final class MemberPreferConverter { + + private MemberPreferConverter() { + } + + public static List to(Member member, List foodCategories) { + return foodCategories.stream() + .map(foodCategory -> MemberPrefer.builder() + .member(member) + .foodCategory(foodCategory) + .build()) + .toList(); + } + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/memberprefer/repository/MemberPreferRepository.java b/src/main/java/javalab/umc7th_mission/domain/memberprefer/repository/MemberPreferRepository.java new file mode 100644 index 0000000..d35fa8d --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/memberprefer/repository/MemberPreferRepository.java @@ -0,0 +1,8 @@ +package javalab.umc7th_mission.domain.memberprefer.repository; + +import javalab.umc7th_mission.domain.memberprefer.MemberPrefer; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberPreferRepository extends JpaRepository { + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/memberprefer/service/MemberPreferService.java b/src/main/java/javalab/umc7th_mission/domain/memberprefer/service/MemberPreferService.java new file mode 100644 index 0000000..a4d01f5 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/memberprefer/service/MemberPreferService.java @@ -0,0 +1,25 @@ +package javalab.umc7th_mission.domain.memberprefer.service; + +import java.util.List; +import javalab.umc7th_mission.domain.foodcategory.FoodCategory; +import javalab.umc7th_mission.domain.member.Member; +import javalab.umc7th_mission.domain.memberprefer.MemberPrefer; +import javalab.umc7th_mission.domain.memberprefer.MemberPreferConverter; +import javalab.umc7th_mission.domain.memberprefer.repository.MemberPreferRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberPreferService { + + private final MemberPreferRepository memberPreferRepository; + + @Transactional + public void saveMemberPrefers(Member member, List foodCategories) { + List memberPrefers = MemberPreferConverter.to(member, foodCategories); + memberPreferRepository.saveAll(memberPrefers); + } +} From 3d8632c20c0fbf91c7698c8b1c85110f1b4a1621 Mon Sep 17 00:00:00 2001 From: tmdcheol Date: Fri, 22 Nov 2024 15:04:17 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20swagger=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 스웨거 설정추가 - 회원 제약 사항 추가 --- build.gradle | 8 ++-- .../umc7th_mission/config/SwaggerConfig.java | 38 +++++++++++++++++++ .../apipayload/exception/ExceptionAdvice.java | 9 ----- .../umc7th_mission/domain/member/Member.java | 6 +++ 4 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 src/main/java/javalab/umc7th_mission/config/SwaggerConfig.java diff --git a/build.gradle b/build.gradle index 095155d..d80a816 100644 --- a/build.gradle +++ b/build.gradle @@ -29,19 +29,21 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' + // swagger + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' - //test 롬복 사용 + // test lombok testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' - - //Querydsl 추가 + // querydsl implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" 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..9099fe6 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/SwaggerConfig.java @@ -0,0 +1,38 @@ +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"; + SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName); + + 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/config/apipayload/exception/ExceptionAdvice.java b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java index ef6089a..052be37 100644 --- a/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java @@ -44,15 +44,6 @@ public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotVali 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) { diff --git a/src/main/java/javalab/umc7th_mission/domain/member/Member.java b/src/main/java/javalab/umc7th_mission/domain/member/Member.java index f9dc0bf..e4b8db7 100644 --- a/src/main/java/javalab/umc7th_mission/domain/member/Member.java +++ b/src/main/java/javalab/umc7th_mission/domain/member/Member.java @@ -14,10 +14,15 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; @Getter @Entity @NoArgsConstructor(access = PROTECTED) +@DynamicUpdate +@DynamicInsert public class Member extends BaseEntity { @Id @@ -52,6 +57,7 @@ public class Member extends BaseEntity { @Column(length = 50) private String email; + @ColumnDefault("0") private Integer point; @Builder From 1f26d08d56fecbe8c1022e0c455c0c1673ebd10d Mon Sep 17 00:00:00 2001 From: tmdcheol Date: Fri, 22 Nov 2024 15:30:26 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20CategoriesExistValidator=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - validator 를 repository 로 접근 대신 service 에 의존하도록 변경 --- .../apipayload/code/status/ErrorStatus.java | 3 ++ .../apipayload/exception/ExceptionAdvice.java | 23 ++++++++++++ .../validation/CategoriesExistValidator.java | 37 +++++++++++++++++++ .../config/validation/ExistCategories.java | 22 +++++++++++ .../member/controller/MemberController.java | 4 +- .../domain/member/dto/MemberRequest.java | 22 ++++++----- src/main/resources/messages.properties | 1 + 7 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 src/main/java/javalab/umc7th_mission/config/validation/CategoriesExistValidator.java create mode 100644 src/main/java/javalab/umc7th_mission/config/validation/ExistCategories.java create mode 100644 src/main/resources/messages.properties diff --git a/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java index f4c59d3..7fe76ca 100644 --- a/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/code/status/ErrorStatus.java @@ -21,6 +21,9 @@ public enum ErrorStatus implements BaseErrorCode { NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST, "MEMBER4002", "닉네임은 필수 입니다."), GENDER_INVALID_DATA(HttpStatus.BAD_REQUEST, "MEMBER4003", "존재하지 않는 성별입니다."), + // FoodCategory Error + FOOD_CATEGORY_NOT_FOUND(HttpStatus.BAD_REQUEST, "FOODCATEGORY4003", "존재하지 않는 음식카테고리입니다."), + // Article Error ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."); diff --git a/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java index 052be37..8a53d07 100644 --- a/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java +++ b/src/main/java/javalab/umc7th_mission/config/apipayload/exception/ExceptionAdvice.java @@ -1,6 +1,7 @@ package javalab.umc7th_mission.config.apipayload.exception; import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; @@ -24,6 +25,19 @@ @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) { @@ -44,6 +58,14 @@ public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotVali ErrorStatus.valueOf("_BAD_REQUEST"), request, errors); } + @ExceptionHandler + public ResponseEntity exception(Exception e, WebRequest request) { + log.error("exception:{}", e.getMessage()); + 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) { @@ -109,4 +131,5 @@ private ResponseEntity handleExceptionInternalConstraint(Exception e, request ); } + } \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/config/validation/CategoriesExistValidator.java b/src/main/java/javalab/umc7th_mission/config/validation/CategoriesExistValidator.java new file mode 100644 index 0000000..4f2ee12 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/validation/CategoriesExistValidator.java @@ -0,0 +1,37 @@ +package javalab.umc7th_mission.config.validation; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import java.util.List; +import javalab.umc7th_mission.config.apipayload.code.status.ErrorStatus; +import javalab.umc7th_mission.domain.foodcategory.FoodCategory; +import javalab.umc7th_mission.domain.foodcategory.service.FoodCategoryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class CategoriesExistValidator implements ConstraintValidator> { + + private final FoodCategoryService service; + + @Override + public void initialize(ExistCategories constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(List values, ConstraintValidatorContext context) { + List foodCategories = service.getByIds(values); + boolean isValid = foodCategories.size() == values.size(); + + 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/config/validation/ExistCategories.java b/src/main/java/javalab/umc7th_mission/config/validation/ExistCategories.java new file mode 100644 index 0000000..16468e5 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/config/validation/ExistCategories.java @@ -0,0 +1,22 @@ +package javalab.umc7th_mission.config.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Constraint(validatedBy = CategoriesExistValidator.class) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistCategories { + + String message() default "{Category}"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java b/src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java index a0b4134..d4095ae 100644 --- a/src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java +++ b/src/main/java/javalab/umc7th_mission/domain/member/controller/MemberController.java @@ -1,10 +1,10 @@ package javalab.umc7th_mission.domain.member.controller; +import jakarta.validation.Valid; import javalab.umc7th_mission.domain.member.dto.MemberRequest.JoinDTO; import javalab.umc7th_mission.domain.member.dto.MemberResponse.JoinResultDTO; import javalab.umc7th_mission.domain.member.service.MemberService; import lombok.RequiredArgsConstructor; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -19,7 +19,7 @@ public class MemberController { @PostMapping("/") public JoinResultDTO join( - @RequestBody @Validated JoinDTO request + @RequestBody @Valid JoinDTO request ){ return service.join(request); } diff --git a/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java index c8267a6..9a9930e 100644 --- a/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java +++ b/src/main/java/javalab/umc7th_mission/domain/member/dto/MemberRequest.java @@ -1,6 +1,10 @@ package javalab.umc7th_mission.domain.member.dto; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import java.util.List; +import javalab.umc7th_mission.config.validation.ExistCategories; public final class MemberRequest { @@ -8,15 +12,15 @@ private MemberRequest() { } public record JoinDTO( - String name, - String gender, - Integer age, - Integer birthYear, - Integer birthMonth, - Integer birthDay, - String address, - String specAddress, - List preferCategoryIds + @NotBlank String name, + @NotBlank String gender, + @NotNull Integer age, + @NotNull Integer birthYear, + @NotNull Integer birthMonth, + @NotNull Integer birthDay, + @Size(min = 5, max = 12) String address, + @Size(min = 5, max = 12) String specAddress, + @ExistCategories List preferCategoryIds ) { } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties new file mode 100644 index 0000000..235f9ae --- /dev/null +++ b/src/main/resources/messages.properties @@ -0,0 +1 @@ +Category=???? ????? ???? ????. \ No newline at end of file From de0def307bd9a6eaccfb4c8947139d80b9729c48 Mon Sep 17 00:00:00 2001 From: tmdcheol Date: Fri, 29 Nov 2024 16:11:44 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=209=EC=A3=BC=EC=B0=A8=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=88=98=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MemberMissionController.java | 44 ++++++++++++++++++ .../dto/MemberMissionResponseDTO.java | 11 +++++ .../repository/MemberMissionRepository.java | 14 ++++++ .../service/MemberMissionService.java | 46 +++++++++++++++++++ .../mission/controller/MissionController.java | 34 ++++++++++++++ .../mission/dto/MissionResponseDto.java | 11 +++++ .../mission/repository/MissionRepository.java | 12 +++++ .../mission/service/MissionService.java | 27 +++++++++++ .../review/controller/ReviewController.java | 31 +++++++++++++ .../domain/review/dto/ReviewRequest.java | 5 ++ .../domain/review/dto/ReviewResponse.java | 25 ++++++++++ .../review/repository/ReviewRepository.java | 12 +++++ .../domain/review/service/ReviewService.java | 38 +++++++++++++++ 13 files changed, 310 insertions(+) create mode 100644 src/main/java/javalab/umc7th_mission/domain/membermission/controller/MemberMissionController.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/membermission/dto/MemberMissionResponseDTO.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/membermission/repository/MemberMissionRepository.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/membermission/service/MemberMissionService.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/mission/controller/MissionController.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/mission/dto/MissionResponseDto.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionRepository.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/mission/service/MissionService.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/review/controller/ReviewController.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewRequest.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewResponse.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/review/repository/ReviewRepository.java create mode 100644 src/main/java/javalab/umc7th_mission/domain/review/service/ReviewService.java diff --git a/src/main/java/javalab/umc7th_mission/domain/membermission/controller/MemberMissionController.java b/src/main/java/javalab/umc7th_mission/domain/membermission/controller/MemberMissionController.java new file mode 100644 index 0000000..2b053ec --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/membermission/controller/MemberMissionController.java @@ -0,0 +1,44 @@ +package javalab.umc7th_mission.domain.membermission.controller; + +import javalab.umc7th_mission.config.annotation.CheckPage; +import javalab.umc7th_mission.config.apipayload.ApiResponse; +import javalab.umc7th_mission.domain.membermission.dto.MemberMissionResponseDTO; +import javalab.umc7th_mission.domain.membermission.service.MemberMissionService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/missions") +public class MemberMissionController { + + private final MemberMissionService memberMissionService; + private static final Integer PAGE_SIZE = 10; + + @GetMapping("/member/{memberId}/ongoing") + public ApiResponse> getOngoingMissionsByMember( + @PathVariable Long memberId, + @RequestParam @CheckPage Integer page + ) { + Pageable pageable = PageRequest.of(page, PAGE_SIZE); + return ApiResponse.onSuccess( + memberMissionService.getOngoingMissionsByMember(memberId, pageable)); + } + + @PatchMapping("/member/{memberId}/complete/{missionId}") + public ResponseEntity completeMission( + @PathVariable Long memberId, + @PathVariable Long missionId + ) { + memberMissionService.completeMission(memberId, missionId); + return ResponseEntity.ok("Mission marked as complete"); + } +} diff --git a/src/main/java/javalab/umc7th_mission/domain/membermission/dto/MemberMissionResponseDTO.java b/src/main/java/javalab/umc7th_mission/domain/membermission/dto/MemberMissionResponseDTO.java new file mode 100644 index 0000000..2fbaf68 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/membermission/dto/MemberMissionResponseDTO.java @@ -0,0 +1,11 @@ +package javalab.umc7th_mission.domain.membermission.dto; + +public record MemberMissionResponseDTO( + Long missionId, + String missionSpec, + Integer reward, + String status, + String storeName +) { + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/membermission/repository/MemberMissionRepository.java b/src/main/java/javalab/umc7th_mission/domain/membermission/repository/MemberMissionRepository.java new file mode 100644 index 0000000..86d6d4e --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/membermission/repository/MemberMissionRepository.java @@ -0,0 +1,14 @@ +package javalab.umc7th_mission.domain.membermission.repository; + +import java.util.Optional; +import javalab.umc7th_mission.domain.membermission.MemberMission; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberMissionRepository extends JpaRepository { + + Page findByMemberIdAndStatus(Long memberId, String status, Pageable pageable); + + Optional findByMemberIdAndMissionId(Long memberId, Long missionId); +} diff --git a/src/main/java/javalab/umc7th_mission/domain/membermission/service/MemberMissionService.java b/src/main/java/javalab/umc7th_mission/domain/membermission/service/MemberMissionService.java new file mode 100644 index 0000000..f54b5f1 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/membermission/service/MemberMissionService.java @@ -0,0 +1,46 @@ +package javalab.umc7th_mission.domain.membermission.service; + +import javalab.umc7th_mission.config.apipayload.code.status.ErrorStatus; +import javalab.umc7th_mission.config.apipayload.exception.GeneralException; +import javalab.umc7th_mission.domain.membermission.MemberMission; +import javalab.umc7th_mission.domain.membermission.dto.MemberMissionResponseDTO; +import javalab.umc7th_mission.domain.membermission.repository.MemberMissionRepository; +import javalab.umc7th_mission.domain.mission.MissionStatus; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberMissionService { + + private final MemberMissionRepository memberMissionRepository; + + public Page getOngoingMissionsByMember(Long memberId, + Pageable pageable) { + String status = MissionStatus.CHALLENGING.name(); + + return memberMissionRepository.findByMemberIdAndStatus(memberId, status, pageable) + .map(memberMission -> new MemberMissionResponseDTO( + memberMission.getMission().getId(), + memberMission.getMission().getMissionSpec(), + memberMission.getMission().getReward(), + memberMission.getStatus().name(), + memberMission.getMission().getStore().getName() + )); + } + + @Transactional + public void completeMission(Long memberId, Long missionId) { + MemberMission memberMission = memberMissionRepository.findByMemberIdAndMissionId(memberId, + missionId) + .orElseThrow(() -> new GeneralException(ErrorStatus._BAD_REQUEST)); + if (!memberMission.getStatus().equals(MissionStatus.CHALLENGING)) { + throw new GeneralException(ErrorStatus._BAD_REQUEST); + } + memberMission.complete(); + } +} diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/controller/MissionController.java b/src/main/java/javalab/umc7th_mission/domain/mission/controller/MissionController.java new file mode 100644 index 0000000..a2964e7 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/mission/controller/MissionController.java @@ -0,0 +1,34 @@ +package javalab.umc7th_mission.domain.mission.controller; + +import javalab.umc7th_mission.config.annotation.CheckPage; +import javalab.umc7th_mission.config.apipayload.ApiResponse; +import javalab.umc7th_mission.domain.mission.dto.MissionResponseDto; +import javalab.umc7th_mission.domain.mission.service.MissionService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/missions") +public class MissionController { + + private static final Integer PAGE_SIZE = 10; + private final MissionService service; + + @GetMapping("/store/{storeId}") + public ApiResponse> getMissionsByStore( + @PathVariable Long storeId, + @RequestParam @CheckPage Integer page + ) { + Pageable pageable = PageRequest.of(page, PAGE_SIZE); + Page missions = service.getMissionsByStore(storeId, pageable); + return ApiResponse.onSuccess(missions); + } +} diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/dto/MissionResponseDto.java b/src/main/java/javalab/umc7th_mission/domain/mission/dto/MissionResponseDto.java new file mode 100644 index 0000000..ea61e71 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/mission/dto/MissionResponseDto.java @@ -0,0 +1,11 @@ +package javalab.umc7th_mission.domain.mission.dto; + +public record MissionResponseDto( + Long missionId, + Integer reward, + String missionSpec, + String storeName +) { + +} + diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionRepository.java b/src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionRepository.java new file mode 100644 index 0000000..6c7d301 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/mission/repository/MissionRepository.java @@ -0,0 +1,12 @@ +package javalab.umc7th_mission.domain.mission.repository; + +import javalab.umc7th_mission.domain.mission.Mission; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MissionRepository extends JpaRepository { + + Page findByStoreId(Long storeId, Pageable pageable); + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/mission/service/MissionService.java b/src/main/java/javalab/umc7th_mission/domain/mission/service/MissionService.java new file mode 100644 index 0000000..239a963 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/mission/service/MissionService.java @@ -0,0 +1,27 @@ +package javalab.umc7th_mission.domain.mission.service; + +import javalab.umc7th_mission.domain.mission.dto.MissionResponseDto; +import javalab.umc7th_mission.domain.mission.repository.MissionRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MissionService { + + private final MissionRepository repository; + + public Page getMissionsByStore(Long storeId, Pageable pageable) { + return repository.findByStoreId(storeId, pageable) + .map(mission -> new MissionResponseDto( + mission.getId(), + mission.getReward(), + mission.getMissionSpec(), + mission.getStore().getName() + )); + } +} diff --git a/src/main/java/javalab/umc7th_mission/domain/review/controller/ReviewController.java b/src/main/java/javalab/umc7th_mission/domain/review/controller/ReviewController.java new file mode 100644 index 0000000..1dbdee0 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/review/controller/ReviewController.java @@ -0,0 +1,31 @@ +package javalab.umc7th_mission.domain.review.controller; + +import javalab.umc7th_mission.config.apipayload.ApiResponse; +import javalab.umc7th_mission.domain.review.dto.ReviewResponse.ReviewsDTO; +import javalab.umc7th_mission.domain.review.service.ReviewService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class ReviewController { + + private final ReviewService reviewService; + + private static final Integer PAGE_SIZE = 10; + + @GetMapping("/member") + public ApiResponse getReviewsByMember( + Long memberId, // 로그인 되어있다고 가정 + @RequestParam(defaultValue = "0") int page + ) { + memberId = 0L; // 추후 argumentResolver 이용 + Pageable pageable = PageRequest.of(page, PAGE_SIZE); + ReviewsDTO result = reviewService.getReviewsByMember(memberId, pageable); + return ApiResponse.onSuccess(result); + } +} diff --git a/src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewRequest.java b/src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewRequest.java new file mode 100644 index 0000000..b05ba74 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewRequest.java @@ -0,0 +1,5 @@ +package javalab.umc7th_mission.domain.review.dto; + +public class ReviewRequest { + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewResponse.java b/src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewResponse.java new file mode 100644 index 0000000..3b161e4 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/review/dto/ReviewResponse.java @@ -0,0 +1,25 @@ +package javalab.umc7th_mission.domain.review.dto; + +import java.time.LocalDate; +import java.util.List; + +public final class ReviewResponse { + + private ReviewResponse() { + } + + public record ReviewsDTO( + List reviews + ) { + + } + + public record ReviewDTO( + String nickname, + Double score, + String body, + LocalDate createdAt + ) { + + } +} diff --git a/src/main/java/javalab/umc7th_mission/domain/review/repository/ReviewRepository.java b/src/main/java/javalab/umc7th_mission/domain/review/repository/ReviewRepository.java new file mode 100644 index 0000000..b477460 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/review/repository/ReviewRepository.java @@ -0,0 +1,12 @@ +package javalab.umc7th_mission.domain.review.repository; + +import javalab.umc7th_mission.domain.review.Review; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReviewRepository extends JpaRepository { + + Page findByMemberId(Long memberId, Pageable pageable); + +} diff --git a/src/main/java/javalab/umc7th_mission/domain/review/service/ReviewService.java b/src/main/java/javalab/umc7th_mission/domain/review/service/ReviewService.java new file mode 100644 index 0000000..fd53143 --- /dev/null +++ b/src/main/java/javalab/umc7th_mission/domain/review/service/ReviewService.java @@ -0,0 +1,38 @@ +package javalab.umc7th_mission.domain.review.service; + +import java.util.ArrayList; +import java.util.List; +import javalab.umc7th_mission.domain.review.Review; +import javalab.umc7th_mission.domain.review.dto.ReviewResponse; +import javalab.umc7th_mission.domain.review.dto.ReviewResponse.ReviewDTO; +import javalab.umc7th_mission.domain.review.repository.ReviewRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReviewService { + + private final ReviewRepository reviewRepository; + + public ReviewResponse.ReviewsDTO getReviewsByMember(Long memberId, Pageable pageable) { + Page reviews = reviewRepository.findByMemberId(memberId, pageable); + + List reviewDTOs = new ArrayList<>(); + for (Review review : reviews) { + ReviewDTO reviewDTO = new ReviewDTO( + review.getMember().getName(), + review.getScore(), + review.getBody(), + review.getCreatedAt().toLocalDate() + ); + reviewDTOs.add(reviewDTO); + } + + return new ReviewResponse.ReviewsDTO(reviewDTOs); + + } +} +