-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] 투표자 API 구현 #205
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
[FEAT] 투표자 API 구현 #205
Changes from all commits
43cba4b
d33dd4c
dd6ac7c
28be904
c9d3d2d
d9f165b
1d64f4e
8de74f9
a2e3596
e2b01b5
57bcb33
f65c9ed
036010e
2ae97ca
da215be
ac9849c
81f4b43
7cc9b03
00ad267
8094397
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.debatetimer.config; | ||
|
|
||
| import com.debatetimer.exception.decoder.H2ErrorDecoder; | ||
| import com.debatetimer.exception.decoder.MySqlErrorDecoder; | ||
| import com.debatetimer.exception.decoder.RepositoryErrorDecoder; | ||
| import lombok.NoArgsConstructor; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.context.annotation.Profile; | ||
|
|
||
| @NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) | ||
| public class ErrorDecoderConfig { | ||
|
|
||
| @Profile({"dev", "prod"}) | ||
| @Configuration | ||
| public static class MySqlErrorDecoderConfig { | ||
|
|
||
| @Bean | ||
| public RepositoryErrorDecoder mySqlErrorDecoder() { | ||
| return new MySqlErrorDecoder(); | ||
| } | ||
| } | ||
|
|
||
| @Profile({"test", "local"}) | ||
| @Configuration | ||
| public static class H2ErrorDecoderConfig { | ||
|
|
||
| @Bean | ||
| public RepositoryErrorDecoder h2ErrorDecoder() { | ||
| return new H2ErrorDecoder(); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package com.debatetimer.controller.poll; | ||
|
|
||
| import com.debatetimer.dto.poll.request.VoteRequest; | ||
| import com.debatetimer.dto.poll.response.VoteCreateResponse; | ||
| import com.debatetimer.dto.poll.response.VoterPollInfoResponse; | ||
| import com.debatetimer.service.poll.VoteService; | ||
| import jakarta.validation.Valid; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.PathVariable; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.ResponseStatus; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| public class VoteController { | ||
|
|
||
| private final VoteService voteService; | ||
|
|
||
| @GetMapping("/api/polls/{pollId}/votes") | ||
| @ResponseStatus(HttpStatus.OK) | ||
| public VoterPollInfoResponse getVotersPollInfo(@PathVariable long pollId) { | ||
| return voteService.getVoterPollInfo(pollId); | ||
| } | ||
|
|
||
| @PostMapping("/api/polls/{pollId}/votes") | ||
| @ResponseStatus(HttpStatus.CREATED) | ||
| public VoteCreateResponse votePoll( | ||
| @PathVariable long pollId, | ||
| @RequestBody @Valid VoteRequest voteRequest | ||
| ) { | ||
| return voteService.vote(pollId, voteRequest); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,4 +5,8 @@ public enum PollStatus { | |
| PROGRESS, | ||
| DONE, | ||
| ; | ||
|
|
||
| public boolean isProgress() { | ||
| return this == PROGRESS; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| package com.debatetimer.domainrepository.poll; | ||
| package com.debatetimer.domainrepository.table; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ??? 이걸 왜 발견 못 했었지... |
||
|
|
||
| import com.debatetimer.domain.customize.CustomizeTable; | ||
| import com.debatetimer.domain.member.Member; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.debatetimer.dto.poll.request; | ||
|
|
||
| import com.debatetimer.domain.poll.VoteTeam; | ||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotNull; | ||
|
|
||
| public record VoteRequest( | ||
| @NotBlank String name, | ||
| @NotBlank String participateCode, | ||
| @NotNull VoteTeam team | ||
| ) { | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package com.debatetimer.dto.poll.response; | ||
|
|
||
| import com.debatetimer.domain.poll.Vote; | ||
| import com.debatetimer.domain.poll.VoteTeam; | ||
|
|
||
| public record VoteCreateResponse( | ||
| long id, | ||
| String name, | ||
| String participateCode, | ||
| VoteTeam team | ||
| ) { | ||
|
|
||
| public VoteCreateResponse(Vote vote) { | ||
| this(vote.getId(), vote.getName().getValue(), vote.getCode().getValue(), vote.getTeam()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package com.debatetimer.dto.poll.response; | ||
|
|
||
| import com.debatetimer.domain.poll.ParticipateCode; | ||
| import com.debatetimer.domain.poll.Poll; | ||
| import com.debatetimer.domain.poll.PollStatus; | ||
| import com.debatetimer.domain.poll.VoteInfo; | ||
|
|
||
| public record VoterPollInfoResponse( | ||
| long id, | ||
| PollStatus status, | ||
| String prosTeamName, | ||
| String consTeamName, | ||
| String participateCode, | ||
| long totalCount, | ||
| long prosCount, | ||
| long consCount | ||
| ) { | ||
|
|
||
| public VoterPollInfoResponse(Poll poll, VoteInfo voteInfo, ParticipateCode code) { | ||
| this( | ||
| poll.getId(), | ||
| poll.getStatus(), | ||
| poll.getProsTeamName().getValue(), | ||
| poll.getConsTeamName().getValue(), | ||
| code.getValue(), | ||
| voteInfo.getTotalCount(), | ||
| voteInfo.getProsCount(), | ||
| voteInfo.getConsCount() | ||
| ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| import com.debatetimer.domain.customize.CustomizeTable; | ||
| import com.debatetimer.domain.member.Member; | ||
| import com.debatetimer.dto.member.TableType; | ||
| import com.debatetimer.entity.BaseTimeEntity; | ||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.FetchType; | ||
| import jakarta.persistence.GeneratedValue; | ||
|
|
@@ -22,7 +23,7 @@ | |
| @Getter | ||
| @Table(name = "customize_table") | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| public class CustomizeTableEntity { | ||
| public class CustomizeTableEntity extends BaseTimeEntity { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BaseTimeEntity가 PollEntity에서도 쓰이던데 패키지 이동해주세요.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✅ 반영 완료 |
||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package com.debatetimer.exception.decoder; | ||
|
|
||
| import org.hibernate.exception.ConstraintViolationException; | ||
| import org.springframework.dao.DataIntegrityViolationException; | ||
|
|
||
| public class H2ErrorDecoder implements RepositoryErrorDecoder { | ||
|
|
||
| protected static final String UNIQUE_CONSTRAINT_VIOLATION_SQL_STATE = "23505"; | ||
|
|
||
| @Override | ||
| public boolean isUniqueConstraintViolation(DataIntegrityViolationException e) { | ||
| Throwable cause = e.getCause(); | ||
| while (cause != null) { | ||
| if (cause instanceof ConstraintViolationException cve) { | ||
| String sqlState = cve.getSQLException().getSQLState(); | ||
| return UNIQUE_CONSTRAINT_VIOLATION_SQL_STATE.equals(sqlState); | ||
| } | ||
| cause = cause.getCause(); | ||
| } | ||
| return false; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.debatetimer.exception.decoder; | ||
|
|
||
| import java.sql.SQLException; | ||
| import org.hibernate.exception.ConstraintViolationException; | ||
| import org.springframework.dao.DataIntegrityViolationException; | ||
|
|
||
| public class MySqlErrorDecoder implements RepositoryErrorDecoder { | ||
|
|
||
| protected static final String MYSQL_UNIQUE_VIOLATION = "23000"; | ||
| protected static final int MYSQL_DUP_ERROR_CODE = 1062; | ||
|
|
||
| @Override | ||
| public boolean isUniqueConstraintViolation(DataIntegrityViolationException e) { | ||
| Throwable cause = e.getCause(); | ||
| while (cause != null) { | ||
| if (cause instanceof ConstraintViolationException cve) { | ||
| SQLException sqlEx = cve.getSQLException(); | ||
| String sqlState = sqlEx.getSQLState(); | ||
| int errorCode = sqlEx.getErrorCode(); | ||
| return MYSQL_UNIQUE_VIOLATION.equals(sqlState) | ||
| && MYSQL_DUP_ERROR_CODE == errorCode; | ||
| } | ||
| cause = cause.getCause(); | ||
| } | ||
| return false; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍