Skip to content

Commit 6efd118

Browse files
committed
feat[poll] 투표기ë �¥ 추가
1 parent 695be1d commit 6efd118

25 files changed

+1037
-349
lines changed
Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package com.ai.lawyer.domain.poll.controller;
22

3+
import com.ai.lawyer.domain.poll.dto.PollCreateDto;
34
import com.ai.lawyer.domain.poll.dto.PollDto;
4-
import com.ai.lawyer.domain.poll.dto.PollWithPostDto;
5+
import com.ai.lawyer.domain.poll.dto.PollVoteDto;
56
import com.ai.lawyer.domain.poll.entity.PollVote;
67
import com.ai.lawyer.domain.poll.entity.PollOptions;
78
import com.ai.lawyer.domain.poll.entity.PollStatics;
89
import com.ai.lawyer.domain.poll.service.PollService;
910
import com.ai.lawyer.domain.post.dto.PostDetailDto;
1011
import com.ai.lawyer.domain.post.service.PostService;
12+
import io.swagger.v3.oas.annotations.Operation;
13+
import io.swagger.v3.oas.annotations.tags.Tag;
1114
import lombok.RequiredArgsConstructor;
15+
import org.springframework.security.core.Authentication;
16+
import org.springframework.security.core.context.SecurityContextHolder;
1217
import org.springframework.web.bind.annotation.*;
1318

1419
import java.util.List;
1520

21+
@Tag(name = "Poll API", description = "투표 관련 API")
1622
@RestController
1723
@RequestMapping("/api/polls")
1824
@RequiredArgsConstructor
@@ -21,55 +27,81 @@ public class PollController {
2127
private final PollService pollService;
2228
private final PostService postService;
2329

30+
@Operation(summary = "투표 단일 조회")
2431
@GetMapping("/{pollId}")
2532
public PollDto getPoll(@PathVariable Long pollId) {
2633
return pollService.getPoll(pollId);
2734
}
2835

36+
@Operation(summary = "투표 옵션 목록 조회")
2937
@GetMapping("/{pollId}/options")
3038
public List<PollOptions> getPollOptions(@PathVariable Long pollId) {
3139
return pollService.getPollOptions(pollId);
3240
}
3341

42+
@Operation(summary = "투표하기")
3443
@PostMapping("/{pollId}/vote")
35-
public PollVote vote(@PathVariable Long pollId, @RequestParam Long pollItemsId, @RequestParam Long memberId) {
44+
public PollVoteDto vote(@PathVariable Long pollId, @RequestParam Long pollItemsId) {
45+
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
46+
Long memberId = (Long) authentication.getPrincipal();
3647
return pollService.vote(pollId, pollItemsId, memberId);
3748
}
3849

50+
@Operation(summary = "투표 통계 조회")
3951
@GetMapping("/{pollId}/statics")
4052
public List<PollStatics> getPollStatics(@PathVariable Long pollId) {
4153
return pollService.getPollStatics(pollId);
4254
}
4355

56+
@Operation(summary = "투표 종료")
4457
@PutMapping("/{pollId}/close")
4558
public void closePoll(@PathVariable Long pollId) {
4659
pollService.closePoll(pollId);
4760
}
4861

62+
@Operation(summary = "투표 삭제")
4963
@DeleteMapping("/{pollId}")
5064
public void deletePoll(@PathVariable Long pollId) {
5165
pollService.deletePoll(pollId);
5266
}
5367

68+
@Operation(summary = "진행중인 투표 Top 1 조회")
5469
@GetMapping("/top/ongoing")
5570
public PollDto getTopOngoingPoll() {
5671
return pollService.getTopPollByStatus(PollDto.PollStatus.ONGOING);
5772
}
5873

74+
@Operation(summary = "종료된 투표 Top 1 조회")
5975
@GetMapping("/top/closed")
6076
public PollDto getTopClosedPoll() {
6177
return pollService.getTopPollByStatus(PollDto.PollStatus.CLOSED);
6278
}
6379

80+
@Operation(summary = "진행중인 투표 상세 조회")
6481
@GetMapping("/top/ongoing-detail")
6582
public PostDetailDto getTopOngoingPollDetail() {
6683
PollDto pollDto = pollService.getTopPollByStatus(PollDto.PollStatus.ONGOING);
6784
return postService.getPostDetailById(pollDto.getPostId());
6885
}
6986

87+
@Operation(summary = "종료된 투표 상세 조회")
7088
@GetMapping("/top/closed-detail")
7189
public PostDetailDto getTopClosedPollDetail() {
7290
PollDto pollDto = pollService.getTopPollByStatus(PollDto.PollStatus.CLOSED);
7391
return postService.getPostDetailById(pollDto.getPostId());
7492
}
75-
}
93+
94+
@Operation(summary = "투표 생성")
95+
@PostMapping("")
96+
public PollDto createPoll(@RequestBody PollCreateDto request) {
97+
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
98+
Long memberId = (Long) authentication.getPrincipal();
99+
return pollService.createPoll(request, memberId);
100+
}
101+
102+
@Operation(summary = "투표 수정")
103+
@PutMapping("/{pollId}")
104+
public PollDto updatePoll(@PathVariable Long pollId, @RequestBody com.ai.lawyer.domain.poll.dto.PollUpdateDto pollUpdateDto) {
105+
return pollService.updatePoll(pollId, pollUpdateDto);
106+
}
107+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.ai.lawyer.domain.poll.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
import java.util.List;
9+
10+
@Data
11+
@NoArgsConstructor
12+
@AllArgsConstructor
13+
@Builder
14+
public class PollCreateDto {
15+
@Schema(description = "게시글 ID", example = "123")
16+
private Long postId;
17+
@Schema(description = "투표 제목", example = "당신의 선택은?")
18+
private String voteTitle;
19+
@Schema(description = "투표 항목(2개 필수)", example = "[{\"content\": \"항목1 내용\"}, {\"content\": \"항목2 내용\"}]")
20+
private List<PollOptionCreateDto> pollOptions;
21+
}

backend/src/main/java/com/ai/lawyer/domain/poll/dto/PollDto.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class PollDto {
1616
private LocalDateTime createdAt;
1717
private LocalDateTime closedAt;
1818
private List<PollOptionDto> pollOptions;
19+
private Long totalVoteCount;
1920

2021
public enum PollStatus {
2122
ONGOING, CLOSED
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.ai.lawyer.domain.poll.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
@Data
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
@Builder
13+
public class PollOptionCreateDto {
14+
@Schema(description = "투표 항목 내용", example = "항목1 내용")
15+
private String content;
16+
}

backend/src/main/java/com/ai/lawyer/domain/poll/dto/PollOptionDto.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
@AllArgsConstructor
88
@Builder
99
public class PollOptionDto {
10-
private Long pollOptionId;
10+
private Long pollItemsId; // PK
1111
private String content;
12+
private Long voteCount;
13+
private java.util.List<PollStaticsDto> statics;
14+
private int pollOptionIndex;
1215
}
13-
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.ai.lawyer.domain.poll.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
@Data
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
@Builder
13+
public class PollOptionUpdateDto {
14+
@Schema(description = "투표 항목 내용", example = "항목1 내용")
15+
private String content;
16+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.ai.lawyer.domain.poll.dto;
2+
3+
import lombok.*;
4+
5+
@Data
6+
@NoArgsConstructor
7+
@AllArgsConstructor
8+
@Builder
9+
public class PollStaticsDto {
10+
private String gender;
11+
private String ageGroup;
12+
private Long voteCount;
13+
}
14+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.ai.lawyer.domain.poll.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
import java.util.List;
9+
10+
@Data
11+
@NoArgsConstructor
12+
@AllArgsConstructor
13+
@Builder
14+
public class PollUpdateDto {
15+
@Schema(description = "투표 제목", example = "당신의 선택은?")
16+
private String voteTitle;
17+
@Schema(description = "투표 항목(2개 필수)", example = "[{\"content\": \"항목1 내용\"}, {\"content\": \"항목2 내용\"}]")
18+
private List<PollOptionUpdateDto> pollOptions;
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.ai.lawyer.domain.poll.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
@Data
9+
@NoArgsConstructor
10+
@AllArgsConstructor
11+
@Builder
12+
public class PollVoteDto {
13+
private Long pollVoteId;
14+
private Long pollId;
15+
private Long pollItemsId;
16+
private Long memberId;
17+
private Long voteCount;
18+
}
19+

backend/src/main/java/com/ai/lawyer/domain/poll/entity/Poll.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class Poll {
1919
@Column(name = "poll_id")
2020
private Long pollId;
2121

22-
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
22+
@OneToOne(fetch = FetchType.LAZY)
2323
@JoinColumn(name = "post_id", nullable = true)
2424
private Post post;
2525

@@ -36,6 +36,9 @@ public class Poll {
3636
@Column(name = "closed_at")
3737
private LocalDateTime closedAt;
3838

39+
@OneToMany(mappedBy = "poll", cascade = CascadeType.REMOVE, orphanRemoval = true)
40+
private java.util.List<PollOptions> pollOptions;
41+
3942
// 투표 상태 Enum 타입
4043
public enum PollStatus {
4144
ONGOING, CLOSED

0 commit comments

Comments
 (0)