diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index e3d8a51a..b1ad4db9 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -99,11 +99,6 @@ * link:purchase-check.html[구독 상태 및 열람권 개수 조회하기] -=== Pay API - -- @Deprecated at 2024.03 -* link:pay.html[결제 전환율 체크] - === Notice API * 🆕 link:find-notice.html[공지 조회, 2024-01-29] diff --git a/src/docs/asciidoc/pay.adoc b/src/docs/asciidoc/pay.adoc deleted file mode 100644 index 14a67d19..00000000 --- a/src/docs/asciidoc/pay.adoc +++ /dev/null @@ -1,10 +0,0 @@ -:reproducible: -== 친구 추가하기 - -=== 요청 - -include::{snippets}/api/v1/pay/postPayCount/http-request.adoc[] - -=== 응답 - -include::{snippets}/api/v1/pay/postPayCount/http-response.adoc[] diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java index b635332c..2b76a64b 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java @@ -50,8 +50,7 @@ protected void doFilterInternal( || requestPath.startsWith("/v2/google/notifications") || requestPath.startsWith("/api/v1/admob/verify") || requestPath.startsWith("/api/v1/statistics") - || (requestPath.startsWith("/api/v1/auth") - && !requestPath.startsWith("/api/v1/auth/token/issue"))) { + || (requestPath.startsWith("/api/v1/auth") && !requestPath.startsWith("/api/v1/auth/token/issue"))) { filterChain.doFilter(request, response); return; } @@ -68,6 +67,22 @@ protected void doFilterInternal( throw new CustomAuthenticationException(AUTHENTICATION_ERROR); } + val token = accessHeader.substring(BEARER.length()); + Long userId = tokenProvider.getUserId(token); + request.setAttribute("userId", userId); + } else if (requestPath.equals("/api/v1/user/post/comment")) { + val accessHeader = request.getHeader(AUTHORIZATION); + log.info("Authorization : {}", accessHeader); + + if (accessHeader == null) { + filterChain.doFilter(request, response); + return; + } + + if (!accessHeader.startsWith(BEARER)) { + throw new CustomAuthenticationException(AUTHENTICATION_ERROR); + } + val token = accessHeader.substring(BEARER.length()); Long userId = tokenProvider.getUserId(token); request.setAttribute("userId", userId); diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java index 7689136b..3bcc310e 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java @@ -1,5 +1,7 @@ package com.yello.server.domain.authorization.filter; +import static org.springframework.http.HttpHeaders.AUTHORIZATION; + import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserRepository; import jakarta.servlet.FilterChain; @@ -48,6 +50,11 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse return; } + if (requestPath.equals("/api/v1/user/post/comment") && request.getHeader(AUTHORIZATION) == null) { + filterChain.doFilter(request, response); + return; + } + final Long userId = (Long) request.getAttribute("userId"); log.info("Current user's id: {}", userId); diff --git a/src/main/java/com/yello/server/domain/pay/controller/PayController.java b/src/main/java/com/yello/server/domain/pay/controller/PayController.java deleted file mode 100644 index e7a8bf1e..00000000 --- a/src/main/java/com/yello/server/domain/pay/controller/PayController.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.yello.server.domain.pay.controller; - -import static com.yello.server.global.common.SuccessCode.CREATE_PAY_COUNT; - -import com.yello.server.domain.pay.dto.request.PayCountRequest; -import com.yello.server.domain.pay.service.PayService; -import com.yello.server.domain.user.entity.User; -import com.yello.server.global.common.annotation.AccessTokenUser; -import com.yello.server.global.common.dto.BaseResponse; -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 -@RequestMapping("api/v1/pay") -@RequiredArgsConstructor -public class PayController { - - private final PayService payService; - - @PostMapping - public BaseResponse postPayCount(@AccessTokenUser User user, @RequestBody PayCountRequest request) { - payService.postPayCount(user.getId(), request.index()); - return BaseResponse.success(CREATE_PAY_COUNT); - } -} diff --git a/src/main/java/com/yello/server/domain/pay/dto/request/PayCountRequest.java b/src/main/java/com/yello/server/domain/pay/dto/request/PayCountRequest.java deleted file mode 100644 index f54bbe4f..00000000 --- a/src/main/java/com/yello/server/domain/pay/dto/request/PayCountRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.yello.server.domain.pay.dto.request; - -import lombok.Builder; - -@Builder -public record PayCountRequest( - Integer index -) { - -} diff --git a/src/main/java/com/yello/server/domain/pay/repository/PayJpaRepository.java b/src/main/java/com/yello/server/domain/pay/repository/PayJpaRepository.java deleted file mode 100644 index 7b32874d..00000000 --- a/src/main/java/com/yello/server/domain/pay/repository/PayJpaRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.yello.server.domain.pay.repository; - -import com.yello.server.domain.pay.entity.Pay; -import com.yello.server.domain.user.entity.User; -import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface PayJpaRepository extends JpaRepository { - - List findAllByUserAndOptionIndex(User user, Integer optionIndex); -} diff --git a/src/main/java/com/yello/server/domain/pay/repository/PayRepository.java b/src/main/java/com/yello/server/domain/pay/repository/PayRepository.java deleted file mode 100644 index 778aec1e..00000000 --- a/src/main/java/com/yello/server/domain/pay/repository/PayRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.yello.server.domain.pay.repository; - -import com.yello.server.domain.pay.entity.Pay; -import com.yello.server.domain.user.entity.User; -import java.util.List; - -public interface PayRepository { - - Pay save(Pay pay); - - List findAllByUserAndOptionIndex(User user, Integer optionIndex); -} diff --git a/src/main/java/com/yello/server/domain/pay/repository/PayRepositoryImpl.java b/src/main/java/com/yello/server/domain/pay/repository/PayRepositoryImpl.java deleted file mode 100644 index 457d21a3..00000000 --- a/src/main/java/com/yello/server/domain/pay/repository/PayRepositoryImpl.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.yello.server.domain.pay.repository; - -import com.yello.server.domain.pay.entity.Pay; -import com.yello.server.domain.user.entity.User; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -public class PayRepositoryImpl implements PayRepository { - - private final PayJpaRepository payJpaRepository; - - @Override - public Pay save(Pay pay) { - return payJpaRepository.save(pay); - } - - @Override - public List findAllByUserAndOptionIndex(User user, Integer optionIndex) { - return payJpaRepository.findAllByUserAndOptionIndex(user, optionIndex); - } -} diff --git a/src/main/java/com/yello/server/domain/pay/service/PayService.java b/src/main/java/com/yello/server/domain/pay/service/PayService.java deleted file mode 100644 index 4ccd1548..00000000 --- a/src/main/java/com/yello/server/domain/pay/service/PayService.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.yello.server.domain.pay.service; - -import com.yello.server.domain.pay.entity.Pay; -import com.yello.server.domain.pay.repository.PayRepository; -import com.yello.server.domain.user.entity.User; -import com.yello.server.domain.user.repository.UserRepository; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class PayService { - - private final UserRepository userRepository; - private final PayRepository payRepository; - - @Transactional - public void postPayCount(Long userId, Integer optionIndex) { - final User user = userRepository.getById(userId); - final List allByUserAndIndex = payRepository.findAllByUserAndOptionIndex(user, - optionIndex); - if (allByUserAndIndex.isEmpty()) { - payRepository.save(Pay.createPay(optionIndex, user)); - } - } -} diff --git a/src/main/java/com/yello/server/domain/user/controller/UserController.java b/src/main/java/com/yello/server/domain/user/controller/UserController.java index d3705f9d..16316a6d 100644 --- a/src/main/java/com/yello/server/domain/user/controller/UserController.java +++ b/src/main/java/com/yello/server/domain/user/controller/UserController.java @@ -1,6 +1,8 @@ package com.yello.server.domain.user.controller; import static com.yello.server.global.common.SuccessCode.DELETE_USER_SUCCESS; +import static com.yello.server.global.common.SuccessCode.GET_USER_POST_COMMENT_SUCCESS; +import static com.yello.server.global.common.SuccessCode.POST_USER_POST_COMMENT_SUCCESS; import static com.yello.server.global.common.SuccessCode.READ_USER_DATA_SUCCESS; import static com.yello.server.global.common.SuccessCode.READ_USER_SUBSCRIBE_SUCCESS; import static com.yello.server.global.common.SuccessCode.READ_USER_SUCCESS; @@ -11,10 +13,12 @@ import com.yello.server.domain.user.dto.request.UserDataUpdateRequest; import com.yello.server.domain.user.dto.request.UserDeleteReasonRequest; import com.yello.server.domain.user.dto.request.UserDeviceTokenRequest; +import com.yello.server.domain.user.dto.request.UserPostCommentUpdateRequest; import com.yello.server.domain.user.dto.request.UserUpdateRequest; import com.yello.server.domain.user.dto.response.UserDataResponse; import com.yello.server.domain.user.dto.response.UserDetailResponse; import com.yello.server.domain.user.dto.response.UserDetailV2Response; +import com.yello.server.domain.user.dto.response.UserPostCommentResponse; import com.yello.server.domain.user.dto.response.UserResponse; import com.yello.server.domain.user.dto.response.UserSubscribeDetailResponse; import com.yello.server.domain.user.entity.User; @@ -23,8 +27,10 @@ import com.yello.server.global.common.annotation.AccessTokenUser; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.global.common.dto.EmptyObject; +import jakarta.annotation.Nullable; import lombok.RequiredArgsConstructor; import lombok.val; +import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -32,6 +38,7 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -105,4 +112,19 @@ public BaseResponse updateUserData(@AccessTokenUser User user, @PathVariable("ta userService.updateUserData(user.getId(), UserDataType.fromCode(tag), request); return BaseResponse.success(UPDATE_USER_DATA_SUCCESS); } + + @GetMapping("/v1/user/post/comment") + public BaseResponse getUserPostComment(@Nullable @AccessTokenUser User user, + @RequestParam(value = "postId") Long postId, Pageable pageable) { + System.out.println("user = " + user); + val data = userService.getUserPostComment(user == null ? null : user.getId(), postId, pageable); + return BaseResponse.success(GET_USER_POST_COMMENT_SUCCESS, data); + } + + @PostMapping("/v1/user/post/comment") + public BaseResponse postUserPostComment(@Nullable @AccessTokenUser User user, + @RequestBody UserPostCommentUpdateRequest request) { + userService.updatePostComment(user == null ? null : user.getId(), request); + return BaseResponse.success(POST_USER_POST_COMMENT_SUCCESS); + } } diff --git a/src/main/java/com/yello/server/domain/user/dto/request/UserPostCommentUpdateRequest.java b/src/main/java/com/yello/server/domain/user/dto/request/UserPostCommentUpdateRequest.java new file mode 100644 index 00000000..8fc53506 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/dto/request/UserPostCommentUpdateRequest.java @@ -0,0 +1,16 @@ +package com.yello.server.domain.user.dto.request; + +import jakarta.annotation.Nullable; + +public record UserPostCommentUpdateRequest( + @Nullable Long id, + Long postId, + String userName, + String yelloId, + String status, + String title, + String subtitle, + String content +) { + +} diff --git a/src/main/java/com/yello/server/domain/user/dto/response/UserPostCommentResponse.java b/src/main/java/com/yello/server/domain/user/dto/response/UserPostCommentResponse.java new file mode 100644 index 00000000..154b9b97 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/dto/response/UserPostCommentResponse.java @@ -0,0 +1,13 @@ +package com.yello.server.domain.user.dto.response; + +import java.util.List; +import lombok.Builder; + +@Builder +public record UserPostCommentResponse( + Long pageCount, + Long totalCount, + List postCommentList +) { + +} diff --git a/src/main/java/com/yello/server/domain/user/dto/response/UserPostCommentVO.java b/src/main/java/com/yello/server/domain/user/dto/response/UserPostCommentVO.java new file mode 100644 index 00000000..5967aac7 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/dto/response/UserPostCommentVO.java @@ -0,0 +1,40 @@ +package com.yello.server.domain.user.dto.response; + +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.entity.UserPost; +import com.yello.server.domain.user.entity.UserPostComment; +import lombok.Builder; + +@Builder +public record UserPostCommentVO( + Long id, + Long userPostId, + Long userId, + String status, + String userName, + String yelloId, + String title, + String subtitle, + String content, + String createdAt, + String updatedAt +) { + + public static UserPostCommentVO of(UserPostComment userPostComment) { + UserPost userPost = userPostComment.getUserPost(); + User user = userPostComment.getUser(); + return UserPostCommentVO.builder() + .id(userPostComment.getId()) + .userPostId(userPost == null ? null : userPost.getId()) + .userId(user == null ? null : user.getId()) + .status(userPostComment.getStatus().getInitial()) + .userName(userPostComment.getUserName()) + .yelloId(userPostComment.getYelloId()) + .title(userPostComment.getTitle()) + .subtitle(userPostComment.getSubtitle()) + .content(userPostComment.getContent()) + .createdAt(String.valueOf(userPostComment.getCreatedAt())) + .updatedAt(String.valueOf(userPostComment.getUpdatedAt())) + .build(); + } +} diff --git a/src/main/java/com/yello/server/domain/pay/entity/Pay.java b/src/main/java/com/yello/server/domain/user/entity/UserPost.java similarity index 52% rename from src/main/java/com/yello/server/domain/pay/entity/Pay.java rename to src/main/java/com/yello/server/domain/user/entity/UserPost.java index 47463c7d..b9cfe813 100644 --- a/src/main/java/com/yello/server/domain/pay/entity/Pay.java +++ b/src/main/java/com/yello/server/domain/user/entity/UserPost.java @@ -1,6 +1,8 @@ -package com.yello.server.domain.pay.entity; +package com.yello.server.domain.user.entity; -import com.yello.server.domain.user.entity.User; +import com.yello.server.global.common.dto.AuditingTimeEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; @@ -16,32 +18,39 @@ import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; -@Entity @Getter +@Entity @Builder @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Pay { +public class UserPost extends AuditingTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private Integer optionIndex; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "userId") - @OnDelete(action = OnDeleteAction.CASCADE) + @OnDelete(action = OnDeleteAction.SET_NULL) + @JoinColumn(name = "userId", nullable = true) private User user; - public static Pay of(Integer optionIndex, User user) { - return Pay.builder() - .optionIndex(optionIndex) - .user(user) - .build(); - } - - public static Pay createPay(Integer optionIndex, User user) { - return Pay.of(optionIndex, user); - } -} + @Column(nullable = false) + @Convert(converter = UserPostStatusConverter.class) + private UserPostStatus status; + + @Column + private String userName; + + @Column + private String yelloId; + + @Column + private String title; + + @Column + private String subtitle; + + @Column(columnDefinition = "MEDIUMTEXT") + private String content; + +} \ No newline at end of file diff --git a/src/main/java/com/yello/server/domain/user/entity/UserPostComment.java b/src/main/java/com/yello/server/domain/user/entity/UserPostComment.java new file mode 100644 index 00000000..a482f709 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/entity/UserPostComment.java @@ -0,0 +1,73 @@ +package com.yello.server.domain.user.entity; + +import com.yello.server.domain.user.dto.request.UserPostCommentUpdateRequest; +import com.yello.server.global.common.dto.AuditingTimeEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; + +@Getter +@Entity +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserPostComment extends AuditingTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.RESTRICT) + @JoinColumn(name = "userPostId", nullable = false) + private UserPost userPost; + + @ManyToOne(fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.SET_NULL) + @JoinColumn(name = "userId", nullable = true) + private User user; + + @Column(nullable = false) + @Convert(converter = UserPostCommentStatusConverter.class) + private UserPostCommentStatus status; + + @Column + private String userName; + + @Column + private String yelloId; + + @Column + private String title; + + @Column + private String subtitle; + + @Column(columnDefinition = "TEXT") + private String content; + + public void update(UserPostCommentUpdateRequest request, UserPost userPost, User user, + UserPostCommentStatus status) { + this.userPost = userPost; + this.user = user; + this.status = status; + this.userName = request.userName(); + this.yelloId = request.yelloId(); + this.title = request.title(); + this.subtitle = request.subtitle(); + this.content = request.content(); + } +} diff --git a/src/main/java/com/yello/server/domain/user/entity/UserPostCommentStatus.java b/src/main/java/com/yello/server/domain/user/entity/UserPostCommentStatus.java new file mode 100644 index 00000000..d3757166 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/entity/UserPostCommentStatus.java @@ -0,0 +1,31 @@ +package com.yello.server.domain.user.entity; + +import static com.yello.server.global.common.ErrorCode.ENUM_BAD_REQUEST_EXCEPTION; + +import com.yello.server.global.exception.EnumIllegalArgumentException; +import java.util.Arrays; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum UserPostCommentStatus { + ACTIVE("ACTIVE"), + INACTIVE("INACTIVE"); + + private final String initial; + + public static UserPostCommentStatus fromCode(String dbData) { + return Arrays.stream(UserPostCommentStatus.values()) + .filter(v -> v.getInitial().equals(dbData)) + .findAny() + .orElseThrow(() -> new EnumIllegalArgumentException(ENUM_BAD_REQUEST_EXCEPTION)); + } + + public static UserPostCommentStatus fromName(String name) { + return Arrays.stream(UserPostCommentStatus.values()) + .filter(v -> v.name().equals(name)) + .findAny() + .orElseThrow(() -> new EnumIllegalArgumentException(ENUM_BAD_REQUEST_EXCEPTION)); + } +} diff --git a/src/main/java/com/yello/server/domain/user/entity/UserPostCommentStatusConverter.java b/src/main/java/com/yello/server/domain/user/entity/UserPostCommentStatusConverter.java new file mode 100644 index 00000000..f533ffa2 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/entity/UserPostCommentStatusConverter.java @@ -0,0 +1,25 @@ +package com.yello.server.domain.user.entity; + +import jakarta.persistence.AttributeConverter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class UserPostCommentStatusConverter implements AttributeConverter { + + @Override + public String convertToDatabaseColumn(UserPostCommentStatus userData) { + if (userData == null) { + return null; + } + return userData.name(); + } + + @Override + public UserPostCommentStatus convertToEntityAttribute(String dbData) { + if (dbData == null) { + return null; + } + + return UserPostCommentStatus.fromName(dbData); + } +} diff --git a/src/main/java/com/yello/server/domain/user/entity/UserPostStatus.java b/src/main/java/com/yello/server/domain/user/entity/UserPostStatus.java new file mode 100644 index 00000000..d69fef30 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/entity/UserPostStatus.java @@ -0,0 +1,31 @@ +package com.yello.server.domain.user.entity; + +import static com.yello.server.global.common.ErrorCode.ENUM_BAD_REQUEST_EXCEPTION; + +import com.yello.server.global.exception.EnumIllegalArgumentException; +import java.util.Arrays; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum UserPostStatus { + ACTIVE("ACTIVE"), + INACTIVE("INACTIVE"); + + private final String initial; + + public static UserPostStatus fromCode(String dbData) { + return Arrays.stream(UserPostStatus.values()) + .filter(v -> v.getInitial().equals(dbData)) + .findAny() + .orElseThrow(() -> new EnumIllegalArgumentException(ENUM_BAD_REQUEST_EXCEPTION)); + } + + public static UserPostStatus fromName(String name) { + return Arrays.stream(UserPostStatus.values()) + .filter(v -> v.name().equals(name)) + .findAny() + .orElseThrow(() -> new EnumIllegalArgumentException(ENUM_BAD_REQUEST_EXCEPTION)); + } +} diff --git a/src/main/java/com/yello/server/domain/user/entity/UserPostStatusConverter.java b/src/main/java/com/yello/server/domain/user/entity/UserPostStatusConverter.java new file mode 100644 index 00000000..7b851bf4 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/entity/UserPostStatusConverter.java @@ -0,0 +1,25 @@ +package com.yello.server.domain.user.entity; + +import jakarta.persistence.AttributeConverter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class UserPostStatusConverter implements AttributeConverter { + + @Override + public String convertToDatabaseColumn(UserPostStatus userData) { + if (userData == null) { + return null; + } + return userData.name(); + } + + @Override + public UserPostStatus convertToEntityAttribute(String dbData) { + if (dbData == null) { + return null; + } + + return UserPostStatus.fromName(dbData); + } +} diff --git a/src/main/java/com/yello/server/domain/user/exception/UserPostNotFoundException.java b/src/main/java/com/yello/server/domain/user/exception/UserPostNotFoundException.java new file mode 100644 index 00000000..1a77ebd3 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/exception/UserPostNotFoundException.java @@ -0,0 +1,13 @@ +package com.yello.server.domain.user.exception; + +import com.yello.server.global.common.ErrorCode; +import com.yello.server.global.exception.CustomException; +import lombok.Getter; + +@Getter +public class UserPostNotFoundException extends CustomException { + + public UserPostNotFoundException(ErrorCode error) { + super(error, "[UserPostNotFoundException] " + error.getMessage()); + } +} diff --git a/src/main/java/com/yello/server/domain/user/repository/UserPostCommentJpaRepository.java b/src/main/java/com/yello/server/domain/user/repository/UserPostCommentJpaRepository.java new file mode 100644 index 00000000..9547bba5 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/repository/UserPostCommentJpaRepository.java @@ -0,0 +1,24 @@ +package com.yello.server.domain.user.repository; + +import com.yello.server.domain.user.entity.UserPostComment; +import com.yello.server.domain.user.entity.UserPostCommentStatus; +import java.util.List; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface UserPostCommentJpaRepository extends JpaRepository { + + @Query("SELECT count(upc) FROM UserPostComment upc WHERE upc.userPost.id = ?1 AND upc.status = ?2") + Long countByPostId(Long postId, UserPostCommentStatus status); + + @Query("SELECT count(upc) FROM UserPostComment upc WHERE upc.userPost.id = ?1 AND upc.user.id = ?2 AND upc.status = ?3") + Long countByPostIdAndUserId(Long postId, Long userId, UserPostCommentStatus status); + + @Query("SELECT upc FROM UserPostComment upc WHERE upc.userPost.id = ?1 AND upc.status = ?2") + List findAllByPostId(Long postId, UserPostCommentStatus status, Pageable pageable); + + @Query("SELECT upc FROM UserPostComment upc WHERE upc.userPost.id = ?1 AND upc.user.id = ?2 AND upc.status = ?3") + List findAllByPostIdAndUserId(Long postId, Long userId, UserPostCommentStatus status, + Pageable pageable); +} diff --git a/src/main/java/com/yello/server/domain/user/repository/UserPostJpaRepository.java b/src/main/java/com/yello/server/domain/user/repository/UserPostJpaRepository.java new file mode 100644 index 00000000..32530b73 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/repository/UserPostJpaRepository.java @@ -0,0 +1,8 @@ +package com.yello.server.domain.user.repository; + +import com.yello.server.domain.user.entity.UserPost; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserPostJpaRepository extends JpaRepository { + +} diff --git a/src/main/java/com/yello/server/domain/user/repository/UserPostRepository.java b/src/main/java/com/yello/server/domain/user/repository/UserPostRepository.java new file mode 100644 index 00000000..9d5fdb04 --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/repository/UserPostRepository.java @@ -0,0 +1,29 @@ +package com.yello.server.domain.user.repository; + +import com.yello.server.domain.user.entity.UserPost; +import com.yello.server.domain.user.entity.UserPostComment; +import com.yello.server.domain.user.entity.UserPostCommentStatus; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Pageable; + +public interface UserPostRepository { + + Long countPostCommentByPostId(Long postId, UserPostCommentStatus status); + + Long countPostCommentByPostIdAndUserId(Long postId, Long userId, UserPostCommentStatus status); + + List findAllByPostId(Long postId, UserPostCommentStatus status, Pageable pageable); + + List findAllByPostIdAndUserId(Long postId, Long userId, UserPostCommentStatus status, + Pageable pageable); + + UserPostComment getCommentById(Long userPostCommentId); + + UserPostComment save(UserPostComment userPostComment); + + UserPost getPostById(Long userPostId); + + Optional findPostById(Long userPostId); + +} diff --git a/src/main/java/com/yello/server/domain/user/repository/UserPostRepositoryImpl.java b/src/main/java/com/yello/server/domain/user/repository/UserPostRepositoryImpl.java new file mode 100644 index 00000000..4de7d6bd --- /dev/null +++ b/src/main/java/com/yello/server/domain/user/repository/UserPostRepositoryImpl.java @@ -0,0 +1,65 @@ +package com.yello.server.domain.user.repository; + +import static com.yello.server.global.common.ErrorCode.USER_POST_COMMENT_NOT_FOUND_EXCEPTION; +import static com.yello.server.global.common.ErrorCode.USER_POST_NOT_FOUND_EXCEPTION; + +import com.yello.server.domain.user.entity.UserPost; +import com.yello.server.domain.user.entity.UserPostComment; +import com.yello.server.domain.user.entity.UserPostCommentStatus; +import com.yello.server.domain.user.exception.UserPostNotFoundException; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class UserPostRepositoryImpl implements UserPostRepository { + + private final UserPostCommentJpaRepository userPostCommentJpaRepository; + private final UserPostJpaRepository userPostJpaRepository; + + @Override + public Long countPostCommentByPostId(Long postId, UserPostCommentStatus status) { + return userPostCommentJpaRepository.countByPostId(postId, status); + } + + @Override + public Long countPostCommentByPostIdAndUserId(Long postId, Long userId, UserPostCommentStatus status) { + return userPostCommentJpaRepository.countByPostIdAndUserId(postId, userId, status); + } + + @Override + public List findAllByPostId(Long postId, UserPostCommentStatus status, Pageable pageable) { + return userPostCommentJpaRepository.findAllByPostId(postId, status, pageable); + } + + @Override + public List findAllByPostIdAndUserId(Long postId, Long userId, UserPostCommentStatus status, + Pageable pageable) { + return userPostCommentJpaRepository.findAllByPostIdAndUserId(postId, userId, status, pageable); + } + + @Override + public UserPostComment getCommentById(Long userPostCommentId) { + return userPostCommentJpaRepository.findById(userPostCommentId) + .orElseThrow(() -> new UserPostNotFoundException(USER_POST_COMMENT_NOT_FOUND_EXCEPTION)); + } + + @Override + public UserPostComment save(UserPostComment userPostComment) { + return userPostCommentJpaRepository.save(userPostComment); + } + + @Override + public UserPost getPostById(Long userPostId) { + return userPostJpaRepository.findById(userPostId) + .orElseThrow(() -> new UserPostNotFoundException(USER_POST_NOT_FOUND_EXCEPTION)); + } + + @Override + public Optional findPostById(Long userPostId) { + return userPostJpaRepository.findById(userPostId); + } +} diff --git a/src/main/java/com/yello/server/domain/user/service/UserService.java b/src/main/java/com/yello/server/domain/user/service/UserService.java index 4fec5687..5daa1214 100644 --- a/src/main/java/com/yello/server/domain/user/service/UserService.java +++ b/src/main/java/com/yello/server/domain/user/service/UserService.java @@ -17,29 +17,40 @@ import com.yello.server.domain.user.dto.request.UserDataUpdateRequest; import com.yello.server.domain.user.dto.request.UserDeleteReasonRequest; import com.yello.server.domain.user.dto.request.UserDeviceTokenRequest; +import com.yello.server.domain.user.dto.request.UserPostCommentUpdateRequest; import com.yello.server.domain.user.dto.request.UserUpdateRequest; import com.yello.server.domain.user.dto.response.UserDataResponse; import com.yello.server.domain.user.dto.response.UserDetailResponse; import com.yello.server.domain.user.dto.response.UserDetailV2Response; +import com.yello.server.domain.user.dto.response.UserPostCommentResponse; +import com.yello.server.domain.user.dto.response.UserPostCommentVO; import com.yello.server.domain.user.dto.response.UserResponse; import com.yello.server.domain.user.dto.response.UserSubscribeDetailResponse; import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.entity.UserData; import com.yello.server.domain.user.entity.UserDataType; +import com.yello.server.domain.user.entity.UserPost; +import com.yello.server.domain.user.entity.UserPostComment; +import com.yello.server.domain.user.entity.UserPostCommentStatus; import com.yello.server.domain.user.exception.UserConflictException; import com.yello.server.domain.user.exception.UserException; import com.yello.server.domain.user.repository.UserDataRepository; +import com.yello.server.domain.user.repository.UserPostRepository; import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.global.common.dto.EmptyObject; import com.yello.server.global.common.util.ConstantUtil; +import jakarta.annotation.Nullable; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import lombok.Builder; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -55,6 +66,7 @@ public class UserService { private final UserAdminRepository userAdminRepository; private final UserDataRepository userDataRepository; private final UserGroupRepository userGroupRepository; + private final UserPostRepository userPostRepository; private final UserRepository userRepository; private final VoteRepository voteRepository; @@ -194,4 +206,59 @@ public void updateUserData(Long userId, UserDataType tag, UserDataUpdateRequest userDataRepository.save(UserData.of(tag, savedValue, user)); } } + + @Transactional + public void updatePostComment(@Nullable Long userId, UserPostCommentUpdateRequest request) { + Optional user = userRepository.findById(userId); + UserPost userPost = userPostRepository.getPostById(request.postId()); + UserPostCommentStatus status = UserPostCommentStatus.fromCode(request.status()); + + if (request.id() == null) { + userPostRepository.save(UserPostComment.builder() + .userPost(userPost) + .user(user.orElse(null)) + .status(status) + .userName(user.isPresent() ? user.get().getName() : request.userName()) + .yelloId(user.isPresent() ? user.get().getYelloId() : request.yelloId()) + .title(request.title()) + .subtitle(request.subtitle()) + .content(request.content()) + .build()); + } else { + UserPostComment userPostComment = userPostRepository.getCommentById(request.id()); + userPostComment.update(request, userPost, user.orElse(null), status); + } + } + + public UserPostCommentResponse getUserPostComment(@Nullable Long userId, Long postId, Pageable pageable) { + // exception + userPostRepository.getPostById(postId); + + // logic + Long totalCount; + long pageSize = pageable.getPageSize(); + List userPostCommentList = new ArrayList<>(); + + if (userId == null) { + totalCount = userPostRepository.countPostCommentByPostId(postId, UserPostCommentStatus.ACTIVE); + userPostCommentList.addAll( + userPostRepository.findAllByPostId(postId, UserPostCommentStatus.ACTIVE, pageable) + .stream().map(UserPostCommentVO::of).toList() + ); + } else { + totalCount = userPostRepository.countPostCommentByPostIdAndUserId(postId, userId, + UserPostCommentStatus.ACTIVE); + userPostCommentList.addAll( + userPostRepository.findAllByPostIdAndUserId(postId, userId, UserPostCommentStatus.ACTIVE, pageable) + .stream().map(UserPostCommentVO::of).toList() + ); + } + + return UserPostCommentResponse.builder() + .pageCount(totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1) + .totalCount(totalCount) + .postCommentList(userPostCommentList) + .build(); + } + } diff --git a/src/main/java/com/yello/server/global/common/ErrorCode.java b/src/main/java/com/yello/server/global/common/ErrorCode.java index f27e7a9e..a34de675 100644 --- a/src/main/java/com/yello/server/global/common/ErrorCode.java +++ b/src/main/java/com/yello/server/global/common/ErrorCode.java @@ -112,6 +112,8 @@ public enum ErrorCode { NOT_FOUND_EVENT_REWARD_EXCEPTION(NOT_FOUND, "해당 EventReward가 존재하지 않습니다."), EMPTY_QUERY_STRING_EXCEPTION(NOT_FOUND, "query string 값이 null 입니다."), STATISTICS_NOT_FOUND_EXCEPTION(NOT_FOUND, "해당 통계가 존재하지 않습니다."), + USER_POST_NOT_FOUND_EXCEPTION(NOT_FOUND, "해당 포스트가 존재하지 않습니다."), + USER_POST_COMMENT_NOT_FOUND_EXCEPTION(NOT_FOUND, "해당 댓글이 존재하지 않습니다."), /** * 409 CONFLICT diff --git a/src/main/java/com/yello/server/global/common/SuccessCode.java b/src/main/java/com/yello/server/global/common/SuccessCode.java index d6ea3b9c..e2669038 100644 --- a/src/main/java/com/yello/server/global/common/SuccessCode.java +++ b/src/main/java/com/yello/server/global/common/SuccessCode.java @@ -65,6 +65,8 @@ public enum SuccessCode { VERIFY_ADMOB_SSV_SUCCESS(OK, "Admob ssv 검증에 성공하였습니다."), GET_IS_POSSIBLE_ADMOB_SUCCESS(OK, "광고 보고 포인트 얻기 가능 여부 조회에 성공했습니다."), READ_USER_GROUP_SCHOOL_ATTACK_STATISTICS_SUCCESS(OK, "School Attack 통계 조회에 성공하였습니다."), + GET_USER_POST_COMMENT_SUCCESS(OK, "댓글 조회에 성공하였습니다."), + POST_USER_POST_COMMENT_SUCCESS(OK, "댓글 작성에 성공하였습니다."), /** * 201 CREATED diff --git a/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java b/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java index fc204ea0..40daadf1 100644 --- a/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java +++ b/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java @@ -5,6 +5,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * Resolves SecurityContextHolder.getContext().getAuthentication().getDetails(); + *

+ * if valid request doesn't include Authorization field in header, return null + * + * @see com.yello.server.global.common.annotation.AccessTokenUserResolver + * @see com.yello.server.domain.authorization.filter.JwtFilter + * @see com.yello.server.domain.authorization.filter.JwtExceptionFilter + */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface AccessTokenUser { diff --git a/src/main/java/com/yello/server/global/common/annotation/AccessTokenUserResolver.java b/src/main/java/com/yello/server/global/common/annotation/AccessTokenUserResolver.java index 37168647..720c0716 100644 --- a/src/main/java/com/yello/server/global/common/annotation/AccessTokenUserResolver.java +++ b/src/main/java/com/yello/server/global/common/annotation/AccessTokenUserResolver.java @@ -2,7 +2,9 @@ import com.yello.server.domain.user.entity.User; import org.springframework.core.MethodParameter; +import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.stereotype.Component; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; @@ -23,8 +25,12 @@ public boolean supportsParameter(MethodParameter parameter) { @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { - return SecurityContextHolder.getContext() - .getAuthentication() - .getDetails(); + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication.getDetails() instanceof WebAuthenticationDetails) { + return null; + } + + return authentication.getDetails(); } } diff --git a/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java b/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java index ff643451..b42507fd 100644 --- a/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java +++ b/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java @@ -41,6 +41,7 @@ import com.yello.server.domain.user.exception.UserConflictException; import com.yello.server.domain.user.exception.UserException; import com.yello.server.domain.user.exception.UserNotFoundException; +import com.yello.server.domain.user.exception.UserPostNotFoundException; import com.yello.server.domain.vote.exception.VoteForbiddenException; import com.yello.server.domain.vote.exception.VoteNotFoundException; import com.yello.server.global.common.dto.BaseResponse; @@ -198,7 +199,8 @@ public ResponseEntity ForbiddenException(CustomException exception AdminConfigurationNotFoundException.class, EventNotFoundException.class, EventBadRequestException.class, - StatisticsNotFoundException.class + StatisticsNotFoundException.class, + UserPostNotFoundException.class }) public ResponseEntity NotFoundException(CustomException exception) { return ResponseEntity.status(NOT_FOUND) diff --git a/src/main/resources/static/docs/index.html b/src/main/resources/static/docs/index.html index f89c7eb4..38b6d928 100644 --- a/src/main/resources/static/docs/index.html +++ b/src/main/resources/static/docs/index.html @@ -454,7 +454,6 @@

YELL:O API 문서

  • Vote API
  • Friend API
  • Purchase API
  • -
  • Pay API
  • Notice API
  • Event API
  • @@ -619,23 +618,6 @@

    Purchase API
    -

    Pay API

    -
    - -
    -
    -

    Notice API

      @@ -659,7 +641,7 @@

      Event API

      🆕 이벤트 보상, 2024-02-07

    • -

      🆕 광고보고 보상 얻기, 2024-02-11

      +

      🆕 광고보고 보상 얻기, 2024-02-19

    • 🆕 광고보고 보상 얻기 가능 여부 조회, 2024-02-17

      diff --git a/src/main/resources/static/docs/reward-admob.html b/src/main/resources/static/docs/reward-admob.html index 42d12596..61ecd115 100644 --- a/src/main/resources/static/docs/reward-admob.html +++ b/src/main/resources/static/docs/reward-admob.html @@ -450,7 +450,6 @@

      요청

      POST /api/v1/admob/reward HTTP/1.1
       Content-Type: application/json;charset=UTF-8
       Authorization: Bearer your-access-token
      -IdempotencyKey: 87552f7c-9b62-4b12-b567-1bd062b09288
       Content-Length: 134
       
       {
      @@ -474,7 +473,7 @@ 

      request body

      ADMOB_POINT : 광고 보고 10 포인트

    • -

      ADMOB_MULTIPLE_POINT : 광고 보고 포인트 2배 이벤트

      +

      ADMOB_MULTIPLE_POINT : 투표 후, 광고 보고 포인트 2배 이벤트

    @@ -529,16 +528,6 @@

    NOTE

    • -

      Header에 무작위한 UUID4 값을 넣어주세요

      -
      -
        -
      • -

        예시) IdempotencyKey: 0397b5f3-ecdc-47d6-b5d7-2b1afcf00e87

        -
      • -
      -
      -
    • -
    • 주의사항

        @@ -566,6 +555,9 @@

        CHANGELOG

        • +

          2024.02.19 API ENUM, 명세서 수정

          +
        • +
        • 2024.02.11 릴리즈

        diff --git a/src/test/java/com/yello/server/domain/pay/medium/PayControllerTest.java b/src/test/java/com/yello/server/domain/pay/medium/PayControllerTest.java deleted file mode 100644 index 045da940..00000000 --- a/src/test/java/com/yello/server/domain/pay/medium/PayControllerTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.yello.server.domain.pay.medium; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyHeaders; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.yello.server.domain.authorization.filter.JwtExceptionFilter; -import com.yello.server.domain.authorization.filter.JwtFilter; -import com.yello.server.domain.pay.controller.PayController; -import com.yello.server.domain.pay.dto.request.PayCountRequest; -import com.yello.server.domain.pay.service.PayService; -import com.yello.server.global.exception.ControllerExceptionAdvice; -import com.yello.server.util.WithAccessTokenUser; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.FilterType; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; -import org.springframework.restdocs.operation.preprocess.OperationPreprocessor; -import org.springframework.restdocs.operation.preprocess.Preprocessors; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; - -@AutoConfigureRestDocs -@WebMvcTest( - controllers = PayController.class, - excludeFilters = { - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) - }) -@WithAccessTokenUser -@DisplayNameGeneration(ReplaceUnderscores.class) -@DisplayName("Pay 컨트롤러에서") -class PayControllerTest { - - final OperationPreprocessor[] excludeRequestHeaders = new OperationPreprocessor[]{ - prettyPrint(), - modifyHeaders().remove("X-CSRF-TOKEN"), - modifyHeaders().remove(HttpHeaders.HOST) - }; - - final OperationPreprocessor[] excludeResponseHeaders = new OperationPreprocessor[]{ - prettyPrint(), - modifyHeaders().remove("X-Content-Type-Options"), - modifyHeaders().remove("X-XSS-Protection"), - modifyHeaders().remove("X-Frame-Options"), - modifyHeaders().remove(HttpHeaders.CACHE_CONTROL), - modifyHeaders().remove(HttpHeaders.PRAGMA), - modifyHeaders().remove(HttpHeaders.EXPIRES), - modifyHeaders().remove(HttpHeaders.CONTENT_LENGTH), - }; - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private PayService payService; - - @Test - void 결제_전환율_체크에_성공합니다() throws Exception { - // given - final PayCountRequest request = PayCountRequest.builder() - .index(1) - .build(); - - // when - // then - mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/pay") - .with(csrf().asHeader()) - .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) - .andDo(print()) - .andDo(document("api/v1/pay/postPayCount", - Preprocessors.preprocessRequest(excludeRequestHeaders), - Preprocessors.preprocessResponse(excludeResponseHeaders) - )) - .andExpect(MockMvcResultMatchers.status().isOk()); - - verify(payService, times(1)) - .postPayCount(anyLong(), anyInt()); - } - -}