diff --git a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java index 226e0f2b0..10bf6c04e 100644 --- a/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java +++ b/src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java @@ -40,4 +40,6 @@ default Application getApplicationBySiteUserIdAndTermId(long siteUserId, long te return findBySiteUserIdAndTermId(siteUserId, termId) .orElseThrow(() -> new CustomException(APPLICATION_NOT_FOUND)); } + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/chat/repository/ChatParticipantRepository.java b/src/main/java/com/example/solidconnection/chat/repository/ChatParticipantRepository.java index 4bce2d08c..19be659f6 100644 --- a/src/main/java/com/example/solidconnection/chat/repository/ChatParticipantRepository.java +++ b/src/main/java/com/example/solidconnection/chat/repository/ChatParticipantRepository.java @@ -1,12 +1,20 @@ package com.example.solidconnection.chat.repository; import com.example.solidconnection.chat.domain.ChatParticipant; +import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface ChatParticipantRepository extends JpaRepository { boolean existsByChatRoomIdAndSiteUserId(long chatRoomId, long siteUserId); Optional findByChatRoomIdAndSiteUserId(long chatRoomId, long siteUserId); + + void deleteAllBySiteUserId(long siteUserId); + + @Query("SELECT cp.id FROM ChatParticipant cp WHERE cp.siteUserId = :siteUserId") + List findAllIdsBySiteUserId(@Param("siteUserId") long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/chat/repository/ChatReadStatusRepository.java b/src/main/java/com/example/solidconnection/chat/repository/ChatReadStatusRepository.java index 5ff82a75b..b6f0fec06 100644 --- a/src/main/java/com/example/solidconnection/chat/repository/ChatReadStatusRepository.java +++ b/src/main/java/com/example/solidconnection/chat/repository/ChatReadStatusRepository.java @@ -1,6 +1,7 @@ package com.example.solidconnection.chat.repository; import com.example.solidconnection.chat.domain.ChatReadStatus; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -15,4 +16,6 @@ INSERT INTO chat_read_status (chat_room_id, chat_participant_id, created_at, upd ON DUPLICATE KEY UPDATE updated_at = NOW(6) """, nativeQuery = true) void upsertReadStatus(@Param("chatRoomId") long chatRoomId, @Param("chatParticipantId") long chatParticipantId); + + void deleteAllByChatParticipantIdIn(List chatParticipantIds); } diff --git a/src/main/java/com/example/solidconnection/community/comment/repository/CommentRepository.java b/src/main/java/com/example/solidconnection/community/comment/repository/CommentRepository.java index 4291eb57c..8464299e5 100644 --- a/src/main/java/com/example/solidconnection/community/comment/repository/CommentRepository.java +++ b/src/main/java/com/example/solidconnection/community/comment/repository/CommentRepository.java @@ -42,4 +42,6 @@ default Comment getById(Long id) { return findById(id) .orElseThrow(() -> new CustomException(INVALID_COMMENT_ID)); } + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/community/post/repository/PostLikeRepository.java b/src/main/java/com/example/solidconnection/community/post/repository/PostLikeRepository.java index 4fa3d3e72..a7791a55e 100644 --- a/src/main/java/com/example/solidconnection/community/post/repository/PostLikeRepository.java +++ b/src/main/java/com/example/solidconnection/community/post/repository/PostLikeRepository.java @@ -16,4 +16,6 @@ default PostLike getByPostAndSiteUserId(Post post, long siteUserId) { return findPostLikeByPostAndSiteUserId(post, siteUserId) .orElseThrow(() -> new CustomException(INVALID_POST_LIKE)); } + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/community/post/repository/PostRepository.java b/src/main/java/com/example/solidconnection/community/post/repository/PostRepository.java index cca590270..285bcb151 100644 --- a/src/main/java/com/example/solidconnection/community/post/repository/PostRepository.java +++ b/src/main/java/com/example/solidconnection/community/post/repository/PostRepository.java @@ -59,4 +59,6 @@ default Post getById(Long id) { return findById(id) .orElseThrow(() -> new CustomException(INVALID_POST_ID)); } + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/mentor/repository/MentorApplicationRepository.java b/src/main/java/com/example/solidconnection/mentor/repository/MentorApplicationRepository.java index d03b53892..186dfb313 100644 --- a/src/main/java/com/example/solidconnection/mentor/repository/MentorApplicationRepository.java +++ b/src/main/java/com/example/solidconnection/mentor/repository/MentorApplicationRepository.java @@ -8,4 +8,6 @@ public interface MentorApplicationRepository extends JpaRepository { boolean existsBySiteUserIdAndMentorApplicationStatusIn(long siteUserId, List mentorApplicationStatuses); + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/mentor/repository/MentorRepository.java b/src/main/java/com/example/solidconnection/mentor/repository/MentorRepository.java index 85dbbc0bf..672f9325e 100644 --- a/src/main/java/com/example/solidconnection/mentor/repository/MentorRepository.java +++ b/src/main/java/com/example/solidconnection/mentor/repository/MentorRepository.java @@ -27,4 +27,6 @@ public interface MentorRepository extends JpaRepository { Slice findAllByRegion(@Param("region") Region region, Pageable pageable); List findAllBySiteUserIdIn(Set siteUserIds); + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java b/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java index 16230b74b..2d072be07 100644 --- a/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java +++ b/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java @@ -39,4 +39,6 @@ public interface MentoringRepository extends JpaRepository { @Query("SELECT m FROM Mentoring m WHERE m.menteeId = :menteeId AND m.verifyStatus = :verifyStatus") Slice findApprovedMentoringsByMenteeId(long menteeId, @Param("verifyStatus") VerifyStatus verifyStatus, Pageable pageable); + + void deleteAllByMenteeId(long menteeId); } diff --git a/src/main/java/com/example/solidconnection/news/repository/LikedNewsRepository.java b/src/main/java/com/example/solidconnection/news/repository/LikedNewsRepository.java index 26e3d8e3c..0bbd60930 100644 --- a/src/main/java/com/example/solidconnection/news/repository/LikedNewsRepository.java +++ b/src/main/java/com/example/solidconnection/news/repository/LikedNewsRepository.java @@ -9,4 +9,6 @@ public interface LikedNewsRepository extends JpaRepository { boolean existsByNewsIdAndSiteUserId(long newsId, long siteUserId); Optional findByNewsIdAndSiteUserId(long newsId, long siteUserId); + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/news/repository/NewsRepository.java b/src/main/java/com/example/solidconnection/news/repository/NewsRepository.java index 0d3ccf3e9..566d8feae 100644 --- a/src/main/java/com/example/solidconnection/news/repository/NewsRepository.java +++ b/src/main/java/com/example/solidconnection/news/repository/NewsRepository.java @@ -8,4 +8,6 @@ public interface NewsRepository extends JpaRepository, NewsCustomRepository { List findAllBySiteUserIdOrderByUpdatedAtDesc(long siteUserId); + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/report/repository/ReportRepository.java b/src/main/java/com/example/solidconnection/report/repository/ReportRepository.java index c32d3cd5f..91e94da8d 100644 --- a/src/main/java/com/example/solidconnection/report/repository/ReportRepository.java +++ b/src/main/java/com/example/solidconnection/report/repository/ReportRepository.java @@ -7,4 +7,6 @@ public interface ReportRepository extends JpaRepository { boolean existsByReporterIdAndTargetTypeAndTargetId(long reporterId, TargetType targetType, long targetId); + + void deleteAllByReporterId(long reporterId); } diff --git a/src/main/java/com/example/solidconnection/scheduler/UserRemovalScheduler.java b/src/main/java/com/example/solidconnection/scheduler/UserRemovalScheduler.java index da39cf2e9..4428e622a 100644 --- a/src/main/java/com/example/solidconnection/scheduler/UserRemovalScheduler.java +++ b/src/main/java/com/example/solidconnection/scheduler/UserRemovalScheduler.java @@ -1,12 +1,32 @@ package com.example.solidconnection.scheduler; +import com.example.solidconnection.application.repository.ApplicationRepository; +import com.example.solidconnection.chat.repository.ChatParticipantRepository; +import com.example.solidconnection.chat.repository.ChatReadStatusRepository; +import com.example.solidconnection.community.comment.repository.CommentRepository; +import com.example.solidconnection.community.post.repository.PostLikeRepository; +import com.example.solidconnection.community.post.repository.PostRepository; +import com.example.solidconnection.location.country.repository.InterestedCountryRepository; +import com.example.solidconnection.location.region.repository.InterestedRegionRepository; +import com.example.solidconnection.mentor.repository.MentorApplicationRepository; +import com.example.solidconnection.mentor.repository.MentorRepository; +import com.example.solidconnection.mentor.repository.MentoringRepository; +import com.example.solidconnection.news.repository.LikedNewsRepository; +import com.example.solidconnection.news.repository.NewsRepository; +import com.example.solidconnection.report.repository.ReportRepository; +import com.example.solidconnection.s3.service.S3Service; +import com.example.solidconnection.score.repository.GpaScoreRepository; +import com.example.solidconnection.score.repository.LanguageTestScoreRepository; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.SiteUserRepository; +import com.example.solidconnection.siteuser.repository.UserBlockRepository; +import com.example.solidconnection.university.repository.LikedUnivApplyInfoRepository; import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor @Component @@ -16,14 +36,67 @@ public class UserRemovalScheduler { public static final int ACCOUNT_RECOVER_DURATION = 30; private final SiteUserRepository siteUserRepository; + private final InterestedCountryRepository interestedCountryRepository; + private final InterestedRegionRepository interestedRegionRepository; + private final CommentRepository commentRepository; + private final PostRepository postRepository; + private final PostLikeRepository postLikeRepository; + private final LikedUnivApplyInfoRepository likedUnivApplyInfoRepository; + private final ApplicationRepository applicationRepository; + private final GpaScoreRepository gpaScoreRepository; + private final LanguageTestScoreRepository languageTestScoreRepository; + private final MentorRepository mentorRepository; + private final MentoringRepository mentoringRepository; + private final NewsRepository newsRepository; + private final LikedNewsRepository likedNewsRepository; + private final ChatParticipantRepository chatParticipantRepository; + private final ChatReadStatusRepository chatReadStatusRepository; + private final ReportRepository reportRepository; + private final UserBlockRepository userBlockRepository; + private final MentorApplicationRepository mentorApplicationRepository; + private final S3Service s3Service; /* * 탈퇴 후 계정 복구 기한까지 방문하지 않은 사용자를 삭제한다. * */ @Scheduled(cron = EVERY_MIDNIGHT) + @Transactional public void scheduledUserRemoval() { LocalDate cutoffDate = LocalDate.now().minusDays(ACCOUNT_RECOVER_DURATION); List usersToRemove = siteUserRepository.findUsersToBeRemoved(cutoffDate); - siteUserRepository.deleteAll(usersToRemove); + + usersToRemove.forEach(this::deleteUserAndRelatedData); + } + + private void deleteUserAndRelatedData(SiteUser user) { + long siteUserId = user.getId(); + + likedNewsRepository.deleteAllBySiteUserId(siteUserId); + newsRepository.deleteAllBySiteUserId(siteUserId); + + postLikeRepository.deleteAllBySiteUserId(siteUserId); + commentRepository.deleteAllBySiteUserId(siteUserId); + postRepository.deleteAllBySiteUserId(siteUserId); + + mentoringRepository.deleteAllByMenteeId(siteUserId); + mentorRepository.deleteAllBySiteUserId(siteUserId); + mentorApplicationRepository.deleteAllBySiteUserId(siteUserId); + + List chatParticipantIds = chatParticipantRepository.findAllIdsBySiteUserId(siteUserId); + chatReadStatusRepository.deleteAllByChatParticipantIdIn(chatParticipantIds); + chatParticipantRepository.deleteAllBySiteUserId(siteUserId); + reportRepository.deleteAllByReporterId(siteUserId); + userBlockRepository.deleteAllByBlockerIdOrBlockedId(siteUserId, siteUserId); + + applicationRepository.deleteAllBySiteUserId(siteUserId); + gpaScoreRepository.deleteAllBySiteUserId(siteUserId); + languageTestScoreRepository.deleteAllBySiteUserId(siteUserId); + likedUnivApplyInfoRepository.deleteAllBySiteUserId(siteUserId); + interestedCountryRepository.deleteAllBySiteUserId(siteUserId); + interestedRegionRepository.deleteAllBySiteUserId(siteUserId); + + s3Service.deleteExProfile(siteUserId); + + siteUserRepository.delete(user); } } diff --git a/src/main/java/com/example/solidconnection/score/repository/GpaScoreRepository.java b/src/main/java/com/example/solidconnection/score/repository/GpaScoreRepository.java index 207e36234..c5ab3094c 100644 --- a/src/main/java/com/example/solidconnection/score/repository/GpaScoreRepository.java +++ b/src/main/java/com/example/solidconnection/score/repository/GpaScoreRepository.java @@ -13,4 +13,6 @@ public interface GpaScoreRepository extends JpaRepository, GpaSc Optional findGpaScoreBySiteUserIdAndId(long siteUserId, Long id); List findBySiteUserId(long siteUserId); + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/score/repository/LanguageTestScoreRepository.java b/src/main/java/com/example/solidconnection/score/repository/LanguageTestScoreRepository.java index 40fe50106..de66cbcc2 100644 --- a/src/main/java/com/example/solidconnection/score/repository/LanguageTestScoreRepository.java +++ b/src/main/java/com/example/solidconnection/score/repository/LanguageTestScoreRepository.java @@ -14,4 +14,6 @@ public interface LanguageTestScoreRepository extends JpaRepository findLanguageTestScoreBySiteUserIdAndId(long siteUserId, Long id); List findBySiteUserId(long siteUserId); + + void deleteAllBySiteUserId(long siteUserId); } diff --git a/src/main/java/com/example/solidconnection/siteuser/repository/UserBlockRepository.java b/src/main/java/com/example/solidconnection/siteuser/repository/UserBlockRepository.java index 28a88874a..01bc06445 100644 --- a/src/main/java/com/example/solidconnection/siteuser/repository/UserBlockRepository.java +++ b/src/main/java/com/example/solidconnection/siteuser/repository/UserBlockRepository.java @@ -24,4 +24,6 @@ public interface UserBlockRepository extends JpaRepository { WHERE ub.blockerId = :blockerId """) Slice findBlockedUsersWithNickname(@Param("blockerId") long blockerId, Pageable pageable); + + void deleteAllByBlockerIdOrBlockedId(long blockerId, long blockedId); } diff --git a/src/main/java/com/example/solidconnection/university/repository/LikedUnivApplyInfoRepository.java b/src/main/java/com/example/solidconnection/university/repository/LikedUnivApplyInfoRepository.java index 0dc8255a6..684703b58 100644 --- a/src/main/java/com/example/solidconnection/university/repository/LikedUnivApplyInfoRepository.java +++ b/src/main/java/com/example/solidconnection/university/repository/LikedUnivApplyInfoRepository.java @@ -25,4 +25,6 @@ public interface LikedUnivApplyInfoRepository extends JpaRepository findUnivApplyInfosBySiteUserId(@Param("siteUserId") long siteUserId); boolean existsBySiteUserIdAndUnivApplyInfoId(long siteUserId, long univApplyInfoId); + + void deleteAllBySiteUserId(long siteUserId); }