Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@ class PostMapper(

fun toDetailResponse(
post: Post,
authorMember: ClubMember,
comments: List<CommentResponse>,
files: List<FileResponse>,
isLiked: Boolean,
) = PostDetailResponse(
id = post.id,
boardId = post.board.id,
boardName = post.board.name,
author = UserInfo.of(post.user, authorMember.memberRole, resolveProfileImage(authorMember)),
author = UserInfo.of(post.clubMember.user, post.clubMember.memberRole, resolveProfileImage(post.clubMember)),
title = post.title,
content = post.content,
time = post.modifiedAt,
Expand All @@ -46,13 +45,12 @@ class PostMapper(

fun toListResponse(
post: Post,
authorMember: ClubMember,
hasFile: Boolean,
now: LocalDateTime,
isLiked: Boolean,
) = PostListResponse(
id = post.id,
author = UserInfo.of(post.user, authorMember.memberRole, resolveProfileImage(authorMember)),
author = UserInfo.of(post.clubMember.user, post.clubMember.memberRole, resolveProfileImage(post.clubMember)),
boardId = post.board.id,
boardName = post.board.name,
title = post.title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,13 @@ import com.weeth.domain.file.application.mapper.FileMapper
import com.weeth.domain.file.domain.enums.FileOwnerType
import com.weeth.domain.file.domain.repository.FileReader
import com.weeth.domain.file.domain.repository.FileRepository
import com.weeth.domain.user.domain.repository.UserReader
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class ManagePostUseCase(
private val postRepository: PostRepository,
private val boardRepository: BoardRepository,
private val userReader: UserReader,
private val clubMemberPolicy: ClubMemberPolicy,
private val clubMemberCardinalReader: ClubMemberCardinalReader,
private val fileRepository: FileRepository,
Expand All @@ -44,7 +42,6 @@ class ManagePostUseCase(
userId: Long,
): PostSaveResponse {
val member = clubMemberPolicy.getActiveMember(clubId, userId)
val user = userReader.getById(userId)
val board = findBoardInClub(boardId, clubId)
validateWritePermission(board, member)

Expand All @@ -57,7 +54,7 @@ class ManagePostUseCase(
Post.create(
title = request.title,
content = request.content,
user = user,
clubMember = member,
board = board,
cardinalNumber = currentCardinalNumber,
)
Expand All @@ -75,7 +72,6 @@ class ManagePostUseCase(
userId: Long,
): PostSaveResponse {
val member = clubMemberPolicy.getActiveMember(clubId, userId)
val user = userReader.getById(userId)
val post = findPost(postId)
if (post.board.club.id != clubId) throw PostNotFoundException()
validateOwner(post, userId)
Expand All @@ -97,7 +93,6 @@ class ManagePostUseCase(
userId: Long,
) {
val member = clubMemberPolicy.getActiveMember(clubId, userId)
val user = userReader.getById(userId)
val post = findPost(postId)
if (post.board.club.id != clubId) throw PostNotFoundException()
validateOwner(post, userId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import com.weeth.domain.board.application.mapper.PostMapper
import com.weeth.domain.board.domain.repository.BoardRepository
import com.weeth.domain.board.domain.repository.PostLikeRepository
import com.weeth.domain.board.domain.repository.PostRepository
import com.weeth.domain.club.domain.entity.ClubMember
import com.weeth.domain.club.domain.enums.MemberRole
import com.weeth.domain.club.domain.repository.ClubMemberReader
import com.weeth.domain.club.domain.service.ClubMemberPolicy
import com.weeth.domain.comment.application.usecase.query.GetCommentQueryService
import com.weeth.domain.comment.domain.repository.CommentReader
Expand All @@ -34,7 +32,6 @@ class GetPostQueryService(
private val boardRepository: BoardRepository,
private val postLikeRepository: PostLikeRepository,
private val clubMemberPolicy: ClubMemberPolicy,
private val clubMemberReader: ClubMemberReader,
private val commentReader: CommentReader,
private val getCommentQueryService: GetCommentQueryService,
private val fileReader: FileReader,
Expand All @@ -60,14 +57,10 @@ class GetPostQueryService(
val files = fileReader.findAll(FileOwnerType.POST, post.id).map(fileMapper::toFileResponse)
val comments = commentReader.findAllByPostId(post.id)

val commentAuthorIds = comments.map { it.user.id }.distinct()
val allAuthorIds = (commentAuthorIds + post.user.id).distinct()
val memberMap = buildMemberMap(clubId, allAuthorIds)

val commentTree = getCommentQueryService.toCommentTreeResponses(comments, memberMap)
val commentTree = getCommentQueryService.toCommentTreeResponses(comments)
val isLiked = postLikeRepository.existsByPostAndUserIdAndIsActiveTrue(post, userId)

return postMapper.toDetailResponse(post, memberMap.getValue(post.user.id), commentTree, files, isLiked)
return postMapper.toDetailResponse(post, commentTree, files, isLiked)
}

fun findAllPosts(
Expand All @@ -93,15 +86,13 @@ class GetPostQueryService(

val posts = postRepository.findAllActiveByBoardIds(accessibleBoardIds, pageable)
val postIds = posts.content.map { it.id }
val memberMap = buildMemberMap(clubId, posts.content.map { it.user.id }.distinct())
val fileExistsByPostId = buildFileExistsMap(postIds)
val likedPostIds = postLikeRepository.findLikedPostIds(postIds, userId)
val now = LocalDateTime.now()

return posts.map { post ->
postMapper.toListResponse(
post,
memberMap.getValue(post.user.id),
fileExistsByPostId[post.id] == true,
now,
post.id in likedPostIds,
Expand All @@ -125,14 +116,12 @@ class GetPostQueryService(

val postIds = posts.content.map { it.id }
val fileExistsByPostId = buildFileExistsMap(postIds)
val memberMap = buildMemberMap(clubId, posts.content.map { it.user.id }.distinct())
val likedPostIds = postLikeRepository.findLikedPostIds(postIds, userId)
val now = LocalDateTime.now()

return posts.map { post ->
postMapper.toListResponse(
post,
memberMap.getValue(post.user.id),
fileExistsByPostId[post.id] == true,
now,
post.id in likedPostIds,
Expand Down Expand Up @@ -160,32 +149,19 @@ class GetPostQueryService(

val postIds = posts.content.map { it.id }
val fileExistsByPostId = buildFileExistsMap(postIds)
val memberMap = buildMemberMap(clubId, posts.content.map { it.user.id }.distinct())
val likedPostIds = postLikeRepository.findLikedPostIds(postIds, userId)
val now = LocalDateTime.now()

return posts.map { post ->
postMapper.toListResponse(
post,
memberMap.getValue(post.user.id),
fileExistsByPostId[post.id] == true,
now,
post.id in likedPostIds,
)
}
}

/**
* Post, Comment 조회 시 작성자 정보를 매핑하기 위한 헬퍼 메서드
*/
private fun buildMemberMap(
clubId: Long,
userIds: List<Long>,
): Map<Long, ClubMember> {
if (userIds.isEmpty()) return emptyMap()
return clubMemberReader.findAllByClubIdAndUserIds(clubId, userIds).associateBy { it.user.id }
}

private fun validatePage(
pageNumber: Int,
pageSize: Int,
Expand Down
14 changes: 7 additions & 7 deletions src/main/kotlin/com/weeth/domain/board/domain/entity/Post.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.weeth.domain.board.domain.entity

import com.weeth.domain.user.domain.entity.User
import com.weeth.domain.club.domain.entity.ClubMember
import com.weeth.global.common.entity.BaseEntity
import jakarta.persistence.Column
import jakarta.persistence.Entity
Expand All @@ -17,7 +17,7 @@ import jakarta.persistence.Table
class Post(
title: String,
content: String,
user: User,
clubMember: ClubMember,
board: Board,
cardinalNumber: Int? = null,
) : BaseEntity() {
Expand All @@ -35,8 +35,8 @@ class Post(
private set

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false)
var user: User = user
@JoinColumn(name = "club_member_id", nullable = false)
var clubMember: ClubMember = clubMember
private set

@ManyToOne(fetch = FetchType.LAZY, optional = false)
Expand Down Expand Up @@ -78,7 +78,7 @@ class Post(
likeCount--
}

fun isOwnedBy(userId: Long): Boolean = user.id == userId
fun isOwnedBy(userId: Long): Boolean = clubMember.user.id == userId

fun belongsToClub(clubId: Long): Boolean = board.club.id == clubId && !board.isDeleted

Expand Down Expand Up @@ -108,7 +108,7 @@ class Post(
fun create(
title: String,
content: String,
user: User,
clubMember: ClubMember,
board: Board,
cardinalNumber: Int? = null,
): Post {
Expand All @@ -117,7 +117,7 @@ class Post(
return Post(
title = title,
content = content,
user = user,
clubMember = clubMember,
board = board,
cardinalNumber = cardinalNumber,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import java.time.LocalDateTime
interface PostRepository :
JpaRepository<Post, Long>,
PostReader {
@EntityGraph(attributePaths = ["user", "board"])
@EntityGraph(attributePaths = ["clubMember", "clubMember.user", "board"])
@Query(
"""
SELECT p
Expand All @@ -35,7 +35,7 @@ interface PostRepository :
pageable: Pageable,
): Slice<Post>

@EntityGraph(attributePaths = ["user", "board"])
@EntityGraph(attributePaths = ["clubMember", "clubMember.user", "board"])
@Query(
"""
SELECT p
Expand All @@ -52,6 +52,7 @@ interface PostRepository :

fun findByIdAndIsDeletedFalse(id: Long): Post?

@EntityGraph(attributePaths = ["clubMember", "clubMember.user", "board"])
@Query(
"""
SELECT p
Expand All @@ -65,6 +66,7 @@ interface PostRepository :
@Param("id") id: Long,
): Post?

@EntityGraph(attributePaths = ["board", "board.club"])
@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints(QueryHint(name = "jakarta.persistence.lock.timeout", value = "2000"))
@Query(
Expand All @@ -80,7 +82,7 @@ interface PostRepository :
@Param("id") id: Long,
): Post?

@EntityGraph(attributePaths = ["user", "board"])
@EntityGraph(attributePaths = ["clubMember", "clubMember.user", "board"])
@Query(
"""
SELECT p
Expand All @@ -106,7 +108,7 @@ interface PostRepository :
pageable: Pageable,
): Slice<Post> = findAllActiveByBoardIds(boardIds, pageable)

@EntityGraph(attributePaths = ["user"])
@EntityGraph(attributePaths = ["clubMember", "clubMember.user"])
@Query(
"""
SELECT p
Expand All @@ -122,7 +124,7 @@ interface PostRepository :
pageable: Pageable,
): Slice<Post>

@EntityGraph(attributePaths = ["user"])
@EntityGraph(attributePaths = ["clubMember", "clubMember.user"])
@Query(
"""
SELECT p
Expand All @@ -138,7 +140,7 @@ interface PostRepository :
pageable: Pageable,
): Slice<Post>

@EntityGraph(attributePaths = ["user"])
@EntityGraph(attributePaths = ["clubMember", "clubMember.user"])
@Query(
"""
SELECT p
Expand All @@ -156,7 +158,7 @@ interface PostRepository :
pageable: Pageable,
): Slice<Post>

@EntityGraph(attributePaths = ["user"])
@EntityGraph(attributePaths = ["clubMember", "clubMember.user"])
@Query(
"""
SELECT p
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.weeth.domain.comment.application.mapper

import com.weeth.domain.club.domain.entity.ClubMember
import com.weeth.domain.comment.application.dto.response.CommentResponse
import com.weeth.domain.comment.domain.entity.Comment
import com.weeth.domain.file.application.dto.response.FileResponse
Expand All @@ -14,17 +13,16 @@ class CommentMapper(
) {
fun toCommentDto(
comment: Comment,
authorMember: ClubMember,
children: List<CommentResponse>,
fileUrls: List<FileResponse>,
): CommentResponse =
CommentResponse(
id = comment.id,
author =
UserInfo.of(
comment.user,
authorMember.memberRole,
authorMember.profileImageStorageKey?.let { fileAccessUrlPort.resolve(it) },
comment.clubMember.user,
comment.clubMember.memberRole,
comment.clubMember.profileImageStorageKey?.let { fileAccessUrlPort.resolve(it) },
),
content = comment.content,
time = comment.modifiedAt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.weeth.domain.comment.application.usecase.command
import com.weeth.domain.board.application.exception.PostNotFoundException
import com.weeth.domain.board.domain.entity.Post
import com.weeth.domain.board.domain.repository.PostRepository
import com.weeth.domain.club.domain.service.ClubMemberPolicy
import com.weeth.domain.comment.application.dto.request.CommentSaveRequest
import com.weeth.domain.comment.application.dto.request.CommentUpdateRequest
import com.weeth.domain.comment.application.exception.CommentAlreadyDeletedException
Expand All @@ -15,15 +16,14 @@ import com.weeth.domain.file.application.mapper.FileMapper
import com.weeth.domain.file.domain.enums.FileOwnerType
import com.weeth.domain.file.domain.repository.FileReader
import com.weeth.domain.file.domain.repository.FileRepository
import com.weeth.domain.user.domain.repository.UserReader
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class ManageCommentUseCase(
private val commentRepository: CommentRepository,
private val postRepository: PostRepository, // 타 도메인 이므로 Reader 사용 검토
private val userReader: UserReader,
private val clubMemberPolicy: ClubMemberPolicy,
private val fileReader: FileReader,
private val fileRepository: FileRepository,
private val fileMapper: FileMapper,
Expand All @@ -34,8 +34,9 @@ class ManageCommentUseCase(
postId: Long,
userId: Long,
) {
val user = userReader.getById(userId)
val post = findPostWithLock(postId)
val clubId = post.board.club.id
val clubMember = clubMemberPolicy.getActiveMember(clubId, userId)
val parent =
dto.parentCommentId?.let { parentId ->
commentRepository.findByIdAndPostId(parentId, postId) ?: throw CommentNotFoundException()
Expand All @@ -45,7 +46,7 @@ class ManageCommentUseCase(
Comment.createForPost(
content = dto.content,
post = post,
user = user,
clubMember = clubMember,
parent = parent,
)
val savedComment = commentRepository.save(comment)
Expand Down
Loading