From f3d992219e981df367fe5813228c13c5749b0e45 Mon Sep 17 00:00:00 2001 From: Yeongjin Noh <129354455+nohy6630@users.noreply.github.com> Date: Wed, 15 Nov 2023 22:49:17 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=EB=A7=88=EC=9D=8C=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=20API=20=EC=B6=94=EA=B0=80=20(#61)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feat(#51): 후원 관련 엔티티 칼럼 설정 및 엔티티간 매핑 * Feat(#51): 커스텀 예외 설정 * Feat(#51): 후원 및 응원 api 개발 * Feat(#51): 후원 및 응원 관련 dto 작성 * Feat(#51): 후원 홈 목록 조회 관련 API 개발 * Feat(#51): 이미지, 후원사URL 데이터 추가 * Feat(#51): swagger 설명 추가 * Refactor(#51): Support 객체 생성 부분 리팩토링 * Refactor(#51): 이미지 변수명 변경 * Feat(#51): 마음 결제 API 구현 * Feat(#51): 후원시 사용자의 마음 갯수 반영 * Refactor(#51): 네이밍 변경 및 커스텀 예외 추가 * Refactor(#51): dto 폴더 위치 오류 수정 * Rename(#51): 폴더명 오타 수정 --- .../member/controller/MemberController.java | 39 +++++++++++++++++++ .../member/dto/request/BuyHeartRequest.java | 11 ++++++ .../member/dto/response/HeartCntResponse.java | 18 +++++++++ .../backend/domain/member/entity/Member.java | 14 ++++++- .../domain/member/service/MemberService.java | 16 ++++++++ .../dto/response/CreateSupportResponse.java | 3 +- .../support/service/SupportService.java | 6 ++- .../badrequest/BadRequestHeartException.java | 12 ++++++ .../context/CustomExceptionContext.java | 3 +- 9 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/numberone/backend/domain/member/controller/MemberController.java create mode 100644 src/main/java/com/numberone/backend/domain/member/dto/request/BuyHeartRequest.java create mode 100644 src/main/java/com/numberone/backend/domain/member/dto/response/HeartCntResponse.java create mode 100644 src/main/java/com/numberone/backend/exception/badrequest/BadRequestHeartException.java diff --git a/src/main/java/com/numberone/backend/domain/member/controller/MemberController.java b/src/main/java/com/numberone/backend/domain/member/controller/MemberController.java new file mode 100644 index 00000000..92e19892 --- /dev/null +++ b/src/main/java/com/numberone/backend/domain/member/controller/MemberController.java @@ -0,0 +1,39 @@ +package com.numberone.backend.domain.member.controller; + +import com.numberone.backend.domain.member.dto.request.BuyHeartRequest; +import com.numberone.backend.domain.member.dto.response.HeartCntResponse; +import com.numberone.backend.domain.member.service.MemberService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "members", description = "사용자 관련 API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/members") +public class MemberController { + private final MemberService memberService; + + @PostMapping("/heart") + @Operation(summary = "마음 구입하기", description = """ + 구입한 마음 갯수를 body에 담아 전달해주세요. + + response 에는 구입한 후에 사용자의 현재 마음 갯수가 저장되어 있습니다. + """) + public ResponseEntity buyHeart(@RequestBody @Valid BuyHeartRequest buyHeartRequest, Authentication authentication) { + return ResponseEntity.status(HttpStatus.CREATED).body(memberService.buyHeart(buyHeartRequest, authentication.getName())); + } + + @GetMapping("/heart") + @Operation(summary = "사용자의 현재 마음 갯수 가져오기", description = """ + 사용자의 현재 마음 갯수가 response로 전달됩니다. + """) + public ResponseEntity getHeart(Authentication authentication) { + return ResponseEntity.ok(memberService.getHeart(authentication.getName())); + } +} diff --git a/src/main/java/com/numberone/backend/domain/member/dto/request/BuyHeartRequest.java b/src/main/java/com/numberone/backend/domain/member/dto/request/BuyHeartRequest.java new file mode 100644 index 00000000..72498c9a --- /dev/null +++ b/src/main/java/com/numberone/backend/domain/member/dto/request/BuyHeartRequest.java @@ -0,0 +1,11 @@ +package com.numberone.backend.domain.member.dto.request; + +import jakarta.validation.constraints.NotNull; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +public class BuyHeartRequest { + @NotNull(message = "구입한 마음 갯수를 입력해주세요") + private Integer heartCnt; +} diff --git a/src/main/java/com/numberone/backend/domain/member/dto/response/HeartCntResponse.java b/src/main/java/com/numberone/backend/domain/member/dto/response/HeartCntResponse.java new file mode 100644 index 00000000..efb8117d --- /dev/null +++ b/src/main/java/com/numberone/backend/domain/member/dto/response/HeartCntResponse.java @@ -0,0 +1,18 @@ +package com.numberone.backend.domain.member.dto.response; + +import com.numberone.backend.domain.member.entity.Member; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@AllArgsConstructor +@Builder +public class HeartCntResponse { + private Integer heartCnt; + + public static HeartCntResponse of(Member member) { + return HeartCntResponse.builder() + .heartCnt(member.getHeartCnt()) + .build(); + } +} diff --git a/src/main/java/com/numberone/backend/domain/member/entity/Member.java b/src/main/java/com/numberone/backend/domain/member/entity/Member.java index 345732d2..4106b3cf 100644 --- a/src/main/java/com/numberone/backend/domain/member/entity/Member.java +++ b/src/main/java/com/numberone/backend/domain/member/entity/Member.java @@ -28,13 +28,23 @@ public class Member { private List supports = new ArrayList<>(); @Builder - public Member(String email) { + public Member(String email, Integer heartCnt) { this.email = email; + this.heartCnt = heartCnt; } - public static Member of(String email){ + public static Member of(String email) { return Member.builder() .email(email) + .heartCnt(0) .build(); } + + public void plusHeart(int heart) { + heartCnt += heart; + } + + public void minusHeart(int heart) { + heartCnt -= heart; + } } diff --git a/src/main/java/com/numberone/backend/domain/member/service/MemberService.java b/src/main/java/com/numberone/backend/domain/member/service/MemberService.java index 9a36d8d6..3da992d7 100644 --- a/src/main/java/com/numberone/backend/domain/member/service/MemberService.java +++ b/src/main/java/com/numberone/backend/domain/member/service/MemberService.java @@ -1,5 +1,7 @@ package com.numberone.backend.domain.member.service; +import com.numberone.backend.domain.member.dto.request.BuyHeartRequest; +import com.numberone.backend.domain.member.dto.response.HeartCntResponse; import com.numberone.backend.domain.member.entity.Member; import com.numberone.backend.domain.member.repository.MemberRepository; import com.numberone.backend.exception.notfound.NotFoundMemberException; @@ -22,4 +24,18 @@ public Member findByEmail(String email) { public void create(String email) { memberRepository.save(Member.of(email)); } + + @Transactional + public HeartCntResponse buyHeart(BuyHeartRequest buyHeartRequest, String email) { + Member member = memberRepository.findByEmail(email) + .orElseThrow(NotFoundMemberException::new); + member.plusHeart(buyHeartRequest.getHeartCnt()); + return HeartCntResponse.of(member); + } + + public HeartCntResponse getHeart(String email) { + Member member = memberRepository.findByEmail(email) + .orElseThrow(NotFoundMemberException::new); + return HeartCntResponse.of(member); + } } diff --git a/src/main/java/com/numberone/backend/domain/support/dto/response/CreateSupportResponse.java b/src/main/java/com/numberone/backend/domain/support/dto/response/CreateSupportResponse.java index 7d9498c5..cecccfba 100644 --- a/src/main/java/com/numberone/backend/domain/support/dto/response/CreateSupportResponse.java +++ b/src/main/java/com/numberone/backend/domain/support/dto/response/CreateSupportResponse.java @@ -1,5 +1,6 @@ package com.numberone.backend.domain.support.dto.response; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @Getter @@ -9,7 +10,7 @@ public class CreateSupportResponse { private Long supportId; - public static CreateSupportResponse of(Long supportId){ + public static CreateSupportResponse of(Long supportId) { return CreateSupportResponse.builder() .supportId(supportId) .build(); diff --git a/src/main/java/com/numberone/backend/domain/support/service/SupportService.java b/src/main/java/com/numberone/backend/domain/support/service/SupportService.java index 50a285a6..e4f9463b 100644 --- a/src/main/java/com/numberone/backend/domain/support/service/SupportService.java +++ b/src/main/java/com/numberone/backend/domain/support/service/SupportService.java @@ -9,11 +9,10 @@ import com.numberone.backend.domain.support.dto.response.CreateSupportResponse; import com.numberone.backend.domain.support.entity.Support; import com.numberone.backend.domain.support.repository.SupportRepository; +import com.numberone.backend.exception.badrequest.BadRequestHeartException; import com.numberone.backend.exception.notfound.NotFoundMemberException; import com.numberone.backend.exception.notfound.NotFoundSupportException; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.apache.tomcat.util.net.openssl.ciphers.Authentication; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -38,10 +37,13 @@ public CreateSupportResponse create(CreateSupportRequest createSupportRequest, S .orElseThrow(NotFoundSupportException::new); Member member = memberRepository.findByEmail(email) .orElseThrow(NotFoundMemberException::new); + if (member.getHeartCnt() < createSupportRequest.getHeartCnt()) + throw new BadRequestHeartException(); Support support = Support.of( sponsor, member ); + member.minusHeart(createSupportRequest.getHeartCnt()); sponsor.increaseHeart(createSupportRequest.getHeartCnt()); support = supportRepository.save(support); return CreateSupportResponse.of(support.getId()); diff --git a/src/main/java/com/numberone/backend/exception/badrequest/BadRequestHeartException.java b/src/main/java/com/numberone/backend/exception/badrequest/BadRequestHeartException.java new file mode 100644 index 00000000..14dc35f5 --- /dev/null +++ b/src/main/java/com/numberone/backend/exception/badrequest/BadRequestHeartException.java @@ -0,0 +1,12 @@ +package com.numberone.backend.exception.badrequest; + +import com.numberone.backend.exception.context.ExceptionContext; + +import static com.numberone.backend.exception.context.CustomExceptionContext.BAD_REQUEST_HEART; + +public class BadRequestHeartException extends BadRequestException{ + + public BadRequestHeartException() { + super(BAD_REQUEST_HEART); + } +} diff --git a/src/main/java/com/numberone/backend/exception/context/CustomExceptionContext.java b/src/main/java/com/numberone/backend/exception/context/CustomExceptionContext.java index 172c44a2..e77d699d 100644 --- a/src/main/java/com/numberone/backend/exception/context/CustomExceptionContext.java +++ b/src/main/java/com/numberone/backend/exception/context/CustomExceptionContext.java @@ -34,7 +34,8 @@ public enum CustomExceptionContext implements ExceptionContext { //후원 페이지 관련 예외 NOT_FOUND_SUPPORT("존재하지 않는 후원 관계입니다.", 7000), - NOT_FOUND_SPONSOR("존재하지 않는 후원입니다.", 7001) + NOT_FOUND_SPONSOR("존재하지 않는 후원입니다.", 7001), + BAD_REQUEST_HEART("후원을 하기에는 사용자의 마음 갯수가 부족합니다.",7002) ; private final String message;