Skip to content

Commit bea3640

Browse files
authored
Merge pull request #5 from eunhye-ahn/feature/poll-core-0521
[BE] 투표 : 투표 생성/조회/참여 API 구현
2 parents bd1e053 + ea0b292 commit bea3640

File tree

5 files changed

+178
-30
lines changed

5 files changed

+178
-30
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.example.polls.controller;
2+
3+
import com.example.polls.payload.Request.PollRequest;
4+
import com.example.polls.payload.Request.VoteRequest;
5+
import com.example.polls.payload.Response.ApiResponse;
6+
import com.example.polls.payload.Response.PagedResponse;
7+
import com.example.polls.payload.Response.PollResponse;
8+
import com.example.polls.security.CurrentUser;
9+
import com.example.polls.security.UserPrincipal;
10+
import com.example.polls.service.GroupService;
11+
import com.example.polls.service.PollService;
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.http.ResponseEntity;
14+
import org.springframework.web.bind.annotation.*;
15+
16+
import javax.validation.Valid;
17+
18+
@RestController
19+
@RequestMapping("/api/groups/{groupId}/polls")
20+
public class GroupPollController {
21+
@Autowired
22+
private PollService pollService;
23+
@Autowired
24+
private GroupService groupService;
25+
26+
@PostMapping
27+
public ResponseEntity<?> createPollInGroup (@PathVariable Long groupId,
28+
@CurrentUser UserPrincipal currentUser,
29+
@Valid @RequestBody PollRequest request) {
30+
groupService.validateGroupMember(groupId, currentUser.getId());
31+
pollService.createPollInGroup(groupId, request, currentUser);
32+
return ResponseEntity.ok(new ApiResponse(true, "Poll Created Successfully"));
33+
}
34+
35+
@GetMapping
36+
public ResponseEntity<PagedResponse<PollResponse>> getAllPollInGroup(@PathVariable Long groupId,
37+
@CurrentUser UserPrincipal userPrincipal,
38+
@RequestParam(value = "page", defaultValue="0") int page,
39+
@RequestParam(value = "size", defaultValue="10") int size){
40+
PagedResponse<PollResponse> response = pollService.getAllPollsInGroup(groupId, userPrincipal, page, size);
41+
return ResponseEntity.ok(response);
42+
}
43+
44+
45+
@GetMapping("/{pollId}")
46+
public ResponseEntity<PollResponse> getPollByIdInGroup(@PathVariable Long groupId,
47+
@PathVariable Long pollId,
48+
@CurrentUser UserPrincipal userPrincipal){
49+
PollResponse response = pollService.getPollByIdInGroup(pollId, groupId, userPrincipal);
50+
return ResponseEntity.ok(response);
51+
}
52+
53+
@PostMapping("/{pollId}/votes")
54+
public PollResponse castVote(@CurrentUser UserPrincipal userPrincipal,
55+
@PathVariable Long pollId,
56+
@Valid @RequestBody VoteRequest voteRequest){
57+
return pollService.castVoteAndGetUpdatedPoll(pollId, voteRequest, userPrincipal);
58+
}
59+
60+
}

polling-app-server/src/main/java/com/example/polls/model/Poll.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ public class Poll extends UserDateAudit {
4141
@JoinColumn(name = "group_id", nullable = false)
4242
private Group group;
4343

44+
public Group getGroup() {
45+
return group;
46+
}
4447

48+
public void setGroup(Group group) {
49+
this.group = group;
50+
}
4551

4652
public Long getId() {
4753
return id;

polling-app-server/src/main/java/com/example/polls/repository/PollRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ public interface PollRepository extends JpaRepository<Poll, Long> {
2222
List<Poll> findByIdIn(List<Long> pollIds);
2323

2424
List<Poll> findByIdIn(List<Long> pollIds, Sort sort);
25+
26+
Page<Poll> findByGroupId(Long groupId, Pageable pageable);
2527
}

polling-app-server/src/main/java/com/example/polls/service/GroupService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,10 @@ public GroupDetailResponse getGroupDetail(Long groupId, Long userId) {
124124
return new GroupDetailResponse(group.getId(),group.getName(),group.getImageUrl(),members);
125125

126126
}
127+
128+
public void validateGroupMember(Long groupId, Long userId){
129+
if(!groupMemberRepository.existsByUserIdAndGroupId(userId, groupId)){
130+
throw new BadRequestException("해당 그룹에 소속되지 않았습니다.");
131+
}
132+
}
127133
}

polling-app-server/src/main/java/com/example/polls/service/PollService.java

Lines changed: 104 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
import com.example.polls.exception.BadRequestException;
44
import com.example.polls.exception.ResourceNotFoundException;
55
import com.example.polls.model.*;
6-
import com.example.polls.payload.Response.PagedResponse;
76
import com.example.polls.payload.Request.PollRequest;
8-
import com.example.polls.payload.Response.PollResponse;
97
import com.example.polls.payload.Request.VoteRequest;
10-
import com.example.polls.repository.PollRepository;
11-
import com.example.polls.repository.UserRepository;
12-
import com.example.polls.repository.VoteRepository;
8+
import com.example.polls.payload.Response.PagedResponse;
9+
import com.example.polls.payload.Response.PollResponse;
10+
import com.example.polls.repository.*;
1311
import com.example.polls.security.UserPrincipal;
1412
import com.example.polls.util.AppConstants;
1513
import com.example.polls.util.ModelMapper;
@@ -31,6 +29,7 @@
3129
import java.util.function.Function;
3230
import java.util.stream.Collectors;
3331

32+
3433
@Service
3534
public class PollService {
3635

@@ -44,36 +43,66 @@ public class PollService {
4443
private UserRepository userRepository;
4544

4645
private static final Logger logger = LoggerFactory.getLogger(PollService.class);
46+
@Autowired
47+
private GroupRepository groupRepository;
48+
@Autowired
49+
private GroupService groupService;
50+
@Autowired
51+
private GroupMemberRepository groupMemberRepository;
4752

48-
public PagedResponse<PollResponse> getAllPolls(UserPrincipal currentUser, int page, int size) {
49-
validatePageNumberAndSize(page, size);
50-
51-
// Retrieve Polls
52-
Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "createdAt");
53-
Page<Poll> polls = pollRepository.findAll(pageable);
5453

54+
private PagedResponse<PollResponse> mapPollPagetoPageResponse(UserPrincipal currentUser, Page<Poll> polls) {
5555
if(polls.getNumberOfElements() == 0) {
5656
return new PagedResponse<>(Collections.emptyList(), polls.getNumber(),
5757
polls.getSize(), polls.getTotalElements(), polls.getTotalPages(), polls.isLast());
5858
}
5959

60-
// Map Polls to PollResponses containing vote counts and poll creator details
6160
List<Long> pollIds = polls.map(Poll::getId).getContent();
6261
Map<Long, Long> choiceVoteCountMap = getChoiceVoteCountMap(pollIds);
6362
Map<Long, Long> pollUserVoteMap = getPollUserVoteMap(currentUser, pollIds);
6463
Map<Long, User> creatorMap = getPollCreatorMap(polls.getContent());
6564

66-
List<PollResponse> pollResponses = polls.map(poll -> {
67-
return ModelMapper.mapPollToPollResponse(poll,
68-
choiceVoteCountMap,
69-
creatorMap.get(poll.getCreatedBy()),
70-
pollUserVoteMap == null ? null : pollUserVoteMap.getOrDefault(poll.getId(), null));
71-
}).getContent();
65+
List<PollResponse> pollResponses = polls.map(poll -> ModelMapper.mapPollToPollResponse(
66+
poll,
67+
choiceVoteCountMap,
68+
creatorMap.get(poll.getCreatedBy()),
69+
pollUserVoteMap == null ? null : pollUserVoteMap.getOrDefault(poll.getId(), null)
70+
)).getContent();
7271

7372
return new PagedResponse<>(pollResponses, polls.getNumber(),
7473
polls.getSize(), polls.getTotalElements(), polls.getTotalPages(), polls.isLast());
7574
}
7675

76+
77+
public PagedResponse<PollResponse> getAllPolls(UserPrincipal currentUser, int page, int size) {
78+
validatePageNumberAndSize(page, size);
79+
80+
// Retrieve Polls
81+
Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "createdAt");
82+
Page<Poll> polls = pollRepository.findAll(pageable);
83+
84+
return mapPollPagetoPageResponse(currentUser, polls);
85+
}
86+
87+
public PagedResponse<PollResponse> getAllPollsInGroup(Long groupId, UserPrincipal userPrincipal, int page, int size) {
88+
//그룹 유효성검사
89+
Group group = groupRepository.findById(groupId)
90+
.orElseThrow(() -> new ResourceNotFoundException("Group", "id", groupId));
91+
92+
//그룹 멤버 인증
93+
if(!groupMemberRepository.existsByUserIdAndGroupId(userPrincipal.getId(), groupId)) {
94+
throw new BadRequestException("그룹에 가입된 사용자만 투표를 조회할 수 있습니다.");
95+
}
96+
97+
//page 표시 정보 설정하기
98+
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
99+
//결과 데이터 가져오기
100+
Page<Poll> polls = pollRepository.findByGroupId(groupId, pageable);
101+
102+
return mapPollPagetoPageResponse(userPrincipal, polls);
103+
}
104+
105+
77106
public PagedResponse<PollResponse> getPollsCreatedBy(String username, UserPrincipal currentUser, int page, int size) {
78107
validatePageNumberAndSize(page, size);
79108

@@ -143,29 +172,49 @@ public PagedResponse<PollResponse> getPollsVotedBy(String username, UserPrincipa
143172
}
144173

145174

146-
public Poll createPoll(PollRequest pollRequest) {
175+
private Poll createPollInternal(PollRequest request, Long createdBy, Group group) {
147176
Poll poll = new Poll();
148-
poll.setQuestion(pollRequest.getQuestion());
177+
poll.setQuestion(request.getQuestion());
178+
179+
if (createdBy != null) {
180+
poll.setCreatedBy(createdBy);
181+
}
182+
183+
if (group != null) {
184+
poll.setGroup(group);
185+
}
149186

150-
pollRequest.getChoices().forEach(choiceRequest -> {
187+
request.getChoices().forEach(choiceRequest -> {
151188
poll.addChoice(new Choice(choiceRequest.getText()));
152189
});
153190

154191
Instant now = Instant.now();
155-
Instant expirationDateTime = now.plus(Duration.ofDays(pollRequest.getPollLength().getDays()))
156-
.plus(Duration.ofHours(pollRequest.getPollLength().getHours()));
157-
192+
Instant expirationDateTime = now.plus(Duration.ofDays(request.getPollLength().getDays()))
193+
.plus(Duration.ofHours(request.getPollLength().getHours()));
158194
poll.setExpirationDateTime(expirationDateTime);
159195

160196
return pollRepository.save(poll);
161197
}
162198

163-
public PollResponse getPollById(Long pollId, UserPrincipal currentUser) {
164-
Poll poll = pollRepository.findById(pollId).orElseThrow(
165-
() -> new ResourceNotFoundException("Poll", "id", pollId));
199+
public Poll createPoll(PollRequest pollRequest) {
200+
return createPollInternal(pollRequest, null, null);
201+
}
166202

167-
// Retrieve Vote Counts of every choice belonging to the current poll
168-
List<ChoiceVoteCount> votes = voteRepository.countByPollIdGroupByChoiceId(pollId);
203+
//그룹 투표 생성
204+
public Poll createPollInGroup(Long groupId, PollRequest request, UserPrincipal userPrincipal) {
205+
//그룹 엔티티 조회
206+
Group group = groupRepository.findById(groupId)
207+
.orElseThrow(() -> new ResourceNotFoundException("Group", "id", groupId));
208+
boolean isMember = groupMemberRepository.existsByUserIdAndGroupId(userPrincipal.getId(), groupId);
209+
if(!isMember) {
210+
throw new BadRequestException("해당 그룹에 가입된 자만 투표할 수 있습니다.");
211+
}
212+
//저장
213+
return createPollInternal(request, userPrincipal.getId(), group);
214+
}
215+
216+
public PollResponse buildPollResponse(Poll poll, UserPrincipal currentUser) {
217+
List<ChoiceVoteCount> votes = voteRepository.countByPollIdGroupByChoiceId(poll.getId());
169218

170219
Map<Long, Long> choiceVotesMap = votes.stream()
171220
.collect(Collectors.toMap(ChoiceVoteCount::getChoiceId, ChoiceVoteCount::getVoteCount));
@@ -177,13 +226,38 @@ public PollResponse getPollById(Long pollId, UserPrincipal currentUser) {
177226
// Retrieve vote done by logged in user
178227
Vote userVote = null;
179228
if(currentUser != null) {
180-
userVote = voteRepository.findByUserIdAndPollId(currentUser.getId(), pollId);
229+
userVote = voteRepository.findByUserIdAndPollId(currentUser.getId(), poll.getId());
181230
}
182231

183232
return ModelMapper.mapPollToPollResponse(poll, choiceVotesMap,
184233
creator, userVote != null ? userVote.getChoice().getId(): null);
185234
}
186235

236+
public PollResponse getPollById(Long pollId, UserPrincipal currentUser) {
237+
Poll poll = pollRepository.findById(pollId).orElseThrow(
238+
() -> new ResourceNotFoundException("Poll", "id", pollId));
239+
240+
return buildPollResponse(poll, currentUser);
241+
}
242+
243+
public PollResponse getPollByIdInGroup(Long pollId, Long groupId, UserPrincipal currentUser) {
244+
Group group = groupRepository.findById(groupId)
245+
.orElseThrow(() -> new ResourceNotFoundException("Group", "id", groupId));
246+
boolean isMember = groupMemberRepository.existsByUserIdAndGroupId(currentUser.getId(), groupId);
247+
if(!isMember) {
248+
throw new BadRequestException("해당 그룹에 가입된 사용자만 투표를 조회할 수 있습니다.");
249+
}
250+
251+
Poll poll = pollRepository.findById(pollId).orElseThrow(
252+
() -> new ResourceNotFoundException("Poll", "id", pollId)
253+
);
254+
if(poll.getGroup() != null && !poll.getGroup().getId().equals(groupId)) {
255+
throw new BadRequestException("해당 투표는 요청한 그룹에 속하지 않습니다.");
256+
}
257+
258+
return buildPollResponse(poll, currentUser);
259+
}
260+
187261
public PollResponse castVoteAndGetUpdatedPoll(Long pollId, VoteRequest voteRequest, UserPrincipal currentUser) {
188262
Poll poll = pollRepository.findById(pollId)
189263
.orElseThrow(() -> new ResourceNotFoundException("Poll", "id", pollId));

0 commit comments

Comments
 (0)