Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.ai.lawyer.domain.poll.service.PollService;
import com.ai.lawyer.domain.post.dto.PostDetailDto;
import com.ai.lawyer.domain.post.service.PostService;
import com.ai.lawyer.global.response.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
Expand All @@ -32,52 +33,60 @@ public class PollController {

@Operation(summary = "투표 단일 조회")
@GetMapping("/{pollId}")
public PollDto getPoll(@PathVariable Long pollId) {
return pollService.getPoll(pollId);
public ResponseEntity<ApiResponse<PollDto>> getPoll(@PathVariable Long pollId) {
PollDto poll = pollService.getPoll(pollId);
return ResponseEntity.ok(new ApiResponse<>(200, "투표 단일 조회 성공", poll));
}

@Operation(summary = "투표 옵션 목록 조회")
@GetMapping("/{pollId}/options")
public List<PollOptions> getPollOptions(@PathVariable Long pollId) {
return pollService.getPollOptions(pollId);
public ResponseEntity<ApiResponse<List<PollOptions>>> getPollOptions(@PathVariable Long pollId) {
List<PollOptions> options = pollService.getPollOptions(pollId);
return ResponseEntity.ok(new ApiResponse<>(200, "투표 옵션 목록 조회 성공", options));
}

@Operation(summary = "투표하기")
@PostMapping("/{pollId}/vote")
public ResponseEntity<?> vote(@PathVariable Long pollId, @RequestParam Long pollItemsId) {
public ResponseEntity<ApiResponse<PollVoteDto>> vote(@PathVariable Long pollId, @RequestParam Long pollItemsId) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Long memberId = Long.parseLong(authentication.getName());
return ResponseEntity.ok(pollService.vote(pollId, pollItemsId, memberId));
PollVoteDto result = pollService.vote(pollId, pollItemsId, memberId);
return ResponseEntity.ok(new ApiResponse<>(200, "투표가 성공적으로 완료되었습니다.", result));
}

@Operation(summary = "투표 통계 조회")
@GetMapping("/{pollId}/statics")
public List<PollStatics> getPollStatics(@PathVariable Long pollId) {
return pollService.getPollStatics(pollId);
public ResponseEntity<ApiResponse<List<PollStatics>>> getPollStatics(@PathVariable Long pollId) {
List<PollStatics> statics = pollService.getPollStatics(pollId);
return ResponseEntity.ok(new ApiResponse<>(200, "투표 통계 조회 성공", statics));
}

@Operation(summary = "투표 종료")
@PutMapping("/{pollId}/close")
public void closePoll(@PathVariable Long pollId) {
public ResponseEntity<ApiResponse<Void>> closePoll(@PathVariable Long pollId) {
pollService.closePoll(pollId);
return ResponseEntity.ok(new ApiResponse<>(200, "투표가 종료되었습니다.", null));
}

@Operation(summary = "투표 삭제")
@DeleteMapping("/{pollId}")
public void deletePoll(@PathVariable Long pollId) {
public ResponseEntity<ApiResponse<Void>> deletePoll(@PathVariable Long pollId) {
pollService.deletePoll(pollId);
return ResponseEntity.ok(new ApiResponse<>(200, "투표가 삭제되었습니다.", null));
}

@Operation(summary = "진행중인 투표 Top 1 조회")
@GetMapping("/top/ongoing")
public PollDto getTopOngoingPoll() {
return pollService.getTopPollByStatus(PollDto.PollStatus.ONGOING);
public ResponseEntity<ApiResponse<PollDto>> getTopOngoingPoll() {
PollDto poll = pollService.getTopPollByStatus(PollDto.PollStatus.ONGOING);
return ResponseEntity.ok(new ApiResponse<>(200, "진행중인 투표 Top 1 조회 성공", poll));
}

@Operation(summary = "종료된 투표 Top 1 조회")
@GetMapping("/top/closed")
public PollDto getTopClosedPoll() {
return pollService.getTopPollByStatus(PollDto.PollStatus.CLOSED);
public ResponseEntity<ApiResponse<PollDto>> getTopClosedPoll() {
PollDto poll = pollService.getTopPollByStatus(PollDto.PollStatus.CLOSED);
return ResponseEntity.ok(new ApiResponse<>(200, "종료된 투표 Top 1 조회 성공", poll));
}

// @Operation(summary = "진행중인 투표 상세 조회")
Expand All @@ -96,63 +105,68 @@ public PollDto getTopClosedPoll() {

@Operation(summary = "투표 생성")
@PostMapping("")
public ResponseEntity<?> createPoll(@RequestBody PollCreateDto pollCreateDto) {
public ResponseEntity<ApiResponse<PollDto>> createPoll(@RequestBody PollCreateDto pollCreateDto) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Long memberId = Long.parseLong(authentication.getName());
return ResponseEntity.ok(pollService.createPoll(pollCreateDto, memberId));
PollDto created = pollService.createPoll(pollCreateDto, memberId);
return ResponseEntity.ok(new ApiResponse<>(201, "투표가 생성되었습니다.", created));
}

@Operation(summary = "투표 수정")
@PutMapping("/{pollId}")
public PollDto updatePoll(@PathVariable Long pollId, @RequestBody com.ai.lawyer.domain.poll.dto.PollUpdateDto pollUpdateDto) {
return pollService.updatePoll(pollId, pollUpdateDto);
public ResponseEntity<ApiResponse<PollDto>> updatePoll(@PathVariable Long pollId, @RequestBody com.ai.lawyer.domain.poll.dto.PollUpdateDto pollUpdateDto) {
PollDto updated = pollService.updatePoll(pollId, pollUpdateDto);
return ResponseEntity.ok(new ApiResponse<>(200, "투표가 수정되었습니다.", updated));
}

@Operation(summary = "진행중인 투표 전체 목록 조회")
@GetMapping("/ongoing")
public List<PollDto> getOngoingPolls() {
return pollService.getPollsByStatus(PollDto.PollStatus.ONGOING);
public ResponseEntity<ApiResponse<List<PollDto>>> getOngoingPolls() {
List<PollDto> polls = pollService.getPollsByStatus(PollDto.PollStatus.ONGOING);
return ResponseEntity.ok(new ApiResponse<>(200, "진행중인 투표 전체 목록 조회 성공", polls));
}

@Operation(summary = "종료된 투표 전체 목록 조회")
@GetMapping("/closed")
public List<PollDto> getClosedPolls() {
return pollService.getPollsByStatus(PollDto.PollStatus.CLOSED);
public ResponseEntity<ApiResponse<List<PollDto>>> getClosedPolls() {
List<PollDto> polls = pollService.getPollsByStatus(PollDto.PollStatus.CLOSED);
return ResponseEntity.ok(new ApiResponse<>(200, "종료된 투표 전체 목록 조회 성공", polls));
}

@Operation(summary = "종료된 투표 Top N 조회")
@GetMapping("/top/closed-list") //검색조건 : pi/polls/top/closed-list?size=3
public List<PollDto> getTopClosedPolls(@RequestParam(defaultValue = "3") int size) {
return pollService.getTopNPollsByStatus(PollDto.PollStatus.CLOSED, size);
public ResponseEntity<ApiResponse<List<PollDto>>> getTopClosedPolls(@RequestParam(defaultValue = "3") int size) {
List<PollDto> polls = pollService.getTopNPollsByStatus(PollDto.PollStatus.CLOSED, size);
String message = String.format("종료된 투표 Top %d 조회 성공", size);
return ResponseEntity.ok(new ApiResponse<>(200, message, polls));
}

@Operation(summary = "진행중인 투표 Top N 조회")
@GetMapping("/top/ongoing-list") //검색조건 : api/polls/top/ongoing-list?size=3
public List<PollDto> getTopOngoingPolls(@RequestParam(defaultValue = "3") int size) {
return pollService.getTopNPollsByStatus(PollDto.PollStatus.ONGOING, size);
public ResponseEntity<ApiResponse<List<PollDto>>> getTopOngoingPolls(@RequestParam(defaultValue = "3") int size) {
List<PollDto> polls = pollService.getTopNPollsByStatus(PollDto.PollStatus.ONGOING, size);
String message = String.format("진행중인 투표 Top %d 조회 성공", size);
return ResponseEntity.ok(new ApiResponse<>(200, message, polls));
}

@Operation(summary = "index(순번)로 투표하기 - Swagger 편의용")
@PostMapping("/{pollId}/vote-by-index")
public ResponseEntity<?> voteByIndex(@PathVariable Long pollId, @RequestParam int index) {
public ResponseEntity<ApiResponse<PollVoteDto>> voteByIndex(@PathVariable Long pollId, @RequestParam int index) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Long memberId = Long.parseLong(authentication.getName());

List<PollOptions> options = pollService.getPollOptions(pollId);
if (index < 1 || index > options.size()) {
throw new ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST, "index가 옵션 범위를 벗어났습니다.");
}
Long pollItemsId = options.get(index - 1).getPollItemsId();
return ResponseEntity.ok(pollService.vote(pollId, pollItemsId, memberId));
PollVoteDto result = pollService.vote(pollId, pollItemsId, memberId);
return ResponseEntity.ok(new ApiResponse<>(200, "투표가 성공적으로 완료되었습니다.", result));
}

@ExceptionHandler(ResponseStatusException.class)
public ResponseEntity<Object> handleResponseStatusException(ResponseStatusException ex) {
public ResponseEntity<ApiResponse<Void>> handleResponseStatusException(ResponseStatusException ex) {
int code = ex.getStatusCode().value();
String message = ex.getReason();
return ResponseEntity.status(code).body(new java.util.HashMap<String, Object>() {{
put("code", code);
put("message", message);
}});
return ResponseEntity.status(code).body(new ApiResponse<>(code, message, null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ public class Poll {
@Column(name = "poll_id")
private Long pollId;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id", nullable = true)
@OneToOne(mappedBy = "poll", fetch = FetchType.LAZY)
private Post post;

@Column(length = 100, nullable = false, name = "vote_title")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ public class PollOptions {
private Long pollItemsId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "poll_id", nullable = false)
@JoinColumn(name = "poll_id", nullable = false, foreignKey = @ForeignKey(name = "FK_POLLOPTIONS_POLL"))
private Poll poll;

@Column(length = 100, nullable = false, name = "option")
@Column(length = 100, nullable = false, name = "option_text")
private String option;

@Column(name = "count")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ public class PollStatics {
private Long statId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "poll_id", nullable = false)
@JoinColumn(name = "poll_id", nullable = false, foreignKey = @ForeignKey(name = "FK_POLLSTATICS_POLL"))
private Poll poll;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "poll_items_id", nullable = false)
@JoinColumn(name = "poll_items_id", nullable = false, foreignKey = @ForeignKey(name = "FK_POLLSTATICS_POLLOPTIONS"))
private PollOptions pollOptions;

@Column(length = 10, name = "gender")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ public class PollVote {
private Long pollVoteId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "poll_id", nullable = false)
@JoinColumn(name = "poll_id", nullable = false, foreignKey = @ForeignKey(name = "FK_POLLVOTE_POLL"))
private Poll poll;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = false)
@JoinColumn(name = "member_id", nullable = false, foreignKey = @ForeignKey(name = "FK_POLLVOTE_MEMBER"))
private Member member;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "poll_items_id", nullable = false)
@JoinColumn(name = "poll_items_id", nullable = false, foreignKey = @ForeignKey(name = "FK_POLLVOTE_POLLOPTIONS"))
private PollOptions pollOptions;
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ public PollDto createPoll(PollCreateDto request, Long memberId) {
pollOptionsRepository.save(option);
}
return convertToDto(savedPoll);
} catch (ResponseStatusException e) {
throw e;
} catch (Exception e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "투표 생성 중 오류가 발생했습니다.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.ai.lawyer.domain.member.entity.Member;
import com.ai.lawyer.domain.member.repositories.MemberRepository;
import com.ai.lawyer.global.jwt.TokenProvider;
import com.ai.lawyer.global.response.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -147,12 +148,4 @@ public ResponseEntity<ApiResponse<List<PostDto>>> getMyPosts() {
List<PostDto> posts = postService.getMyPosts(memberId);
return ResponseEntity.ok(new ApiResponse<>(200, "본인 게시글 전체 조회 성공", posts));
}

@Data
@AllArgsConstructor
public static class ApiResponse<T> {
private int code;
private String message;
private T result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class Post {
private Long postId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = false)
@JoinColumn(name = "member_id", nullable = false, foreignKey = @ForeignKey(name = "FK_POST_MEMBER"))
private Member member;

@Column(name = "post_name", length = 100, nullable = false)
Expand All @@ -37,7 +37,7 @@ public class Post {
@Column(name = "created_at")
private LocalDateTime createdAt;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) // 포스트 삭제 시 연관된 투표도 삭제
@JoinColumn(name = "poll_id")
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "poll_id", foreignKey = @ForeignKey(name = "FK_POST_POLL"))
private Poll poll;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ai.lawyer.global.response;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class ApiResponse<T> {
private int code;
private String message;
private T result;
}

Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ void t10() throws Exception {
Mockito.when(pollService.getPoll(Mockito.anyLong())).thenReturn(responseDto);
mockMvc.perform(get("/api/polls/1"))
.andExpect(status().isOk())
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.pollId").value(1L))
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.voteTitle").value("테스트 투표"));
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.result.pollId").value(1L))
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.result.voteTitle").value("테스트 투표"));
}

@Test
Expand All @@ -162,7 +162,7 @@ void t11() throws Exception {
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post("/api/polls/1/vote")
.param("pollItemsId", "1")
).andExpect(status().isOk())
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.pollId").value(1L))
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.memberId").value(1L));
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.result.pollId").value(1L))
.andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath("$.result.memberId").value(1L));
}
}