@@ -101,5 +101,67 @@ public void checkAndProcessLevelUp(Member member) {
101101 }
102102 }
103103
104+ @ Transactional
105+ public void checkLevelDown (Integer memberId , int xpBeforeRevoke , int revokedXp ) {
106+ log .info ("### [LEVELDOWN] START checkLevelDown for Member ID: {}" , memberId );
107+
108+ Member member = memberRepository .findById (memberId )
109+ .orElseThrow (() -> new CustomException (ErrorCode .NOT_FOUND , "Member not found with id: " + memberId ));
110+
111+ log .info (" [Current Status] Initial Level: {}, XP Before Revoke: {}, Revoked XP: {}" ,
112+ member .getLevel (), xpBeforeRevoke , revokedXp );
113+
114+ checkAndProcessLevelDown (member , xpBeforeRevoke , revokedXp );
115+
116+ memberRepository .save (member );
117+
118+ log .info ("### [LEVELDOWN] END checkLevelDown. Final Level: {}, Final XP: {}, Final XP Req: {}" ,
119+ member .getLevel (), member .getXp (), member .getXpReq ());
120+ }
121+
122+ private void checkAndProcessLevelDown (Member member , int xpBeforeRevoke , int revokedXp ) {
123+ int currentLevel = member .getLevel ();
124+
125+ // 레벨이 1보다 크고, XP가 0이 되어 롤백이 필요한 상황을 가정
126+ // (XP가 0이 아닌 다른 값이라면 레벨 다운이 필요 없다고 가정)
127+ while (currentLevel > 1 && member .getXp () == 0 ) {
128+
129+ int previousLevel = currentLevel - 1 ;
130+
131+ Optional <LevelXP > previousLevelXP = levelXPRepository .findById (previousLevel );
132+
133+ if (previousLevelXP .isEmpty ()) {
134+ log .warn (" [LEVEL DOWN FAILED] Previous Level XP requirement not found for Level {}. Aborting rollback." , previousLevel );
135+ break ;
136+ }
137+
138+ int xpToNextOfPreviousLevel = previousLevelXP .get ().getXpToNext ();
139+
140+ // 1. XP 복원 계산 (요청된 4990 XP로 복원되는 핵심 로직)
141+ // 복원 XP = (이전 레벨 요구 XP) + (회수 전 잔여 XP) - (회수된 XP)
142+ // 시나리오: 5000 + 390 - 400 = 4990
143+ int restoredXp = xpToNextOfPreviousLevel + xpBeforeRevoke - revokedXp ;
144+
145+ // 2. 레벨 다운 처리
146+ currentLevel = previousLevel ;
147+ member .setLevel (currentLevel );
148+
149+ // XP 복원 값 설정
150+ member .setXp (restoredXp );
151+
152+ log .info (" [LEVEL DOWN!] Member Leveled Down to {}. Restored XP: {}" , currentLevel , restoredXp );
153+
154+ // 3. 다음 레벨 요구량(xpReq) 업데이트
155+ member .setXpReq (xpToNextOfPreviousLevel );
156+ log .info (" [XP Req Update] Next XP Required: {}" , xpToNextOfPreviousLevel );
157+
158+ // 4. 레벨 다운 보상 회수 (필요하다면 로직 추가)
159+ // levelUpRewardService.revokeReward(member.getId(), previousLevel + 1);
160+
161+ // 단일 레벨 롤백만 처리하고 루프 종료
162+ break ;
163+ }
164+ }
165+
104166
105167}
0 commit comments