Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

투표 기능 예외 처리 #49

Merged
merged 7 commits into from
Feb 14, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package balancetalk.global.exception;

import lombok.Getter;

@Getter
public class BalanceTalkException extends RuntimeException {

private final ErrorCode errorCode;

public BalanceTalkException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
}
28 changes: 28 additions & 0 deletions src/main/java/balancetalk/global/exception/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package balancetalk.global.exception;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;

import static org.springframework.http.HttpStatus.*;

@Getter
@RequiredArgsConstructor
public enum ErrorCode {
// 400
MISMATCHED_BALANCE_OPTION(BAD_REQUEST, "선택한 선택지는 다른 게시글에 속해 있습니다."),
EXPIRED_POST_DEADLINE(BAD_REQUEST, "투표가 이미 종료된 게시글입니다."),
UNMODIFIABLE_VOTE(BAD_REQUEST, "투표 수정이 불가능한 게시글입니다."),

// 404
NOT_FOUND_POST(NOT_FOUND, "존재하지 않는 게시글입니다."),
NOT_FOUND_BALANCE_OPTION(NOT_FOUND, "존재하지 않는 선택지입니다."),
NOT_FOUND_MEMBER(NOT_FOUND, "존재하지 않는 회원입니다."),
NOT_FOUND_VOTE(NOT_FOUND, "해당 게시글에서 투표한 기록이 존재하지 않습니다."),

// 409
ALREADY_VOTE(CONFLICT, "투표는 한 번만 가능합니다.");

private final HttpStatus httpStatus;
private final String message;
}
18 changes: 18 additions & 0 deletions src/main/java/balancetalk/global/exception/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package balancetalk.global.exception;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ErrorResponse {

private HttpStatus httpStatus;
private String message;

public static ErrorResponse from(ErrorCode errorCode) {
return new ErrorResponse(errorCode.getHttpStatus(), errorCode.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package balancetalk.global.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(BalanceTalkException.class)
public ResponseEntity<ErrorResponse> handleBalanceTalkException(BalanceTalkException e) {
ErrorResponse errorResponse = ErrorResponse.from(e.getErrorCode());
log.error("exception message = {}", e.getMessage());
return ResponseEntity.status(errorResponse.getHttpStatus()).body(errorResponse);
}
}
5 changes: 5 additions & 0 deletions src/main/java/balancetalk/module/member/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,9 @@ public class Member extends BaseTimeEntity {

@OneToMany(mappedBy = "reporter")
private List<Report> reports = new ArrayList<>(); // 신고한 기록

public boolean hasVoted(Post post) {
return votes.stream()
.anyMatch(vote -> vote.getBalanceOption().getPost().equals(post));
}
}
4 changes: 4 additions & 0 deletions src/main/java/balancetalk/module/post/domain/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ public void init() {
public boolean notContainsBalanceOption(BalanceOption option) {
return !options.contains(option);
}

public boolean hasDeadlineExpired() {
return deadline.isBefore(LocalDateTime.now());
}
}
34 changes: 22 additions & 12 deletions src/main/java/balancetalk/module/vote/application/VoteService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package balancetalk.module.vote.application;

import static balancetalk.global.exception.ErrorCode.*;

import balancetalk.global.exception.BalanceTalkException;
import balancetalk.module.member.domain.Member;
import balancetalk.module.member.domain.MemberRepository;
import balancetalk.module.post.domain.BalanceOption;
Expand Down Expand Up @@ -28,22 +31,29 @@ public class VoteService {

public Vote createVote(Long postId, VoteRequest voteRequest) {
Post post = postRepository.findById(postId)
.orElseThrow();
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_POST));
BalanceOption balanceOption = balanceOptionRepository.findById(voteRequest.getSelectedOptionId())
.orElseThrow();
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_BALANCE_OPTION));
Member member = memberRepository.findById(voteRequest.getMemberId())
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_MEMBER));

if (post.notContainsBalanceOption(balanceOption)) {
throw new RuntimeException();
throw new BalanceTalkException(MISMATCHED_BALANCE_OPTION);
}
if (member.hasVoted(post)) {
throw new BalanceTalkException(ALREADY_VOTE);
}
if (post.hasDeadlineExpired()) {
throw new BalanceTalkException(EXPIRED_POST_DEADLINE);
}

Member member = memberRepository.findById(voteRequest.getMemberId())
.orElseThrow();
return voteRepository.save(voteRequest.toEntity(balanceOption, member));
}

@Transactional(readOnly = true)
public List<VotingStatusResponse> readVotingStatus(Long postId) {
Post post = postRepository.findById(postId)
.orElseThrow();
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_POST));

List<BalanceOption> options = post.getOptions();
List<VotingStatusResponse> responses = new ArrayList<>();
Expand All @@ -61,20 +71,20 @@ public List<VotingStatusResponse> readVotingStatus(Long postId) {

public Vote updateVote(Long postId, VoteRequest voteRequest) {
Post post = postRepository.findById(postId)
.orElseThrow();
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_POST));

if (post.isCasual()) {
throw new IllegalArgumentException(); // TODO 예외 처리
throw new BalanceTalkException(UNMODIFIABLE_VOTE);
}

Member member = memberRepository.findById(voteRequest.getMemberId())
.orElseThrow();
BalanceOption newSelectedOption = balanceOptionRepository.findById(voteRequest.getSelectedOptionId())
.orElseThrow();
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_BALANCE_OPTION));
Member member = memberRepository.findById(voteRequest.getMemberId())
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_MEMBER));
Vote findVote = member.getVotes().stream()
.filter(vote -> vote.getBalanceOption().getPost().equals(post))
.findFirst()
.orElseThrow();
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_VOTE));
return findVote.changeBalanceOption(newSelectedOption);
}
}