Skip to content

Commit c847375

Browse files
authored
feat : 추천/추천 취소 기능 -> 추천/비추천 기능으로 변경 + 테스트 코드 작성 (#69)
* refactor : 도메인 model 패키지 구조 변경 * feat : 커뮤니티 추천, 비추천 기능 구현 완료 - 추천 요청 또는 상태 조회 시 VoteResponse 반환 - VoteResponse는 추천 상태, 해당 토론글 또는 댓글의 추천, 비추천 개수를 포함하고 있음 - 알림 관련 버그 - VoteType=UP인 상태로 추천 요청을 날리면 이전 상태와 상관 없이 그 때마다 알림이 발생함 * feat : 알림 도배 버그 수정 - afterVote() 메서드 호출 시 이전 추천 상태를 확인하도록 함 * feat : 알림 상태 저장 로직 버그 수정 - VoteType NONE 요청을 계속 날리면 에러가 발생하는 버그를 수정함 - `could not execute statement [Data truncated for column 'vote_type' at row 1] [insert into discussion_vote (created_at,discussion_id,vote_type,voter_id) values (?,?,?,?)]` - 로직을 수정해서 NONE 요청이라면 가장 먼저 처리하도록 함 * feat : 추천 관련 도메인 서비스 - 단위 테스트 작성 완료 - 애플리케이션 서비스는 추후 통합 테스트로 커버할 예정 * docs : 추천 관련 swagger 어노테이션 추가 * feat : request DTO null 제약 조건 추가 * feat : 추천, 비추천 카운트 쿼리에서 enum과 관련된 타입 안정성 문제 해결 - VoteType 값을 파라미터로 받아서 적용함
1 parent 615517f commit c847375

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+642
-116
lines changed

src/main/java/org/ezcode/codetest/application/community/dto/request/DiscussionCreateRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
44

5-
import org.ezcode.codetest.domain.community.model.Discussion;
5+
import org.ezcode.codetest.domain.community.model.entity.Discussion;
66
import org.ezcode.codetest.domain.language.model.entity.Language;
77
import org.ezcode.codetest.domain.problem.model.entity.Problem;
88
import org.ezcode.codetest.domain.user.model.entity.User;

src/main/java/org/ezcode/codetest/application/community/dto/request/ReplyCreateRequest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
44

5-
import org.ezcode.codetest.domain.community.model.Discussion;
6-
import org.ezcode.codetest.domain.community.model.Reply;
5+
import org.ezcode.codetest.domain.community.model.entity.Discussion;
6+
import org.ezcode.codetest.domain.community.model.entity.Reply;
77
import org.ezcode.codetest.domain.user.model.entity.User;
88

99
import io.swagger.v3.oas.annotations.media.Schema;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.ezcode.codetest.application.community.dto.request;
2+
3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
4+
5+
import org.ezcode.codetest.domain.community.model.enums.VoteType;
6+
7+
import io.swagger.v3.oas.annotations.media.Schema;
8+
import jakarta.validation.constraints.NotNull;
9+
10+
@Schema(name = "VoteRequest", description = "추천 요청 DTO")
11+
public record VoteRequest(
12+
13+
@Schema(
14+
description = "투표 유형 (UP / DOWN / NONE)",
15+
example = "UP",
16+
requiredMode = REQUIRED
17+
)
18+
@NotNull
19+
VoteType voteType
20+
21+
) {
22+
}

src/main/java/org/ezcode/codetest/application/community/dto/response/DiscussionResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
44

55
import org.ezcode.codetest.application.usermanagement.user.dto.response.SimpleUserInfoResponse;
6-
import org.ezcode.codetest.domain.community.model.Discussion;
6+
import org.ezcode.codetest.domain.community.model.entity.Discussion;
77

88
import io.swagger.v3.oas.annotations.media.Schema;
99

src/main/java/org/ezcode/codetest/application/community/dto/response/ReplyResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
44

55
import org.ezcode.codetest.application.usermanagement.user.dto.response.SimpleUserInfoResponse;
6-
import org.ezcode.codetest.domain.community.model.Reply;
6+
import org.ezcode.codetest.domain.community.model.entity.Reply;
77

88
import io.swagger.v3.oas.annotations.media.Schema;
99

src/main/java/org/ezcode/codetest/application/community/dto/response/VoteResponse.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,43 @@
22

33
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
44

5+
import org.ezcode.codetest.domain.community.model.VoteResult;
6+
import org.ezcode.codetest.domain.community.model.enums.VoteType;
7+
58
import io.swagger.v3.oas.annotations.media.Schema;
69

710
@Schema(name = "VoteResponse", description = "추천 상태 응답 DTO")
811
public record VoteResponse(
12+
13+
@Schema(
14+
description = "현재 투표 유형",
15+
example = "UP / DOWN / NONE",
16+
requiredMode = REQUIRED
17+
)
18+
VoteType voteType,
19+
920
@Schema(
10-
description = "추천 상태 (추천되어 있으면 true, 취소되면 false)",
11-
example = "true",
21+
description = "총 UPVOTE 수",
22+
example = "10",
1223
requiredMode = REQUIRED
1324
)
14-
boolean voteStatus
25+
Long upvoteCount,
26+
27+
@Schema(
28+
description = "총 DOWNVOTE 수",
29+
example = "2",
30+
requiredMode = REQUIRED
31+
)
32+
Long downvoteCount
33+
1534
) {
1635

17-
public static VoteResponse of(boolean voteStatus) {
18-
return new VoteResponse(voteStatus);
36+
public static VoteResponse from(VoteResult voteResult) {
37+
38+
return new VoteResponse(
39+
voteResult.voteType(),
40+
voteResult.upvoteCount(),
41+
voteResult.downvoteCount()
42+
);
1943
}
2044
}

src/main/java/org/ezcode/codetest/application/community/service/BaseVoteService.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.ezcode.codetest.application.community.service;
22

33
import org.ezcode.codetest.application.community.dto.response.VoteResponse;
4-
import org.ezcode.codetest.domain.community.model.BaseVote;
4+
import org.ezcode.codetest.domain.community.model.VoteResult;
5+
import org.ezcode.codetest.domain.community.model.entity.BaseVote;
6+
import org.ezcode.codetest.domain.community.model.enums.VoteType;
57
import org.ezcode.codetest.domain.community.service.BaseVoteDomainService;
68
import org.ezcode.codetest.domain.user.model.entity.User;
79
import org.ezcode.codetest.domain.user.service.UserDomainService;
@@ -15,34 +17,27 @@ public abstract class BaseVoteService<T extends BaseVote, D extends BaseVoteDoma
1517
protected final D voteDomainService;
1618
private final UserDomainService userDomainService;
1719

18-
/**
19-
* 추천 애플리케이션 서비스 공통 로직
20-
* - 각자 도메인에 맞는 검증 로직을 수행하고 호출됨
21-
* - 추천 토글 (추천 또는 추천 취소)
22-
* - 추천 했다면 알림 등의 후속 동작 수행
23-
*
24-
* @param voterId 추천한 유저 id
25-
* @param targetId 추천 대상 entity id (자유글, 댓글 등)
26-
* @return 추천이 됐는지, 취소가 됐는지 등의 정보를 담은 VoteResponse 반환
27-
*/
28-
protected VoteResponse toggleVote(Long voterId, Long targetId) {
20+
protected VoteResponse manageVote(Long voterId, Long targetId, VoteType voteType) {
2921

3022
User voter = userDomainService.getUserById(voterId);
3123

32-
boolean isVoted = voteDomainService.toggleVote(voter, targetId);
24+
VoteResult voteResult = voteDomainService.manageVote(voter, targetId, voteType);
3325

34-
if (isVoted) {
26+
// 알림 도배 방지용 검증 로직
27+
// voteType=UP인 요청을 반복해서 날릴 경우 알림이 도배될 수 있는 문제를 방지
28+
if (voteResult.voteType() == VoteType.UP && voteResult.prevVoteType() != VoteType.UP) {
3529
afterVote(voter, targetId);
3630
}
3731

38-
return VoteResponse.of(isVoted);
32+
return VoteResponse.from(voteResult);
3933
}
4034

4135
@Transactional(readOnly = true)
4236
public VoteResponse getVoteStatus(Long userId, Long targetId) {
4337

44-
boolean voteStatus = voteDomainService.getVoteStatus(userId, targetId);
45-
return new VoteResponse(voteStatus);
38+
VoteResult voteResult = voteDomainService.getVoteStatus(userId, targetId);
39+
40+
return VoteResponse.from(voteResult);
4641
}
4742

4843
protected abstract void afterVote(User voter, Long targetId);

src/main/java/org/ezcode/codetest/application/community/service/DiscussionService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import org.ezcode.codetest.application.community.dto.request.DiscussionCreateRequest;
44
import org.ezcode.codetest.application.community.dto.request.DiscussionModifyRequest;
55
import org.ezcode.codetest.application.community.dto.response.DiscussionResponse;
6-
import org.ezcode.codetest.domain.community.model.Discussion;
6+
import org.ezcode.codetest.domain.community.model.entity.Discussion;
77
import org.ezcode.codetest.domain.community.service.DiscussionDomainService;
88
import org.ezcode.codetest.domain.language.model.entity.Language;
99
import org.ezcode.codetest.domain.problem.model.entity.Problem;

src/main/java/org/ezcode/codetest/application/community/service/DiscussionVoteService.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
import java.util.Optional;
44

5+
import org.ezcode.codetest.application.community.dto.request.VoteRequest;
56
import org.ezcode.codetest.application.community.dto.response.VoteResponse;
67
import org.ezcode.codetest.application.notification.event.NotificationCreateEvent;
78
import org.ezcode.codetest.application.notification.port.NotificationEventService;
8-
import org.ezcode.codetest.domain.community.model.Discussion;
9-
import org.ezcode.codetest.domain.community.model.DiscussionVote;
9+
import org.ezcode.codetest.domain.community.model.entity.Discussion;
10+
import org.ezcode.codetest.domain.community.model.entity.DiscussionVote;
1011
import org.ezcode.codetest.domain.community.service.DiscussionDomainService;
1112
import org.ezcode.codetest.domain.community.service.DiscussionVoteDomainService;
1213
import org.ezcode.codetest.domain.user.model.entity.User;
@@ -32,11 +33,11 @@ public DiscussionVoteService(
3233
}
3334

3435
@Transactional
35-
public VoteResponse toggleVoteOnDiscussion(Long problemId, Long discussionId, Long userId) {
36+
public VoteResponse manageVoteOnDiscussion(Long problemId, Long discussionId, VoteRequest request, Long userId) {
3637

3738
Discussion discussion = voteDomainService.getValidatedDiscussion(discussionId, problemId);
3839

39-
return super.toggleVote(userId, discussion.getId());
40+
return super.manageVote(userId, discussion.getId(), request.voteType());
4041
}
4142

4243
@Override

src/main/java/org/ezcode/codetest/application/community/service/ReplyService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import org.ezcode.codetest.application.community.dto.response.ReplyResponse;
88
import org.ezcode.codetest.application.notification.event.NotificationCreateEvent;
99
import org.ezcode.codetest.application.notification.port.NotificationEventService;
10-
import org.ezcode.codetest.domain.community.model.Discussion;
11-
import org.ezcode.codetest.domain.community.model.Reply;
10+
import org.ezcode.codetest.domain.community.model.entity.Discussion;
11+
import org.ezcode.codetest.domain.community.model.entity.Reply;
1212
import org.ezcode.codetest.domain.community.service.DiscussionDomainService;
1313
import org.ezcode.codetest.domain.community.service.ReplyDomainService;
1414
import org.ezcode.codetest.domain.user.model.entity.User;

0 commit comments

Comments
 (0)