Skip to content
This repository was archived by the owner on Jan 11, 2026. It is now read-only.
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 @@ -3,15 +3,14 @@
import com.example.spot.post.domain.Post;
import com.example.spot.post.domain.schedule.PostScheduleComments;
import com.example.spot.post.infrastructure.jpa.PostRepository;
import com.example.spot.post.infrastructure.jpa.PostScheduleCommentsRepository;
import com.example.spot.post.infrastructure.jpa.schedule.PostScheduleCommentsRepository;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class PostSortCommentsScheduler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
import com.example.spot.post.domain.Post;
import com.example.spot.post.domain.schedule.PostScheduleLikes;
import com.example.spot.post.infrastructure.jpa.PostRepository;
import com.example.spot.post.infrastructure.jpa.PostScheduleLikesRepository;
import com.example.spot.post.infrastructure.jpa.schedule.PostScheduleLikesRepository;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class PostSortLikesScheduler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
import com.example.spot.post.domain.Post;
import com.example.spot.post.domain.schedule.PostScheduleRealTime;
import com.example.spot.post.infrastructure.jpa.PostRepository;
import com.example.spot.post.infrastructure.jpa.PostScheduleRealTimeRepository;
import com.example.spot.post.infrastructure.jpa.schedule.PostScheduleRealTimeRepository;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class PostSortRealTimeScheduler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ public interface ScrapPostUseCase {
ScrapPostResponse cancelPostScrap(Long postId, Long memberId);

//게시글 스크랩 모두 취소
ScrapsPostDeleteResponse cancelPostScraps(ScrapAllDeleteRequest request);
ScrapsPostDeleteResponse cancelPostScraps(ScrapAllDeleteRequest request, Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import com.example.spot.member.domain.Member;
import com.example.spot.member.infrastructure.jpa.MemberRepository;
import com.example.spot.post.application.command.LikePostUseCase;
import com.example.spot.post.application.query.GetLikedPostUseCase;
import com.example.spot.post.domain.Post;
import com.example.spot.post.infrastructure.jpa.PostRepository;
import com.example.spot.post.domain.association.LikedPost;
import com.example.spot.post.infrastructure.jpa.LikedPostRepository;
import com.example.spot.post.infrastructure.jpa.PostRepository;
import com.example.spot.post.infrastructure.jpa.PostStatsRepository;
import com.example.spot.post.presentation.dto.response.post.PostLikeResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -24,8 +25,7 @@ public class LikePostUseCaseImpl implements LikePostUseCase {
private final MemberRepository memberRepository;
private final PostRepository postRepository;
private final LikedPostRepository likedPostRepository;

private final GetLikedPostUseCase getLikedPostUseCase;
private final PostStatsRepository postStatsRepository;

/**
* 게시글에 좋아요를 합니다.
Expand All @@ -40,33 +40,15 @@ public class LikePostUseCaseImpl implements LikePostUseCase {
@Transactional
@Override
public PostLikeResponse likePost(Long postId, Long memberId) {
// 회원 정보 가져오기
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND));
// 게시글 조회
Post post = postRepository.findById(postId)
.orElseThrow(() -> new PostHandler(ErrorStatus._POST_NOT_FOUND));
//좋아요 여부 확인
if (likedPostRepository.findByMemberIdAndPostId(memberId, postId).isPresent()) {
throw new PostHandler(ErrorStatus._POST_ALREADY_LIKED);
}

// 좋아요 객체 생성 및 저장
LikedPost likedPost = LikedPost.builder()
.post(post)
.member(member)
.build();
ensurePostAndMemberExist(postId, memberId);

likedPostRepository.saveAndFlush(likedPost);
// 회원 정보 가져오기
Member memberRef = requireMemberRef(memberId);
Post postRef = requirePostRef(postId);

// 게시글의 현재 좋아요 수 조회
long likeCount = getLikedPostUseCase.countByPostId(postId);
saveLikePostAndIncreaseLikeCount(postId, postRef, memberRef);

// 좋아요 결과 반환
return PostLikeResponse.builder()
.postId(post.getId())
.likeCount(likeCount)
.build();
return getPostLikeResponse(postId, postRef);
}

/**
Expand All @@ -82,26 +64,66 @@ public PostLikeResponse likePost(Long postId, Long memberId) {
@Transactional
@Override
public PostLikeResponse cancelPostLike(Long postId, Long memberId) {
// 회원 정보 가져오기
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND));
// 게시글 조회
Post post = postRepository.findById(postId)
.orElseThrow(() -> new PostHandler(ErrorStatus._POST_NOT_FOUND));
// 좋아요 여부 확인
LikedPost likedPost = likedPostRepository.findByMemberIdAndPostId(member.getId(), post.getId())
.orElseThrow(() -> new PostHandler(ErrorStatus._POST_NOT_LIKED));

// 좋아요 객체 삭제
likedPostRepository.delete(likedPost);
likedPostRepository.flush();
ensurePostAndMemberExist(postId, memberId);
Post postRef = requirePostRef(postId);

deleteLikePostAndDecreaseLikeCount(postId, memberId);

// 게시글의 현재 좋아요 수 조회
long likeCount = getLikedPostUseCase.countByPostId(postId);
return getPostLikeResponse(postId, postRef);
}

/* ------------------------------- private method ------------------------------------------ */

// 좋아요 취소 결과 반환
private void ensurePostAndMemberExist(Long postId, Long memberId) {
// 게시글 존재 여부 확인
if (!postRepository.existsById(postId)) {
throw new PostHandler(ErrorStatus._POST_NOT_FOUND);
}

// 회원 존재 여부 확인
if (!memberRepository.existsById(memberId)) {
throw new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND);
}
}

private Member requireMemberRef(Long memberId) {
return memberRepository.getReferenceById(memberId);
}

private Post requirePostRef(Long postId) {
return postRepository.getReferenceById(postId);
}

private void saveLikePostAndIncreaseLikeCount(Long postId, Post postRef, Member memberRef) {
try {
// 1) 좋아요 행 삽입 시도
likedPostRepository.save(
LikedPost.builder()
.post(postRef)
.member(memberRef)
.build()
);

// 2) 삽입 성공한 경우에만 카운터 +1
postStatsRepository.incrementLike(postId);
} catch (DataIntegrityViolationException e) {
throw new PostHandler(ErrorStatus._POST_ALREADY_LIKED);
}
}

private void deleteLikePostAndDecreaseLikeCount(Long postId, Long memberId) {
int effectedRow = likedPostRepository.deleteByMemberIdAndPostId(memberId, postId);
if (effectedRow == 1) {
postStatsRepository.decrementLike(postId);
}
}

private PostLikeResponse getPostLikeResponse(Long postId, Post postRef) {
long likeCount = postStatsRepository.getLikeCount(postId);
// 좋아요 결과 반환
return PostLikeResponse.builder()
.postId(post.getId())
.postId(postRef.getId())
.likeCount(likeCount)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package com.example.spot.post.application.command.impl;

import com.example.spot.post.domain.PostComment;
import com.example.spot.post.infrastructure.jpa.PostCommentRepository;
import com.example.spot.post.presentation.dto.request.comment.CommentCreateRequest;
import com.example.spot.post.presentation.dto.response.comment.CommentCreateResponse;
import com.example.spot.common.api.code.status.ErrorStatus;
import com.example.spot.common.api.exception.handler.MemberHandler;
import com.example.spot.common.api.exception.handler.PostHandler;
import com.example.spot.member.domain.Member;
import com.example.spot.member.infrastructure.jpa.MemberRepository;
import com.example.spot.post.application.command.ManagePostCommentUseCase;
import com.example.spot.post.domain.Post;
import com.example.spot.post.domain.PostComment;
import com.example.spot.post.infrastructure.jpa.PostCommentRepository;
import com.example.spot.post.infrastructure.jpa.PostRepository;
import com.example.spot.post.infrastructure.jpa.PostStatsRepository;
import com.example.spot.post.presentation.dto.request.comment.CommentCreateRequest;
import com.example.spot.post.presentation.dto.response.comment.CommentCreateResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -24,6 +25,7 @@ public class ManagePostCommentUseCaseImpl implements ManagePostCommentUseCase {
private final PostRepository postRepository;
private final MemberRepository memberRepository;
private final PostCommentRepository postCommentRepository;
private final PostStatsRepository postStatsRepository;

/**
* 게시글에 댓글을 생성합니다.
Expand All @@ -38,29 +40,47 @@ public class ManagePostCommentUseCaseImpl implements ManagePostCommentUseCase {
@Transactional
@Override
public CommentCreateResponse createComment(Long postId, Long memberId, CommentCreateRequest request) {
// 게시글 조회
Post post = postRepository.findById(postId)
.orElseThrow(() -> new PostHandler(ErrorStatus._POST_NOT_FOUND));

// 회원 정보 가져오기
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND));
// 게시글과 회원 존재 여부 확인 및 참조 가져오기
ensurePostAndMemberExist(postId, memberId);
Post post = requirePostRef(postId);
Member member = requireMemberRef(memberId);

// 부모 댓글 생성
// 댓글 생성 및 저장
PostComment comment = PostComment.builder()
.content(request.getContent())
.isAnonymous(request.isAnonymous())
.post(post)
.parentComment(null)
.member(member)
.build();
PostComment saved = savePostCommentAndIncreaseCommentCount(postId, comment);

// 댓글 객체 저장
comment = postCommentRepository.saveAndFlush(comment);
post.addComment(comment);
post.plusCommentNum();
return CommentCreateResponse.toDTO(saved);
}

/* ------------------------------- private method ------------------------------------------ */

private void ensurePostAndMemberExist(Long postId, Long memberId) {
// 게시글 존재 여부 확인
if (!postRepository.existsById(postId)) {
throw new PostHandler(ErrorStatus._POST_NOT_FOUND);
}

// 회원 존재 여부 확인
if (!memberRepository.existsById(memberId)) {
throw new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND);
}
}

private Member requireMemberRef(Long memberId) {
return memberRepository.getReferenceById(memberId);
}

private Post requirePostRef(Long postId) {
return postRepository.getReferenceById(postId);
}

// 생성된 댓글 정보 반환
return CommentCreateResponse.toDTO(comment);
private PostComment savePostCommentAndIncreaseCommentCount(Long postId, PostComment comment) {
postStatsRepository.incrementComment(postId);
return postCommentRepository.save(comment);
}
}
Loading