From 12c9cad83e362421333bf78bb4aace70db225eb8 Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 14:16:50 +0900 Subject: [PATCH 1/8] =?UTF-8?q?Food=20repository=EC=9E=91=EC=84=B1+?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/food/exception/FoodException.java | 10 ++++++++++ .../food/exception/code/FoodErrorCode.java | 16 ++++++++++++++++ .../food/exception/code/FoodExceptiodd.java | 10 ++++++++++ .../domain/food/repository/FoodRepository.java | 8 ++++++++ 4 files changed, 44 insertions(+) create mode 100644 src/main/java/com/example/demo/domain/food/exception/FoodException.java create mode 100644 src/main/java/com/example/demo/domain/food/exception/code/FoodErrorCode.java create mode 100644 src/main/java/com/example/demo/domain/food/exception/code/FoodExceptiodd.java create mode 100644 src/main/java/com/example/demo/domain/food/repository/FoodRepository.java diff --git a/src/main/java/com/example/demo/domain/food/exception/FoodException.java b/src/main/java/com/example/demo/domain/food/exception/FoodException.java new file mode 100644 index 0000000..ab971de --- /dev/null +++ b/src/main/java/com/example/demo/domain/food/exception/FoodException.java @@ -0,0 +1,10 @@ +package com.example.demo.domain.food.exception; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; +import com.example.demo.global.apiPayload.exception.GeneralException; + +public class FoodException extends GeneralException { + public FoodException(BaseErrorCode code) { + super(code); + } +} diff --git a/src/main/java/com/example/demo/domain/food/exception/code/FoodErrorCode.java b/src/main/java/com/example/demo/domain/food/exception/code/FoodErrorCode.java new file mode 100644 index 0000000..9034a12 --- /dev/null +++ b/src/main/java/com/example/demo/domain/food/exception/code/FoodErrorCode.java @@ -0,0 +1,16 @@ +package com.example.demo.domain.food.exception.code; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; +import com.example.demo.global.apiPayload.code.GeneralErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum FoodErrorCode implements BaseErrorCode { + Food_NOT_FOUND(HttpStatus.NOT_FOUND, "FOOD404","이거는 푸드 테스트"); + private final HttpStatus status; + private final String code; + private final String message; +} diff --git a/src/main/java/com/example/demo/domain/food/exception/code/FoodExceptiodd.java b/src/main/java/com/example/demo/domain/food/exception/code/FoodExceptiodd.java new file mode 100644 index 0000000..e79d92e --- /dev/null +++ b/src/main/java/com/example/demo/domain/food/exception/code/FoodExceptiodd.java @@ -0,0 +1,10 @@ +package com.example.demo.domain.food.exception.code; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; +import com.example.demo.global.apiPayload.exception.GeneralException; + +public class FoodExceptiodd extends GeneralException { + public FoodExceptiodd(BaseErrorCode code) { + super(code); + } +} diff --git a/src/main/java/com/example/demo/domain/food/repository/FoodRepository.java b/src/main/java/com/example/demo/domain/food/repository/FoodRepository.java new file mode 100644 index 0000000..2b87143 --- /dev/null +++ b/src/main/java/com/example/demo/domain/food/repository/FoodRepository.java @@ -0,0 +1,8 @@ +package com.example.demo.domain.food.repository; + +import com.example.demo.domain.food.entity.Food; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FoodRepository extends JpaRepository { + +} From 29b5e1e90a1faa8843b9cebe7d048057c65a30cb Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 14:17:39 +0900 Subject: [PATCH 2/8] =?UTF-8?q?Member=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC,=EC=BB=A8=EB=B2=84=ED=84=B0,=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 25 +++++++ .../member/converter/MemberConverter.java | 30 +++++++++ .../service/command/MemberCommandService.java | 11 ++++ .../command/MemberCommandServiceImpl.java | 66 +++++++++++++++++++ 4 files changed, 132 insertions(+) create mode 100644 src/main/java/com/example/demo/domain/member/controller/MemberController.java create mode 100644 src/main/java/com/example/demo/domain/member/converter/MemberConverter.java create mode 100644 src/main/java/com/example/demo/domain/member/service/command/MemberCommandService.java create mode 100644 src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java diff --git a/src/main/java/com/example/demo/domain/member/controller/MemberController.java b/src/main/java/com/example/demo/domain/member/controller/MemberController.java new file mode 100644 index 0000000..0cdf3f3 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/controller/MemberController.java @@ -0,0 +1,25 @@ +package com.example.demo.domain.member.controller; + +import com.example.demo.domain.member.dto.req.MemberReqDTO; +import com.example.demo.domain.member.dto.res.MemberResDTO; +import com.example.demo.domain.member.exception.code.MemberSuccessCode; +import com.example.demo.domain.member.service.command.MemberCommandService; +import com.example.demo.global.apiPayload.ApiResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@RequiredArgsConstructor +public class MemberController { + private final MemberCommandService memberCommandService; + // 회원가입 + @PostMapping("/sign-up") + public ApiResponse signUp( + @RequestBody MemberReqDTO.JoinDTO dto + ){ + return ApiResponse.onSuccess(MemberSuccessCode.FOUND, memberCommandService.signup(dto)); + } +} diff --git a/src/main/java/com/example/demo/domain/member/converter/MemberConverter.java b/src/main/java/com/example/demo/domain/member/converter/MemberConverter.java new file mode 100644 index 0000000..1539aa9 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/converter/MemberConverter.java @@ -0,0 +1,30 @@ +package com.example.demo.domain.member.converter; + +import com.example.demo.domain.member.dto.req.MemberReqDTO; +import com.example.demo.domain.member.dto.res.MemberResDTO; +import com.example.demo.domain.member.entity.Member; + +public class MemberConverter { + // Entity -> DTO + public static MemberResDTO.JoinDTO toJoinDTO( + Member member + ){ + return MemberResDTO.JoinDTO.builder() + .memberId(member.getId()) + .createAt(member.getCreatedAt()) + .build(); + } + + // DTO -> Entity + public static Member toMember( + MemberReqDTO.JoinDTO dto + ){ + return Member.builder() + .name(dto.name()) + .birth(dto.birth()) + .address(dto.address()) + .detailAddress(dto.specAddress()) + .gender(dto.gender()) + .build(); + } +} diff --git a/src/main/java/com/example/demo/domain/member/service/command/MemberCommandService.java b/src/main/java/com/example/demo/domain/member/service/command/MemberCommandService.java new file mode 100644 index 0000000..ef21627 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/service/command/MemberCommandService.java @@ -0,0 +1,11 @@ +package com.example.demo.domain.member.service.command; + +import com.example.demo.domain.member.dto.req.MemberReqDTO; +import com.example.demo.domain.member.dto.res.MemberResDTO; + +public interface MemberCommandService { + + public MemberResDTO.JoinDTO signup( + MemberReqDTO.JoinDTO dto + ); +} diff --git a/src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java b/src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java new file mode 100644 index 0000000..f113bb6 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java @@ -0,0 +1,66 @@ +package com.example.demo.domain.member.service.command; + +import com.example.demo.domain.food.entity.Food; +import com.example.demo.domain.food.exception.FoodException; +import com.example.demo.domain.food.exception.code.FoodErrorCode; +import com.example.demo.domain.food.repository.FoodRepository; +import com.example.demo.domain.member.converter.MemberConverter; +import com.example.demo.domain.member.dto.req.MemberReqDTO; +import com.example.demo.domain.member.dto.res.MemberResDTO; +import com.example.demo.domain.member.entity.Member; +import com.example.demo.domain.member.entity.mapping.MemberFood; +import com.example.demo.domain.member.repository.MemberFoodRepository; +import com.example.demo.domain.member.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class MemberCommandServiceImpl implements MemberCommandService { + + private final MemberRepository memberRepository; + private final MemberFoodRepository memberFoodRepository; + private final FoodRepository foodRepository; + + // 회원가입 + @Override + @Transactional + public MemberResDTO.JoinDTO signup( + MemberReqDTO.JoinDTO dto + ) { + // 사용자 생성 + Member member = MemberConverter.toMember(dto); + // DB 적용 + memberRepository.save(member); + + // 선호 음식 존재 여부 확인 + if (dto.preferCategory().size() > 1) { + List memberFoodList = new ArrayList<>(); + + // 선호 음식 ID별 조회 + for (Long id : dto.preferCategory()) { + + // 음식 존재 여부 검증 + Food food = foodRepository.findById(id) + .orElseThrow(() -> new FoodException(FoodErrorCode.Food_NOT_FOUND)); + + // MemberFood 엔티티 생성 (컨버터 사용해야 함) + MemberFood memberFood = MemberFood.builder() + .member(member) + .food(food) + .build(); + + // 사용자 - 음식 (선호 음식) 추가 + memberFoodList.add(memberFood); + } + + // 모든 선호 음식 추가: DB 적용 + memberFoodRepository.saveAll(memberFoodList); + } + return MemberConverter.toJoinDTO(member); + } +} From b6ecf88b3e1c0d2c4d945d71cceef47a417d02a5 Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 14:17:55 +0900 Subject: [PATCH 3/8] =?UTF-8?q?Member=20=EC=84=B1=EA=B3=B5=EB=B0=8F=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/exception/MemberException.java | 10 ++++++++++ .../exception/code/MemberErrorCode.java | 18 ++++++++++++++++++ .../exception/code/MemberSuccessCode.java | 19 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/main/java/com/example/demo/domain/member/exception/MemberException.java create mode 100644 src/main/java/com/example/demo/domain/member/exception/code/MemberErrorCode.java create mode 100644 src/main/java/com/example/demo/domain/member/exception/code/MemberSuccessCode.java diff --git a/src/main/java/com/example/demo/domain/member/exception/MemberException.java b/src/main/java/com/example/demo/domain/member/exception/MemberException.java new file mode 100644 index 0000000..7b18715 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/exception/MemberException.java @@ -0,0 +1,10 @@ +package com.example.demo.domain.member.exception; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; +import com.example.demo.global.apiPayload.exception.GeneralException; + +public class MemberException extends GeneralException { + public MemberException(BaseErrorCode code) { + super(code); + } +} diff --git a/src/main/java/com/example/demo/domain/member/exception/code/MemberErrorCode.java b/src/main/java/com/example/demo/domain/member/exception/code/MemberErrorCode.java new file mode 100644 index 0000000..e79612a --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/exception/code/MemberErrorCode.java @@ -0,0 +1,18 @@ +package com.example.demo.domain.member.exception.code; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum MemberErrorCode implements BaseErrorCode { + NOT_FOUND(HttpStatus.NOT_FOUND, + "MEMBER404_1", + "해당 사용자를 찾지 못했습니다."), + ; + private final HttpStatus status; + private final String code; + private final String message; +} diff --git a/src/main/java/com/example/demo/domain/member/exception/code/MemberSuccessCode.java b/src/main/java/com/example/demo/domain/member/exception/code/MemberSuccessCode.java new file mode 100644 index 0000000..a4b0c5a --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/exception/code/MemberSuccessCode.java @@ -0,0 +1,19 @@ +package com.example.demo.domain.member.exception.code; + +import com.example.demo.global.apiPayload.code.BaseSuccessCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum MemberSuccessCode implements BaseSuccessCode { + FOUND(HttpStatus.OK, + "MEMBER200_1", + "성공적으로 사용자를 조회했습니다."), + ; + private final HttpStatus status; + private final String code; + private final String message; + +} From 3a61d4ac620fbd5c63e0a5393372769ff0d42811 Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 14:18:24 +0900 Subject: [PATCH 4/8] =?UTF-8?q?Member=20DTO=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/dto/req/MemberReqDTO.java | 21 +++++++++++++++++++ .../domain/member/dto/res/MemberResDTO.java | 13 ++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/main/java/com/example/demo/domain/member/dto/req/MemberReqDTO.java create mode 100644 src/main/java/com/example/demo/domain/member/dto/res/MemberResDTO.java diff --git a/src/main/java/com/example/demo/domain/member/dto/req/MemberReqDTO.java b/src/main/java/com/example/demo/domain/member/dto/req/MemberReqDTO.java new file mode 100644 index 0000000..faa5e69 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/dto/req/MemberReqDTO.java @@ -0,0 +1,21 @@ +package com.example.demo.domain.member.dto.req; + +import com.example.demo.domain.member.enums.Address; +import com.example.demo.domain.member.enums.Gender; + +import java.time.LocalDate; +import java.util.List; + +public class MemberReqDTO { + + + + public record JoinDTO( + String name, + Gender gender, + LocalDate birth, + Address address, + String specAddress, + List preferCategory + ){} +} diff --git a/src/main/java/com/example/demo/domain/member/dto/res/MemberResDTO.java b/src/main/java/com/example/demo/domain/member/dto/res/MemberResDTO.java new file mode 100644 index 0000000..42ced4a --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/dto/res/MemberResDTO.java @@ -0,0 +1,13 @@ +package com.example.demo.domain.member.dto.res; + +import lombok.Builder; + +import java.time.LocalDateTime; + +public class MemberResDTO { + @Builder + public record JoinDTO( + Long memberId, + LocalDateTime createAt + ){} +} From d687905efacb87b47102ddab08d2bd17894cc7ce Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 14:18:42 +0900 Subject: [PATCH 5/8] =?UTF-8?q?MemberQueryService=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/service/query/MemberQueryService.java | 5 +++++ .../service/query/MemberQueryServiceImpl.java | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/main/java/com/example/demo/domain/member/service/query/MemberQueryService.java create mode 100644 src/main/java/com/example/demo/domain/member/service/query/MemberQueryServiceImpl.java diff --git a/src/main/java/com/example/demo/domain/member/service/query/MemberQueryService.java b/src/main/java/com/example/demo/domain/member/service/query/MemberQueryService.java new file mode 100644 index 0000000..29b7c9a --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/service/query/MemberQueryService.java @@ -0,0 +1,5 @@ +package com.example.demo.domain.member.service.query; + +public interface MemberQueryService { + void checkFlag(Long flag); +} diff --git a/src/main/java/com/example/demo/domain/member/service/query/MemberQueryServiceImpl.java b/src/main/java/com/example/demo/domain/member/service/query/MemberQueryServiceImpl.java new file mode 100644 index 0000000..ee83324 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/service/query/MemberQueryServiceImpl.java @@ -0,0 +1,15 @@ +package com.example.demo.domain.member.service.query; + +import com.example.demo.domain.member.exception.MemberException; +import com.example.demo.domain.member.exception.code.MemberErrorCode; +import com.example.demo.domain.test.exception.TestException; +import com.example.demo.domain.test.exception.code.TestErrorCode; + +public class MemberQueryServiceImpl implements MemberQueryService { + @Override + public void checkFlag(Long flag) { + if(flag==1){ + throw new MemberException(MemberErrorCode.NOT_FOUND); + } + } +} From b7bd2ca393d6ead7e4e471b43463771c7776737c Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 14:19:00 +0900 Subject: [PATCH 6/8] MemberFoodReoisitory --- .../domain/member/repository/MemberFoodRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/com/example/demo/domain/member/repository/MemberFoodRepository.java diff --git a/src/main/java/com/example/demo/domain/member/repository/MemberFoodRepository.java b/src/main/java/com/example/demo/domain/member/repository/MemberFoodRepository.java new file mode 100644 index 0000000..5296599 --- /dev/null +++ b/src/main/java/com/example/demo/domain/member/repository/MemberFoodRepository.java @@ -0,0 +1,8 @@ +package com.example.demo.domain.member.repository; + +import com.example.demo.domain.member.entity.mapping.MemberFood; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberFoodRepository extends JpaRepository { + +} From 86a389ca4d6f3ad3ede51e923e384f27d8996a73 Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 18:12:13 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EC=9E=91=EC=84=B1?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20API=20=EA=B5=AC=ED=98=84(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/MemberCommandServiceImpl.java | 4 +- .../review/controller/ReviewController.java | 20 +++++++-- .../review/converter/ReviewConverter.java | 28 ++++++++++++ .../domain/review/dto/req/ReviewReqDTO.java | 20 +++++++++ .../domain/review/dto/res/ReviewResDTO.java | 10 +++++ .../service/command/ReviewCommandService.java | 10 +++++ .../command/ReviewCommandServiceImpl.java | 43 +++++++++++++++++++ .../store/exception/StoreException.java | 9 ++++ .../store/exception/code/StoreErrorCode.java | 24 +++++++++++ .../exception/code/StoreSuccessCode.java | 19 ++++++++ .../store/repository/StoreRepository.java | 8 ++++ 11 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/example/demo/domain/review/dto/req/ReviewReqDTO.java create mode 100644 src/main/java/com/example/demo/domain/review/service/command/ReviewCommandService.java create mode 100644 src/main/java/com/example/demo/domain/review/service/command/ReviewCommandServiceImpl.java create mode 100644 src/main/java/com/example/demo/domain/store/exception/StoreException.java create mode 100644 src/main/java/com/example/demo/domain/store/exception/code/StoreErrorCode.java create mode 100644 src/main/java/com/example/demo/domain/store/exception/code/StoreSuccessCode.java create mode 100644 src/main/java/com/example/demo/domain/store/repository/StoreRepository.java diff --git a/src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java b/src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java index f113bb6..8c58f85 100644 --- a/src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java +++ b/src/main/java/com/example/demo/domain/member/service/command/MemberCommandServiceImpl.java @@ -48,17 +48,15 @@ public MemberResDTO.JoinDTO signup( Food food = foodRepository.findById(id) .orElseThrow(() -> new FoodException(FoodErrorCode.Food_NOT_FOUND)); - // MemberFood 엔티티 생성 (컨버터 사용해야 함) MemberFood memberFood = MemberFood.builder() .member(member) .food(food) .build(); - // 사용자 - 음식 (선호 음식) 추가 memberFoodList.add(memberFood); } - // 모든 선호 음식 추가: DB 적용 + //DB 적용 memberFoodRepository.saveAll(memberFoodList); } return MemberConverter.toJoinDTO(member); diff --git a/src/main/java/com/example/demo/domain/review/controller/ReviewController.java b/src/main/java/com/example/demo/domain/review/controller/ReviewController.java index b17184e..56ffcdf 100644 --- a/src/main/java/com/example/demo/domain/review/controller/ReviewController.java +++ b/src/main/java/com/example/demo/domain/review/controller/ReviewController.java @@ -2,15 +2,15 @@ import com.example.demo.domain.review.converter.ReviewConverter; +import com.example.demo.domain.review.dto.req.ReviewReqDTO; import com.example.demo.domain.review.dto.res.ReviewResDTO; +import com.example.demo.domain.review.entity.Review; +import com.example.demo.domain.review.service.command.ReviewCommandService; import com.example.demo.domain.review.service.query.ReviewQueryService; import com.example.demo.global.apiPayload.ApiResponse; import com.example.demo.global.apiPayload.code.GeneralSuccessCode; 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; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -19,6 +19,7 @@ @RequestMapping("/reviews") public class ReviewController { private final ReviewQueryService reviewQueryService; + private final ReviewCommandService reviewCommandService; @GetMapping("/my") public ApiResponse> getMyReviews( @@ -44,5 +45,16 @@ public ApiResponse exception( } + @PostMapping("/post") + public ApiResponse createReview( + @RequestBody ReviewReqDTO.ReviewRegisterDTO request) { + + // 서비스 실행 + Review review = reviewCommandService.createReview(request); + GeneralSuccessCode code = GeneralSuccessCode.OK; + // 결과 반환 + return ApiResponse.onSuccess(code,ReviewConverter.toCreateResultDTO(review)); + } + } diff --git a/src/main/java/com/example/demo/domain/review/converter/ReviewConverter.java b/src/main/java/com/example/demo/domain/review/converter/ReviewConverter.java index 52f5863..cc8e0e8 100644 --- a/src/main/java/com/example/demo/domain/review/converter/ReviewConverter.java +++ b/src/main/java/com/example/demo/domain/review/converter/ReviewConverter.java @@ -1,8 +1,14 @@ package com.example.demo.domain.review.converter; +import com.example.demo.domain.member.entity.Member; +import com.example.demo.domain.review.dto.req.ReviewReqDTO; import com.example.demo.domain.review.dto.res.ReviewResDTO; +import com.example.demo.domain.review.entity.Review; +import com.example.demo.domain.store.entity.Store; import com.example.demo.domain.test.dto.res.TestResDTO; +import java.time.LocalDateTime; + public class ReviewConverter { public static ReviewResDTO.ErrorResult toExceptionDTO( @@ -12,4 +18,26 @@ public static ReviewResDTO.ErrorResult toExceptionDTO( .ReviewString(Reviewting) .build(); } + + + // 1. DTO -> Entity 변환 (DB 저장용) + public static Review toEntity(ReviewReqDTO.ReviewRegisterDTO request, Member member, Store store) { + return Review.builder() + .member(member) + .store(store) + .star(request.getScore()) + .content(request.getContent()) + .build(); + } + + // 2. Entity -> DTO 변환 (응답용) + public static ReviewResDTO.ReviewCreateResultDTO toCreateResultDTO(Review review) { + return ReviewResDTO.ReviewCreateResultDTO.builder() + .reviewId(review.getId()) + .createdAt(LocalDateTime.now()) + .build(); + } + + + } \ No newline at end of file diff --git a/src/main/java/com/example/demo/domain/review/dto/req/ReviewReqDTO.java b/src/main/java/com/example/demo/domain/review/dto/req/ReviewReqDTO.java new file mode 100644 index 0000000..fd3248d --- /dev/null +++ b/src/main/java/com/example/demo/domain/review/dto/req/ReviewReqDTO.java @@ -0,0 +1,20 @@ +package com.example.demo.domain.review.dto.req; + +import lombok.Getter; +import org.antlr.v4.runtime.misc.NotNull; + +public class ReviewReqDTO { + + @Getter + public static class ReviewRegisterDTO { + @NotNull + private Long memberId; // 리뷰 작성자 ID + @NotNull + private Long storeId; // 가게 ID + @NotNull + private Float score; // 별점 + @NotNull + private String content; // 리뷰 내용 + } +} + diff --git a/src/main/java/com/example/demo/domain/review/dto/res/ReviewResDTO.java b/src/main/java/com/example/demo/domain/review/dto/res/ReviewResDTO.java index 80125ad..32ccb3a 100644 --- a/src/main/java/com/example/demo/domain/review/dto/res/ReviewResDTO.java +++ b/src/main/java/com/example/demo/domain/review/dto/res/ReviewResDTO.java @@ -38,5 +38,15 @@ public static class ErrorResult{ } + @Builder + @Getter + public static class ReviewCreateResultDTO { + private Long reviewId; + private LocalDateTime createdAt; + } + + + + } diff --git a/src/main/java/com/example/demo/domain/review/service/command/ReviewCommandService.java b/src/main/java/com/example/demo/domain/review/service/command/ReviewCommandService.java new file mode 100644 index 0000000..a3c5d0d --- /dev/null +++ b/src/main/java/com/example/demo/domain/review/service/command/ReviewCommandService.java @@ -0,0 +1,10 @@ +package com.example.demo.domain.review.service.command; + +import com.example.demo.domain.review.dto.req.ReviewReqDTO; +import com.example.demo.domain.review.entity.Review; + +public interface ReviewCommandService { + + public Review createReview(ReviewReqDTO.ReviewRegisterDTO request); + +} diff --git a/src/main/java/com/example/demo/domain/review/service/command/ReviewCommandServiceImpl.java b/src/main/java/com/example/demo/domain/review/service/command/ReviewCommandServiceImpl.java new file mode 100644 index 0000000..fa2fae3 --- /dev/null +++ b/src/main/java/com/example/demo/domain/review/service/command/ReviewCommandServiceImpl.java @@ -0,0 +1,43 @@ +package com.example.demo.domain.review.service.command; + +import com.example.demo.domain.member.entity.Member; +import com.example.demo.domain.member.exception.MemberException; +import com.example.demo.domain.member.exception.code.MemberErrorCode; +import com.example.demo.domain.member.repository.MemberRepository; +import com.example.demo.domain.review.converter.ReviewConverter; +import com.example.demo.domain.review.dto.req.ReviewReqDTO; +import com.example.demo.domain.review.entity.Review; +import com.example.demo.domain.review.repository.ReviewRepository; +import com.example.demo.domain.store.entity.Store; +import com.example.demo.domain.store.exception.StoreException; +import com.example.demo.domain.store.exception.code.StoreErrorCode; +import com.example.demo.domain.store.repository.StoreRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class ReviewCommandServiceImpl implements ReviewCommandService { + private final ReviewRepository reviewRepository; + private final MemberRepository memberRepository; + private final StoreRepository storeRepository; + + + @Override + public Review createReview(ReviewReqDTO.ReviewRegisterDTO request) { + + Member member = memberRepository.findById(request.getMemberId()) + .orElseThrow(() -> new MemberException(MemberErrorCode.NOT_FOUND)); + + Store store = storeRepository.findById(request.getStoreId()) + .orElseThrow(() -> new StoreException(StoreErrorCode.NOT_FOUND)); + + // 3. 리뷰 엔티티 생성 + Review review = ReviewConverter.toEntity(request, member, store); + + // 4. DB 저장 + return reviewRepository.save(review); + } +} diff --git a/src/main/java/com/example/demo/domain/store/exception/StoreException.java b/src/main/java/com/example/demo/domain/store/exception/StoreException.java new file mode 100644 index 0000000..3749e86 --- /dev/null +++ b/src/main/java/com/example/demo/domain/store/exception/StoreException.java @@ -0,0 +1,9 @@ +package com.example.demo.domain.store.exception; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; + +public class StoreException extends RuntimeException { + public StoreException(BaseErrorCode code) { + super((Throwable) code); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/domain/store/exception/code/StoreErrorCode.java b/src/main/java/com/example/demo/domain/store/exception/code/StoreErrorCode.java new file mode 100644 index 0000000..a059e4c --- /dev/null +++ b/src/main/java/com/example/demo/domain/store/exception/code/StoreErrorCode.java @@ -0,0 +1,24 @@ +package com.example.demo.domain.store.exception.code; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + + +@Getter +@AllArgsConstructor +public enum StoreErrorCode implements BaseErrorCode { + + NOT_FOUND(HttpStatus.NOT_FOUND, + "MEMBER404_1", + "해당 가게를 찾지 못했습니다."), + ; + private final HttpStatus status; + private final String code; + private final String message; +} + + + + diff --git a/src/main/java/com/example/demo/domain/store/exception/code/StoreSuccessCode.java b/src/main/java/com/example/demo/domain/store/exception/code/StoreSuccessCode.java new file mode 100644 index 0000000..3f985e6 --- /dev/null +++ b/src/main/java/com/example/demo/domain/store/exception/code/StoreSuccessCode.java @@ -0,0 +1,19 @@ +package com.example.demo.domain.store.exception.code; + +import com.example.demo.global.apiPayload.code.BaseSuccessCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + + +@Getter +@AllArgsConstructor +public enum StoreSuccessCode implements BaseSuccessCode { + FOUND(HttpStatus.OK, + "STORE200_1", + "성공적으로 사용자를 조회했습니다."), + ; + private final HttpStatus status; + private final String code; + private final String message; +} diff --git a/src/main/java/com/example/demo/domain/store/repository/StoreRepository.java b/src/main/java/com/example/demo/domain/store/repository/StoreRepository.java new file mode 100644 index 0000000..8cea5d7 --- /dev/null +++ b/src/main/java/com/example/demo/domain/store/repository/StoreRepository.java @@ -0,0 +1,8 @@ +package com.example.demo.domain.store.repository; + +import com.example.demo.domain.store.entity.Store; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface StoreRepository extends JpaRepository { + +} From b82bb121cab26744430f30e678a723b24e4cbf54 Mon Sep 17 00:00:00 2001 From: fbehdgus Date: Wed, 26 Nov 2025 18:35:56 +0900 Subject: [PATCH 8/8] =?UTF-8?q?=20=EB=8F=84=EC=A0=84=EC=A4=91=EC=9D=B8=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=EC=97=90=20=EC=B6=94=EA=B0=80=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/controller/MissionController.java | 33 +++++++++++++ .../converter/MemberMissionConverter.java | 26 ++++++++++ .../domain/mission/dto/req/MissionReqDTO.java | 15 ++++++ .../domain/mission/dto/res/MissionResDTO.java | 20 ++++++++ .../exception/MissionException.java} | 10 ++-- .../exception/code/MissionErrorCode.java | 26 ++++++++++ .../exception/code/MissionSuccessCode.java | 4 ++ .../repository/MemberMissionRepository.java | 8 ++++ .../command/MissionCommandService.java | 8 ++++ .../command/MissionCommandServiceImpl.java | 48 +++++++++++++++++++ .../store/exception/StoreException.java | 5 +- 11 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/example/demo/domain/mission/controller/MissionController.java create mode 100644 src/main/java/com/example/demo/domain/mission/converter/MemberMissionConverter.java create mode 100644 src/main/java/com/example/demo/domain/mission/dto/req/MissionReqDTO.java create mode 100644 src/main/java/com/example/demo/domain/mission/dto/res/MissionResDTO.java rename src/main/java/com/example/demo/domain/{food/exception/code/FoodExceptiodd.java => mission/exception/MissionException.java} (50%) create mode 100644 src/main/java/com/example/demo/domain/mission/exception/code/MissionErrorCode.java create mode 100644 src/main/java/com/example/demo/domain/mission/exception/code/MissionSuccessCode.java create mode 100644 src/main/java/com/example/demo/domain/mission/repository/MemberMissionRepository.java create mode 100644 src/main/java/com/example/demo/domain/mission/service/command/MissionCommandService.java create mode 100644 src/main/java/com/example/demo/domain/mission/service/command/MissionCommandServiceImpl.java diff --git a/src/main/java/com/example/demo/domain/mission/controller/MissionController.java b/src/main/java/com/example/demo/domain/mission/controller/MissionController.java new file mode 100644 index 0000000..4d84dc4 --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/controller/MissionController.java @@ -0,0 +1,33 @@ +package com.example.demo.domain.mission.controller; + + +import com.example.demo.domain.member.entity.mapping.MemberMission; +import com.example.demo.domain.mission.converter.MemberMissionConverter; +import com.example.demo.domain.mission.dto.req.MissionReqDTO; +import com.example.demo.domain.mission.dto.res.MissionResDTO; +import com.example.demo.domain.mission.service.command.MissionCommandService; +import com.example.demo.global.apiPayload.ApiResponse; +import com.example.demo.global.apiPayload.code.GeneralSuccessCode; +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 MissionController { + + private final MissionCommandService missionCommandService; + + // 미션 목록에 추가 API + @PostMapping("/add") + public ApiResponse joinMission( + @RequestBody MissionReqDTO.MissionJoinDto request) { + + MemberMission memberMission = missionCommandService.joinMission(request); + GeneralSuccessCode code = GeneralSuccessCode.OK; + return ApiResponse.onSuccess(code,MemberMissionConverter.toJoinResultDto(memberMission)); + } +} diff --git a/src/main/java/com/example/demo/domain/mission/converter/MemberMissionConverter.java b/src/main/java/com/example/demo/domain/mission/converter/MemberMissionConverter.java new file mode 100644 index 0000000..5357a7a --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/converter/MemberMissionConverter.java @@ -0,0 +1,26 @@ +package com.example.demo.domain.mission.converter; + +import com.example.demo.domain.member.entity.Member; +import com.example.demo.domain.member.entity.mapping.MemberMission; +import com.example.demo.domain.mission.dto.res.MissionResDTO; +import com.example.demo.domain.mission.entity.Mission; + +import java.time.LocalDateTime; + +public class MemberMissionConverter { + + public static MemberMission toEntity(Member member, Mission mission) { + return MemberMission.builder() + .member(member) + .mission(mission) + .isComplete(false) // 초기엔 성공 안함 + .build(); + } + + public static MissionResDTO.MissionJoinResultDto toJoinResultDto(MemberMission memberMission) { + return MissionResDTO.MissionJoinResultDto.builder() + .memberMissionId(memberMission.getId()) + .createdAt(LocalDateTime.now()) + .build(); + } +} diff --git a/src/main/java/com/example/demo/domain/mission/dto/req/MissionReqDTO.java b/src/main/java/com/example/demo/domain/mission/dto/req/MissionReqDTO.java new file mode 100644 index 0000000..ea6b559 --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/dto/req/MissionReqDTO.java @@ -0,0 +1,15 @@ +package com.example.demo.domain.mission.dto.req; + +import lombok.Getter; +import org.antlr.v4.runtime.misc.NotNull; + +public class MissionReqDTO { + + @Getter + public static class MissionJoinDto { + @NotNull + private Long memberId; + @NotNull + private Long missionId; + } +} diff --git a/src/main/java/com/example/demo/domain/mission/dto/res/MissionResDTO.java b/src/main/java/com/example/demo/domain/mission/dto/res/MissionResDTO.java new file mode 100644 index 0000000..e28102e --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/dto/res/MissionResDTO.java @@ -0,0 +1,20 @@ +package com.example.demo.domain.mission.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +public class MissionResDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class MissionJoinResultDto { + private Long memberMissionId; // 생성된 매핑 ID + private LocalDateTime createdAt; + } +} diff --git a/src/main/java/com/example/demo/domain/food/exception/code/FoodExceptiodd.java b/src/main/java/com/example/demo/domain/mission/exception/MissionException.java similarity index 50% rename from src/main/java/com/example/demo/domain/food/exception/code/FoodExceptiodd.java rename to src/main/java/com/example/demo/domain/mission/exception/MissionException.java index e79d92e..a459201 100644 --- a/src/main/java/com/example/demo/domain/food/exception/code/FoodExceptiodd.java +++ b/src/main/java/com/example/demo/domain/mission/exception/MissionException.java @@ -1,10 +1,14 @@ -package com.example.demo.domain.food.exception.code; +package com.example.demo.domain.mission.exception; import com.example.demo.global.apiPayload.code.BaseErrorCode; import com.example.demo.global.apiPayload.exception.GeneralException; -public class FoodExceptiodd extends GeneralException { - public FoodExceptiodd(BaseErrorCode code) { +public class MissionException extends GeneralException { + public MissionException(BaseErrorCode code) { super(code); } } + + + + diff --git a/src/main/java/com/example/demo/domain/mission/exception/code/MissionErrorCode.java b/src/main/java/com/example/demo/domain/mission/exception/code/MissionErrorCode.java new file mode 100644 index 0000000..a413605 --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/exception/code/MissionErrorCode.java @@ -0,0 +1,26 @@ +package com.example.demo.domain.mission.exception.code; + +import com.example.demo.global.apiPayload.code.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + + +@Getter +@AllArgsConstructor +public enum MissionErrorCode implements BaseErrorCode { + + NOT_FOUND(HttpStatus.NOT_FOUND, + "MISSION404_1", + "해당 미션을 찾지 못했습니다."), + ; + private final HttpStatus status; + private final String code; + private final String message; +} + + + + + + diff --git a/src/main/java/com/example/demo/domain/mission/exception/code/MissionSuccessCode.java b/src/main/java/com/example/demo/domain/mission/exception/code/MissionSuccessCode.java new file mode 100644 index 0000000..da1aac5 --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/exception/code/MissionSuccessCode.java @@ -0,0 +1,4 @@ +package com.example.demo.domain.mission.exception.code; + +public enum MissionSuccessCode { +} diff --git a/src/main/java/com/example/demo/domain/mission/repository/MemberMissionRepository.java b/src/main/java/com/example/demo/domain/mission/repository/MemberMissionRepository.java new file mode 100644 index 0000000..2fedef1 --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/repository/MemberMissionRepository.java @@ -0,0 +1,8 @@ +package com.example.demo.domain.mission.repository; + +import com.example.demo.domain.member.entity.mapping.MemberMission; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberMissionRepository extends JpaRepository { + boolean existsByMemberIdAndMissionId(Long memberId, Long missionId); +} diff --git a/src/main/java/com/example/demo/domain/mission/service/command/MissionCommandService.java b/src/main/java/com/example/demo/domain/mission/service/command/MissionCommandService.java new file mode 100644 index 0000000..066af71 --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/service/command/MissionCommandService.java @@ -0,0 +1,8 @@ +package com.example.demo.domain.mission.service.command; + +import com.example.demo.domain.member.entity.mapping.MemberMission; +import com.example.demo.domain.mission.dto.req.MissionReqDTO; + +public interface MissionCommandService { + public MemberMission joinMission(MissionReqDTO.MissionJoinDto request); +} diff --git a/src/main/java/com/example/demo/domain/mission/service/command/MissionCommandServiceImpl.java b/src/main/java/com/example/demo/domain/mission/service/command/MissionCommandServiceImpl.java new file mode 100644 index 0000000..841171a --- /dev/null +++ b/src/main/java/com/example/demo/domain/mission/service/command/MissionCommandServiceImpl.java @@ -0,0 +1,48 @@ +package com.example.demo.domain.mission.service.command; + + +import com.example.demo.domain.member.entity.Member; +import com.example.demo.domain.member.entity.mapping.MemberMission; +import com.example.demo.domain.member.exception.MemberException; +import com.example.demo.domain.member.exception.code.MemberErrorCode; +import com.example.demo.domain.member.repository.MemberRepository; +import com.example.demo.domain.mission.converter.MemberMissionConverter; +import com.example.demo.domain.mission.dto.req.MissionReqDTO; +import com.example.demo.domain.mission.entity.Mission; +import com.example.demo.domain.mission.exception.MissionException; +import com.example.demo.domain.mission.exception.code.MissionErrorCode; +import com.example.demo.domain.mission.repository.MemberMissionRepository; +import com.example.demo.domain.mission.repository.MissionRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class MissionCommandServiceImpl implements MissionCommandService { + + private final MissionRepository missionRepository; + private final MemberRepository memberRepository; + private final MemberMissionRepository memberMissionRepository; + + @Override + public MemberMission joinMission(MissionReqDTO.MissionJoinDto request) { + + // 1. 회원 존재 확인 + Member member = memberRepository.findById(request.getMemberId()) + .orElseThrow(() -> new MemberException(MemberErrorCode.NOT_FOUND)); + + // 2. 미션 존재 확인 + Mission mission = missionRepository.findById(request.getMissionId()) + .orElseThrow(() -> new MissionException(MissionErrorCode.NOT_FOUND)); + + // 3. 이미 도전 중인지 확인 -> 추가해야함 + + // 4. 매핑 엔티티 생성 및 저장 + MemberMission memberMission = MemberMissionConverter.toEntity(member, mission); + + return memberMissionRepository.save(memberMission); + } + +} diff --git a/src/main/java/com/example/demo/domain/store/exception/StoreException.java b/src/main/java/com/example/demo/domain/store/exception/StoreException.java index 3749e86..7e6b2bc 100644 --- a/src/main/java/com/example/demo/domain/store/exception/StoreException.java +++ b/src/main/java/com/example/demo/domain/store/exception/StoreException.java @@ -1,9 +1,10 @@ package com.example.demo.domain.store.exception; import com.example.demo.global.apiPayload.code.BaseErrorCode; +import com.example.demo.global.apiPayload.exception.GeneralException; -public class StoreException extends RuntimeException { +public class StoreException extends GeneralException { public StoreException(BaseErrorCode code) { - super((Throwable) code); + super(code); } } \ No newline at end of file