Skip to content

Commit d73cf59

Browse files
committed
MNG-20 feat: MissionComment CRUD 추가
1 parent 6fc0d55 commit d73cf59

23 files changed

+543
-8
lines changed

src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc
5151
.filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링
5252
.count())
5353
.contents(missionArchive.getContents())
54+
.comments(missionArchive.getCommentNum())
5455
.build();
5556
}
5657

src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
import com.moing.backend.domain.member.domain.entity.Member;
55
import com.moing.backend.domain.mission.domain.entity.Mission;
6-
import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus;
76
import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq;
87
import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart;
98
import com.moing.backend.global.entity.BaseTimeEntity;
@@ -50,6 +49,8 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장
5049
@OneToMany(mappedBy = "missionArchive", cascade = CascadeType.REMOVE)
5150
private List<MissionHeart> heartList = new ArrayList<>();
5251

52+
//반정규화
53+
private Long commentNum;
5354

5455
public void updateArchive(MissionArchiveReq missionArchiveReq) {
5556
this.archive = missionArchiveReq.getArchive();
@@ -60,6 +61,13 @@ public void updateCount(Long count) {
6061
this.count = count;
6162
}
6263

64+
public void incrComNum() {
65+
this.commentNum++;
66+
}
67+
68+
public void decrComNum() {
69+
this.commentNum--;
70+
}
6371

6472

6573
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.moing.backend.domain.missionComment.application.mapper;
2+
3+
import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest;
4+
import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive;
5+
import com.moing.backend.domain.missionComment.domain.entity.MissionComment;
6+
import com.moing.backend.domain.teamMember.domain.entity.TeamMember;
7+
import lombok.RequiredArgsConstructor;
8+
import org.springframework.stereotype.Component;
9+
10+
@Component
11+
@RequiredArgsConstructor
12+
public class MissionCommentMapper {
13+
public static MissionComment toMissionComment(TeamMember teamMember, MissionArchive missionArchive, CreateCommentRequest createCommentRequest, boolean isLeader) {
14+
MissionComment missionComment=new MissionComment();
15+
missionComment.init(createCommentRequest.getContent(),isLeader);
16+
missionComment.updateMissionArchive(missionArchive);
17+
missionComment.updateTeamMember(teamMember);
18+
return missionComment;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.moing.backend.domain.missionComment.application.service;
2+
3+
import com.moing.backend.domain.boardComment.application.service.SendCommentAlarmUseCase;
4+
import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest;
5+
import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse;
6+
import com.moing.backend.domain.missionComment.application.mapper.MissionCommentMapper;
7+
import com.moing.backend.domain.missionComment.domain.entity.MissionComment;
8+
import com.moing.backend.domain.missionComment.domain.service.MissionCommentSaveService;
9+
import com.moing.backend.domain.team.application.service.CheckLeaderUseCase;
10+
import com.moing.backend.global.response.BaseMissionServiceResponse;
11+
import com.moing.backend.global.utils.BaseMissionService;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springframework.stereotype.Service;
14+
15+
import javax.transaction.Transactional;
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
@Transactional
20+
public class CreateMissionCommentUseCase {
21+
22+
private final MissionCommentSaveService missionCommentSaveService;
23+
private final BaseMissionService baseMissionService;
24+
private final CheckLeaderUseCase checkLeaderUseCase;
25+
private final SendCommentAlarmUseCase sendCommentAlarmUseCase;
26+
/**
27+
* 게시글 댓글 생성
28+
*/
29+
public CreateCommentResponse createBoardComment(String socialId, Long teamId, Long missionArchiveId, CreateCommentRequest createCommentRequest) {
30+
// 1. 미션 게시글 댓글 생성
31+
BaseMissionServiceResponse data = baseMissionService.getCommonData(socialId, teamId, missionArchiveId);
32+
boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam());
33+
MissionComment missionComment = missionCommentSaveService.saveComment(MissionCommentMapper.toMissionComment(data.getTeamMember(), data.getMissionArchive(), createCommentRequest, isLeader));
34+
// 2. 미션 게시글 댓글 개수 증가
35+
data.getMissionArchive().incrComNum();
36+
// // 3. 미션 게시글 댓글 알림
37+
// sendCommentAlarmUseCase.sendNewUploadAlarm(data, missionComment);
38+
return new CreateCommentResponse(missionComment.getMissionCommentId());
39+
}
40+
}
41+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.moing.backend.domain.missionComment.application.service;
2+
3+
import com.moing.backend.domain.boardComment.exception.NotAuthByBoardCommentException;
4+
import com.moing.backend.domain.missionComment.domain.entity.MissionComment;
5+
import com.moing.backend.domain.missionComment.domain.service.MissionCommentDeleteService;
6+
import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService;
7+
import com.moing.backend.global.response.BaseMissionServiceResponse;
8+
import com.moing.backend.global.utils.BaseMissionService;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
12+
import javax.transaction.Transactional;
13+
14+
@Service
15+
@Transactional
16+
@RequiredArgsConstructor
17+
public class DeleteMissionCommentUseCase {
18+
19+
private final MissionCommentGetService missionCommentGetService;
20+
private final MissionCommentDeleteService missionCommentDeleteService;
21+
private final BaseMissionService baseMissionService;
22+
23+
/**
24+
* 게시글 댓글 삭제
25+
*/
26+
27+
public void deleteMissionComment(String socialId, Long teamId, Long missionArchiveId, Long boardCommentId){
28+
// 1. 게시글 댓글 조회
29+
BaseMissionServiceResponse data = baseMissionService.getCommonData(socialId, teamId, missionArchiveId);
30+
MissionComment missionComment =missionCommentGetService.getComment(boardCommentId);
31+
// 2. 게시글 댓글 작성자만
32+
if (data.getTeamMember() == missionComment.getTeamMember()) {
33+
// 3. 삭제
34+
missionCommentDeleteService.deleteComment(missionComment);
35+
// 4. 댓글 개수 줄이기
36+
data.getMissionArchive().decrComNum();
37+
} else throw new NotAuthByBoardCommentException();
38+
}
39+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.moing.backend.domain.missionComment.application.service;
2+
3+
import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse;
4+
import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService;
5+
import com.moing.backend.global.response.BaseMissionServiceResponse;
6+
import com.moing.backend.global.utils.BaseMissionService;
7+
import lombok.RequiredArgsConstructor;
8+
import org.springframework.stereotype.Service;
9+
10+
import javax.transaction.Transactional;
11+
12+
@Service
13+
@Transactional
14+
@RequiredArgsConstructor
15+
public class GetMissionCommentUseCase {
16+
17+
private final MissionCommentGetService missionCommentGetService;
18+
private final BaseMissionService baseMissionService;
19+
20+
/**
21+
* 게시글 댓글 전체 조회
22+
*/
23+
public GetCommentResponse getBoardCommentAll(String socialId, Long teamId, Long missionArchiveId){
24+
BaseMissionServiceResponse data = baseMissionService.getCommonData(socialId, teamId, missionArchiveId);
25+
return missionCommentGetService.getCommentAll(missionArchiveId, data.getTeamMember());
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.moing.backend.domain.missionComment.application.service;
2+
3+
public class SendMissionAlarmUseCase {
4+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.moing.backend.domain.missionComment.domain.entity;
2+
3+
import com.moing.backend.domain.comment.domain.entity.Comment;
4+
import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive;
5+
import com.moing.backend.domain.teamMember.domain.entity.TeamMember;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Builder;
8+
import lombok.Getter;
9+
import lombok.NoArgsConstructor;
10+
11+
import javax.persistence.*;
12+
13+
@Entity
14+
@Builder
15+
@NoArgsConstructor
16+
@AllArgsConstructor
17+
@Getter
18+
public class MissionComment extends Comment {
19+
20+
@Id
21+
@GeneratedValue(strategy = GenerationType.IDENTITY)
22+
@Column(name = "mission_comment_id")
23+
private Long missionCommentId;
24+
25+
@ManyToOne(fetch = FetchType.LAZY)
26+
@JoinColumn(name = "team_member_id")
27+
private TeamMember teamMember;
28+
29+
@ManyToOne(fetch = FetchType.LAZY)
30+
@JoinColumn(name = "mission_archive_id")
31+
private MissionArchive missionArchive;
32+
33+
/**
34+
* 연관관계 매핑
35+
*/
36+
public void updateMissionArchive(MissionArchive missionArchive) {
37+
this.missionArchive=missionArchive;
38+
}
39+
40+
public void updateTeamMember(TeamMember teamMember) {
41+
this.teamMember = teamMember;
42+
}
43+
44+
public void init(String content, boolean isLeader){
45+
this.content=content;
46+
this.isLeader=isLeader;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.moing.backend.domain.missionComment.domain.repository;
2+
3+
import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse;
4+
import com.moing.backend.domain.history.application.dto.response.NewUploadInfo;
5+
import com.moing.backend.domain.teamMember.domain.entity.TeamMember;
6+
7+
import java.util.List;
8+
import java.util.Optional;
9+
10+
public interface MissionCommentCustomRepository {
11+
GetCommentResponse findMissionCommentAll(Long missionArchiveId, TeamMember teamMember);
12+
13+
Optional<List<NewUploadInfo>> findNewUploadInfo(Long memberId, Long missionArchiveId);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.moing.backend.domain.missionComment.domain.repository;
2+
3+
import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils;
4+
import com.moing.backend.domain.comment.application.dto.response.CommentBlocks;
5+
import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse;
6+
import com.moing.backend.domain.comment.application.dto.response.QCommentBlocks;
7+
import com.moing.backend.domain.history.application.dto.response.NewUploadInfo;
8+
import com.moing.backend.domain.teamMember.domain.entity.QTeamMember;
9+
import com.moing.backend.domain.teamMember.domain.entity.TeamMember;
10+
import com.querydsl.core.types.ExpressionUtils;
11+
import com.querydsl.core.types.Projections;
12+
import com.querydsl.core.types.dsl.BooleanExpression;
13+
import com.querydsl.jpa.JPAExpressions;
14+
import com.querydsl.jpa.impl.JPAQueryFactory;
15+
16+
import javax.persistence.EntityManager;
17+
import java.util.List;
18+
import java.util.Optional;
19+
20+
import static com.moing.backend.domain.member.domain.entity.QMember.member;
21+
import static com.moing.backend.domain.missionComment.domain.entity.QMissionComment.missionComment;
22+
import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember;
23+
24+
public class MissionCommentCustomRepositoryImpl implements MissionCommentCustomRepository{
25+
26+
private final JPAQueryFactory queryFactory;
27+
28+
public MissionCommentCustomRepositoryImpl(EntityManager em) {
29+
this.queryFactory = new JPAQueryFactory(em);
30+
}
31+
32+
33+
@Override
34+
public GetCommentResponse findMissionCommentAll(Long missionArchiveId, TeamMember teamMember) {
35+
36+
BooleanExpression blockCondition = BlockRepositoryUtils.blockCondition(teamMember.getTeamMemberId(), missionComment.teamMember.member.memberId);
37+
38+
List<CommentBlocks> commentBlocks = queryFactory
39+
.select(new QCommentBlocks(
40+
missionComment.missionCommentId,
41+
missionComment.content,
42+
missionComment.teamMember.member.nickName,
43+
missionComment.isLeader,
44+
missionComment.teamMember.member.profileImage,
45+
ExpressionUtils.as(JPAExpressions
46+
.selectOne()
47+
.from(QTeamMember.teamMember)
48+
.where(QTeamMember.teamMember.eq(teamMember)
49+
.and(QTeamMember.teamMember.eq(missionComment.teamMember)))
50+
.exists(), "isWriter"),
51+
missionComment.teamMember.isDeleted,
52+
missionComment.createdDate,
53+
missionComment.teamMember.member.memberId))
54+
.from(missionComment)
55+
.leftJoin(missionComment.teamMember, QTeamMember.teamMember)
56+
.leftJoin(missionComment.teamMember.member, member)
57+
.where(missionComment.missionArchive.id.eq(missionArchiveId)
58+
.and(blockCondition))
59+
.orderBy(missionComment.createdDate.asc())
60+
.fetch();
61+
62+
return new GetCommentResponse(commentBlocks);
63+
}
64+
65+
@Override
66+
public Optional<List<NewUploadInfo>> findNewUploadInfo(Long memberId, Long missionArchiveId) {
67+
BooleanExpression blockCondition= BlockRepositoryUtils.blockCondition(missionComment.teamMember.member.memberId, memberId);
68+
69+
List<NewUploadInfo> result = queryFactory.select(Projections.constructor(NewUploadInfo.class,
70+
missionComment.teamMember.member.fcmToken,
71+
missionComment.teamMember.member.memberId,
72+
missionComment.teamMember.member.isNewUploadPush,
73+
missionComment.teamMember.member.isSignOut))
74+
.distinct()
75+
.from(missionComment)
76+
.leftJoin(missionComment.teamMember, teamMember)
77+
.leftJoin(missionComment.teamMember.member, member)
78+
.where(missionComment.missionArchive.id.eq(missionArchiveId) //게시글의 댓글인데
79+
.and(missionComment.teamMember.member.memberId.ne(memberId)) //나는 포함 안하고
80+
.and(missionComment.teamMember.isDeleted.eq(false)) //탈퇴한 사람도 포함 안함
81+
.and(blockCondition))
82+
.fetch();
83+
84+
return result.isEmpty() ? Optional.empty() : Optional.of(result);
85+
}
86+
}

0 commit comments

Comments
 (0)