-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/#139 광고 플랫폼 연동 해제 API 추가 #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ojy0903
wants to merge
15
commits into
develop
Choose a base branch
from
feat/#139
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 9 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
23f19a7
:sparkles: feat: 플랫폼 연동 해제를 위한 PlatformErrorCode 오류 코드 추가
ojy0903 597823b
:sparkles: feat: 플랫폼 연동 해제를 위한 Repository 메서드 추가
ojy0903 973f2b3
:sparkles: feat: 플랫폼 연동 해제를 별도 Executor 클래스 추가
ojy0903 db323f2
:sparkles: feat: 플랫폼 연동 해제를 위한 Service 메서드 추가
ojy0903 b25cdda
:sparkles: feat: 플랫폼 연동 해제 API 추가
ojy0903 8e640ae
:sparkles: feat: PlatformConnection 삭제 시 FK 위반 보완
ojy0903 f5201e7
:sparkles: feat: PlatformConnection 삭제 시 FK 위반 보완 & DB 풀 고갈 방지를 위한 로직 분리
ojy0903 e4a3abf
Merge remote-tracking branch 'origin/develop' into feat/#139
ojy0903 19f3009
:art: style: 소스코드 주석 추가
ojy0903 17edad5
Merge remote-tracking branch 'origin/develop' into feat/#139
ojy0903 ac597b0
:sparkles: feat: 빈 Project 엔티티 삭제 시 연관된 MetricFact 가 0인지 검증하는 로직 추가
ojy0903 2a2ca5f
:sparkles: feat: 시스템 내부 호출용 플랫폼 계정 단위 연동 해제 로직 추가 (회원탈퇴 시 활용)
ojy0903 6bb9a49
:sparkles: feat: 회원 탈퇴 전용 Organization Soft Delete 메서드 추가
ojy0903 f20f1cd
:sparkles: feat: 회원 탈퇴 시 플랫폼 연동 여부 검증 제거 및 Hard Delete 시 자동 연동 해제 로직 추가
ojy0903 a8ce99a
:recycle: refactor: PlatformConnectionRepository 미사용 메서드 제거
ojy0903 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
...om/whereyouad/WhereYouAd/domains/platform/domain/service/PlatformDataCleanupExecutor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| package com.whereyouad.WhereYouAd.domains.platform.domain.service; | ||
|
|
||
| import com.whereyouad.WhereYouAd.domains.advertisement.persistence.entity.AdCampaign; | ||
| import com.whereyouad.WhereYouAd.domains.advertisement.persistence.repository.AdCampaignRepository; | ||
| import com.whereyouad.WhereYouAd.domains.advertisement.persistence.repository.MetricFactRepository; | ||
| import com.whereyouad.WhereYouAd.domains.click.persistence.repository.ClickLogRepository; | ||
| import com.whereyouad.WhereYouAd.domains.organization.domain.constant.OrgRole; | ||
| import com.whereyouad.WhereYouAd.domains.organization.persistence.entity.OrgMember; | ||
| import com.whereyouad.WhereYouAd.domains.organization.persistence.repository.OrgMemberRepository; | ||
| import com.whereyouad.WhereYouAd.domains.platform.exception.PlatformHandler; | ||
| import com.whereyouad.WhereYouAd.domains.platform.exception.code.PlatformErrorCode; | ||
| import com.whereyouad.WhereYouAd.domains.platform.persistence.entity.PlatformAccount; | ||
| import com.whereyouad.WhereYouAd.domains.platform.persistence.entity.PlatformConnection; | ||
| import com.whereyouad.WhereYouAd.domains.platform.persistence.repository.PlatformAccountRepository; | ||
| import com.whereyouad.WhereYouAd.domains.platform.persistence.repository.PlatformConnectionRepository; | ||
| import com.whereyouad.WhereYouAd.domains.project.persistence.repository.ProjectRepository; | ||
| import com.whereyouad.WhereYouAd.domains.user.exception.code.UserErrorCode; | ||
| import com.whereyouad.WhereYouAd.domains.user.exception.handler.UserHandler; | ||
| import com.whereyouad.WhereYouAd.domains.user.persistence.repository.UserRepository; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.transaction.annotation.Propagation; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @Slf4j | ||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class PlatformDataCleanupExecutor { | ||
|
|
||
| private static final int BATCH_SIZE = 1000; | ||
|
|
||
| private final UserRepository userRepository; | ||
| private final OrgMemberRepository orgMemberRepository; | ||
| private final PlatformAccountRepository platformAccountRepository; | ||
| private final PlatformConnectionRepository platformConnectionRepository; | ||
| private final AdCampaignRepository adCampaignRepository; | ||
| private final ProjectRepository projectRepository; | ||
| private final ClickLogRepository clickLogRepository; | ||
| private final MetricFactRepository metricFactRepository; | ||
|
|
||
| // 권한 & 소유자 검증 + 삭제에 영향받는 projectId 반환 (read-only & 짧은 트랜잭션) | ||
| @Transactional(readOnly = true) | ||
| public List<Long> verifyAndCollectProjectIds(Long userId, Long orgId, Long accountId) { | ||
| userRepository.findById(userId) | ||
| .orElseThrow(() -> new UserHandler(UserErrorCode.USER_NOT_FOUND)); | ||
|
|
||
| OrgMember orgMember = orgMemberRepository.findByUserIdAndOrgId(userId, orgId) | ||
| .orElseThrow(() -> new PlatformHandler(PlatformErrorCode.PLATFORM_ORG_MEMBER_NOT_FOUND)); | ||
|
|
||
| if (orgMember.getRole() != OrgRole.ADMIN) { | ||
| throw new PlatformHandler(PlatformErrorCode.PLATFORM_FORBIDDEN); | ||
| } | ||
|
|
||
| PlatformAccount platformAccount = platformAccountRepository.findById(accountId) | ||
| .orElseThrow(() -> new PlatformHandler(PlatformErrorCode.PLATFORM_ACCOUNT_NOT_FOUND)); | ||
|
|
||
| if (!platformAccount.getOrganization().getId().equals(orgId)) { | ||
| throw new PlatformHandler(PlatformErrorCode.PLATFORM_ACCOUNT_NOT_BELONG_TO_ORG); | ||
| } | ||
|
|
||
| platformConnectionRepository.findByUserIdAndPlatformAccountId(userId, accountId) | ||
| .orElseThrow(() -> new PlatformHandler(PlatformErrorCode.PLATFORM_NOT_ACCOUNT_OWNER)); | ||
|
|
||
| return adCampaignRepository.findDistinctProjectIdsByPlatformAccountId(accountId); | ||
| } | ||
|
|
||
| // 청크 단위로 ClickLog 삭제 — 메인 트랜잭션과 분리 | ||
| @Transactional(propagation = Propagation.REQUIRES_NEW) | ||
| public int deleteClickLogChunk(Long platformAccountId) { | ||
| int deleted = clickLogRepository.deleteByPlatformAccountIdInBatch(platformAccountId, BATCH_SIZE); | ||
| if (deleted > 0) { | ||
| log.debug("ClickLog 청크 삭제 - platformAccountId={}, deleted={}", platformAccountId, deleted); | ||
| } | ||
| return deleted; | ||
| } | ||
|
|
||
| // 청크 단위로 MetricFact 삭제 | ||
| @Transactional(propagation = Propagation.REQUIRES_NEW) | ||
| public int deleteMetricFactChunk(Long platformAccountId) { | ||
| int deleted = metricFactRepository.deleteByPlatformAccountIdInBatch(platformAccountId, BATCH_SIZE); | ||
| if (deleted > 0) { | ||
| log.debug("MetricFact 청크 삭제 - platformAccountId={}, deleted={}", platformAccountId, deleted); | ||
| } | ||
| return deleted; | ||
| } | ||
|
|
||
| // AdCampaign + PlatformConnection + PlatformAccount 원자적 삭제 | ||
| @Transactional | ||
| public void deleteAccountAndRelations(Long accountId) { | ||
| PlatformAccount platformAccount = platformAccountRepository.findById(accountId) | ||
| .orElseThrow(() -> new PlatformHandler(PlatformErrorCode.PLATFORM_ACCOUNT_NOT_FOUND)); | ||
|
|
||
| List<AdCampaign> campaigns = adCampaignRepository.findByPlatformAccount(platformAccount); | ||
|
|
||
| if (!campaigns.isEmpty()) { | ||
| adCampaignRepository.deleteAll(campaigns); | ||
| adCampaignRepository.flush(); | ||
| //AdCampaign 삭제 시 CascadeType.ALL 로 인해 연관된 AdGroup, AdContent 도 함꼐 제거됨 | ||
| } | ||
|
|
||
| List<PlatformConnection> connections = platformConnectionRepository.findAllByPlatformAccount_Id(accountId); | ||
|
|
||
| if (!connections.isEmpty()) { | ||
| platformConnectionRepository.deleteAll(connections); | ||
| platformConnectionRepository.flush(); | ||
| } | ||
|
|
||
| platformAccountRepository.delete(platformAccount); | ||
| } | ||
|
|
||
| //빈 Project 1개 삭제 | ||
| @Transactional | ||
| public void deleteEmptyProject(Long projectId) { | ||
| if (adCampaignRepository.countByProject_Id(projectId) == 0) { | ||
| projectRepository.deleteById(projectId); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.