Skip to content

Commit

Permalink
Merge branch 'main' into feat/757-popular-tag-api-create
Browse files Browse the repository at this point in the history
  • Loading branch information
jschoi-96 authored Nov 29, 2024
2 parents 17d6f66 + 5601f13 commit 657a7c2
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 119 deletions.
150 changes: 70 additions & 80 deletions src/main/java/balancetalk/comment/application/CommentService.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,27 +116,12 @@ public Page<LatestCommentResponse> findAllComments(Long talkPickId, Pageable pag

Page<Comment> comments = commentRepository.findAllByTalkPickIdAndParentIsNull(talkPickId, pageable);

return comments.map(comment -> { //TODO : Duplicates 메서드 분리
int likesCount = likeRepository.countByResourceIdAndLikeType(comment.getId(), LikeType.COMMENT);
boolean myLike = isCommentMyLiked(comment.getId(), guestOrApiMember);
Member member = comment.getMember();
VoteOption option = member.getVoteOnTalkPick(talkPick)
.isPresent() ? member.getVoteOnTalkPick(talkPick).get().getVoteOption() : null;

if (member.getProfileImgId() == null) {
return LatestCommentResponse.fromEntity(comment, option, null, likesCount, myLike);
}

String imgUrl = fileRepository.findById(member.getProfileImgId())
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_FILE))
.getImgUrl();

return LatestCommentResponse.fromEntity(comment, option, imgUrl, likesCount, myLike);
});
return convertToLatestCommentPagesResponse(comments, talkPick, guestOrApiMember);
}

@Transactional(readOnly = true)
public List<LatestCommentResponse> findAllReplies(Long parentId, Long talkPickId, GuestOrApiMember guestOrApiMember) {
public List<LatestCommentResponse> findAllReplies(Long parentId, Long talkPickId,
GuestOrApiMember guestOrApiMember) {

// 부모 댓글이 존재하는지 확인
validateCommentId(parentId);
Expand All @@ -149,102 +134,107 @@ public List<LatestCommentResponse> findAllReplies(Long parentId, Long talkPickId
// 해당 부모 댓글의 답글 조회
List<Comment> replies = commentRepository.findAllRepliesByParentIdOrderByMemberAndCreatedAt(parentId, memberId);

return replies.stream().map(reply -> {
int likesCount = likeRepository.countByResourceIdAndLikeType(reply.getId(), LikeType.COMMENT);
boolean myLike = isCommentMyLiked(reply.getId(), guestOrApiMember);
Member member = reply.getMember();
VoteOption option = member.getVoteOnTalkPick(talkPick)
.isPresent() ? member.getVoteOnTalkPick(talkPick).get().getVoteOption() : null;
if (member.getProfileImgId() == null) {
return LatestCommentResponse.fromEntity(reply, option, null, likesCount, myLike);
}
return convertToLatestCommentResponse(replies, talkPick, guestOrApiMember);
}

String imgUrl = fileRepository.findById(member.getProfileImgId())
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_FILE))
.getImgUrl();
// Page<Comment> 처리
private Page<LatestCommentResponse> convertToLatestCommentPagesResponse(Page<Comment> comments, TalkPick talkPick,
GuestOrApiMember guestOrApiMember) {
return comments.map(comment -> mapToLatestCommentResponse(comment, talkPick, guestOrApiMember));
}

return LatestCommentResponse.fromEntity(reply, option, imgUrl, likesCount, myLike);})
// List<Comment> 처리
private List<LatestCommentResponse> convertToLatestCommentResponse(List<Comment> comments, TalkPick talkPick,
GuestOrApiMember guestOrApiMember) {
return comments.stream()
.map(comment -> mapToLatestCommentResponse(comment, talkPick, guestOrApiMember))
.toList();
}

// 공통 변환 로직
private LatestCommentResponse mapToLatestCommentResponse(Comment comment, TalkPick talkPick,
GuestOrApiMember guestOrApiMember) {
int likesCount = likeRepository.countByResourceIdAndLikeType(comment.getId(), LikeType.COMMENT);
boolean myLike = isCommentMyLiked(comment.getId(), guestOrApiMember);
Member member = comment.getMember();
VoteOption option = member.getVoteOnTalkPick(talkPick)
.isPresent() ? member.getVoteOnTalkPick(talkPick).get().getVoteOption() : null;

@Transactional(readOnly = true)
String imgUrl = (member.getProfileImgId() != null) ? fileRepository.findById(member.getProfileImgId())
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_FILE))
.getImgUrl() : null;

return LatestCommentResponse.fromEntity(comment, option, imgUrl, likesCount, myLike);
}

@Transactional
public Page<BestCommentResponse> findAllBestComments(Long talkPickId, Pageable pageable,
GuestOrApiMember guestOrApiMember) {
validateTalkPickId(talkPickId);
TalkPick talkPick = talkPickRepository.findById(talkPickId)
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_TALK_PICK));

List<Comment> allComments = commentRepository.findByTalkPickIdAndParentIsNullOrderByLikesCountDescCreatedAtAsc(talkPickId,
LikeType.COMMENT);
List<BestCommentResponse> bestComments = new ArrayList<>();
List<BestCommentResponse> otherComments = new ArrayList<>();
List<Comment> allComments = commentRepository.findByTalkPickIdAndParentIsNullOrderByLikesCountDescCreatedAtAsc(
talkPickId, LikeType.COMMENT);

// 최대 좋아요 수 구하기
// 최대 좋아요 수 계산
int maxLikes = allComments.stream()
.mapToInt(comment -> likeRepository.countByResourceIdAndLikeType(comment.getId(), LikeType.COMMENT))
.max()
.orElse(0);

// 좋아요 10개 이상인 댓글이 있는 경우
if (maxLikes >= MIN_COUNT_FOR_BEST_COMMENT) {
for (Comment comment : allComments) {
boolean myLike = isCommentMyLiked(comment.getId(), guestOrApiMember);
int likeCount = likeRepository.countByResourceIdAndLikeType(comment.getId(), LikeType.COMMENT);
Member member = comment.getMember();
VoteOption option = member.getVoteOnTalkPick(talkPick)
.isPresent() ? member.getVoteOnTalkPick(talkPick).get().getVoteOption() : null;
comment.setIsBest(likeCount >= MIN_COUNT_FOR_BEST_COMMENT);
BestCommentResponse response = validateImgUrl(member, comment, option, likeCount, myLike);

if (comment.getIsBest()) {
bestComments.add(response);
} else {
otherComments.add(response);
}
}
} else {
for (Comment comment : allComments) {
boolean myLike = isCommentMyLiked(comment.getId(), guestOrApiMember);
int likeCount = likeRepository.countByResourceIdAndLikeType(comment.getId(), LikeType.COMMENT);
Member member = comment.getMember();
VoteOption option = member.getVoteOnTalkPick(talkPick)
.isPresent() ? member.getVoteOnTalkPick(talkPick).get().getVoteOption() : null;
comment.setIsBest(likeCount == maxLikes);

BestCommentResponse response = validateImgUrl(member, comment, option, likeCount, myLike);

if (comment.getIsBest()) {
bestComments.add(response);
} else {
otherComments.add(response);
}
List<BestCommentResponse> bestComments = new ArrayList<>();
List<BestCommentResponse> otherComments = new ArrayList<>();

for (Comment comment : allComments) {
BestCommentResponse response = processFindBestComments(comment, talkPick, guestOrApiMember, maxLikes);
if (comment.getIsBest()) {
bestComments.add(response);
} else {
otherComments.add(response);
}
}

// 정렬
bestComments.sort(Comparator.comparing(BestCommentResponse::getCreatedAt).reversed());
otherComments.sort(Comparator.comparing(BestCommentResponse::getCreatedAt).reversed());

// 결과 병합
List<BestCommentResponse> result = new ArrayList<>();
result.addAll(bestComments);
result.addAll(otherComments);

// 페이징 처리
int start = (int) pageable.getOffset();
int end = Math.min((start + pageable.getPageSize()), result.size());

return new PageImpl<>(result.subList(start, end), pageable, result.size());
}

private BestCommentResponse validateImgUrl(Member member, Comment comment, VoteOption option,
int likeCount, boolean myLike) {
if (member.getProfileImgId() != null) {
String imgUrl = fileRepository.findById(member.getProfileImgId())
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_FILE))
.getImgUrl();

return BestCommentResponse.fromEntity(comment, option, imgUrl, likeCount, myLike);
private BestCommentResponse processFindBestComments(Comment comment, TalkPick talkPick,
GuestOrApiMember guestOrApiMember, int maxLikes) {
boolean myLike = isCommentMyLiked(comment.getId(), guestOrApiMember);
int likeCount = likeRepository.countByResourceIdAndLikeType(comment.getId(), LikeType.COMMENT);
Member member = comment.getMember();
VoteOption option = member.getVoteOnTalkPick(talkPick)
.isPresent() ? member.getVoteOnTalkPick(talkPick).get().getVoteOption() : null;

// isBest 여부 설정
comment.setIsBest(likeCount >= MIN_COUNT_FOR_BEST_COMMENT || likeCount == maxLikes);
String imgUrl = fetchProfileImgUrl(member);

// BestCommentResponse 생성
return BestCommentResponse.fromEntity(comment, option, imgUrl, likeCount, myLike);
}

// 프로필 이미지 URL 조회
private String fetchProfileImgUrl(Member member) {
if (member.getProfileImgId() == null) {
return null;
}
return BestCommentResponse.fromEntity(comment, option, null, likeCount, myLike);
return fileRepository.findById(member.getProfileImgId())
.orElseThrow(() -> new BalanceTalkException(NOT_FOUND_FILE))
.getImgUrl();
}

public void updateComment(Long commentId, Long talkPickId, String content, ApiMember apiMember) {
Expand Down Expand Up @@ -336,7 +326,7 @@ private void sendReplyNotification(Comment parentComment) {

// 첫 답글 알림
if ((isFirstReplyFromOther && !parentComment.getIsNotifiedForFirstReply()) && !notificationHistory.getOrDefault(firstReplyKey, false)) {
notificationService.sendTalkPickNotification(parentCommentAuthor,talkPick,
notificationService.sendTalkPickNotification(parentCommentAuthor, talkPick,
category, FIRST_COMMENT_REPLY.getMessage());
parentComment.setIsNotifiedForFirstReplyTrue();
// 50, 100개 답글 알림
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/balancetalk/file/domain/File.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package balancetalk.file.domain;

import static balancetalk.file.domain.FileType.FRIENDS;

import balancetalk.global.common.BaseTimeEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
Expand Down Expand Up @@ -71,4 +73,8 @@ public String getS3Key() {
public boolean isUnmapped() {
return directoryPath.endsWith("temp/") && resourceId == null;
}

public boolean isUploadedByMember() {
return fileType != FRIENDS;
}
}
62 changes: 36 additions & 26 deletions src/main/java/balancetalk/game/application/GameService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import balancetalk.game.dto.GameDto.CreateGameMainTagRequest;
import balancetalk.game.dto.GameDto.CreateOrUpdateGame;
import balancetalk.game.dto.GameDto.GameDetailResponse;
import balancetalk.game.dto.GameOptionDto;
import balancetalk.game.dto.GameSetDto.CreateGameSetRequest;
import balancetalk.game.dto.GameSetDto.GameSetDetailResponse;
import balancetalk.game.dto.GameSetDto.GameSetResponse;
Expand All @@ -29,7 +28,6 @@
import balancetalk.vote.domain.GameVote;
import balancetalk.vote.domain.VoteOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -67,9 +65,22 @@ public Long createBalanceGameSet(final CreateGameSetRequest request, final ApiMe
}

gameSet.addGames(games);
gameSetRepository.save(gameSet);
processFiles(request.getGames(), games);
return gameSet.getId();
GameSet savedGameSet = gameSetRepository.save(gameSet);

for (Game game : savedGameSet.getGames()) {
for (GameOption gameOption : game.getGameOptions()) {
relocateFileIfHasImage(gameOption);
}
}

return savedGameSet.getId();
}

private void relocateFileIfHasImage(GameOption gameOption) {
if (gameOption.hasImage()) {
fileRepository.findById(gameOption.getImgId())
.ifPresent(file -> fileHandler.relocateFile(file, gameOption.getId(), GAME_OPTION));
}
}

@Transactional
Expand All @@ -83,30 +94,29 @@ public void updateBalanceGame(Long gameSetId, UpdateGameSetRequest request, ApiM
.map(gameRequest -> gameRequest.toEntity(fileRepository))
.toList();

gameSet.updateGameSetRequest(request.getTitle(), mainTag, request.getSubTag(), newGames);
processFiles(request.getGames(), gameSet.getGames());
}

private void processFiles(List<CreateOrUpdateGame> gameRequests, List<Game> games) {
for (int i = 0; i < gameRequests.size(); i++) {
CreateOrUpdateGame gameRequest = gameRequests.get(i);
Game game = games.get(i);

for (int j = 0; j < gameRequest.getGameOptions().size(); j++) {
GameOptionDto gameOptionDto = gameRequest.getGameOptions().get(j);
GameOption gameOption = game.getGameOptions().get(j);

if (gameOptionDto.getFileId() == null) {
continue;
List<Game> oldGames = gameSet.getGames();
for (int i = 0; i < 10; i++) {
Game oldGame = oldGames.get(i);
Game newGame = newGames.get(i);
List<GameOption> oldGameGameOptions = oldGame.getGameOptions();
List<GameOption> newGameGameOptions = newGame.getGameOptions();
for (int j = 0; j < 2; j++) {
GameOption oldGameOption = oldGameGameOptions.get(j);
GameOption newGameOption = newGameGameOptions.get(j);
if (newGameOption.hasImage()) {
if (oldGameOption.hasImage()) {
File oldFile = fileRepository.findById(oldGameOption.getImgId())
.orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_FILE));
fileHandler.deleteFile(oldFile);
}
File newFile = fileRepository.findById(newGameOption.getImgId())
.orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_FILE));
fileHandler.relocateFile(newFile, oldGameOption.getId(), GAME_OPTION);
}

fileRepository.findById(gameOptionDto.getFileId())
.ifPresent(
file -> fileHandler.relocateFiles(Collections.singletonList(file), gameOption.getId(),
GAME_OPTION));

}
}

gameSet.updateGameSetRequest(request.getTitle(), mainTag, request.getSubTag(), newGames);
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void createTempGame(CreateTempGameSetRequest request, ApiMember apiMember

if (member.hasTempGameSet()) { // 기존 임시저장이 존재하는 경우
TempGameSet existGame = member.getTempGameSet();
existGame.updateTempGameSet(request.getTitle(), newTempGames);
existGame.updateTempGameSet(request.getTitle(), request.getSubTag(), mainTag, newTempGames);
processTempGameFiles(tempGames, existGame.getTempGames());
return;
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/balancetalk/game/domain/GameOption.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public class GameOption {
@Size(max = 30)
private String name;

private Long imgId;

private String imgUrl;

@Size(max = 50)
Expand All @@ -65,6 +67,7 @@ public void addGame(Game game) {
}

public void updateGameOption(GameOption newGameOption) {
this.imgId = newGameOption.getImgId();
this.imgUrl = newGameOption.getImgUrl();
this.name = newGameOption.getName();
this.description = newGameOption.getDescription();
Expand All @@ -81,4 +84,8 @@ public void increaseVotesCount() {
public void decreaseVotesCount() {
this.votesCount--;
}

public boolean hasImage() {
return imgUrl != null && imgId != null;
}
}
4 changes: 3 additions & 1 deletion src/main/java/balancetalk/game/domain/TempGameSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ public void addGames(List<TempGame> tempGames) {
});
}

public void updateTempGameSet(String title, List<TempGame> newTempGames) {
public void updateTempGameSet(String title, String subTag, MainTag mainTag, List<TempGame> newTempGames) {
this.title = title;
this.subTag = subTag;
this.mainTag = mainTag;
IntStream.range(0, this.tempGames.size()).forEach(i -> {
TempGame existingGame = this.tempGames.get(i);
TempGame newGame = newTempGames.get(i);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/balancetalk/game/dto/GameOptionDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public GameOption toEntity(FileRepository fileRepository) {
}
return GameOption.builder()
.name(name)
.imgId(fileId)
.imgUrl(newImgUrl)
.description(description)
.optionType(optionType)
Expand Down
Loading

0 comments on commit 657a7c2

Please sign in to comment.