@@ -571,29 +571,30 @@ private void deleteRepeatPlan(StudyPlan studyPlan, LocalDate selectedDate, Apply
571571 if (exception .getApplyScope () == ApplyScope .FROM_THIS_DATE
572572 && exception .getExceptionType () == StudyPlanException .ExceptionType .MODIFIED ) {
573573
574- LocalDate nextDate = selectedDate . plusDays ( 1 );
575-
576- // 다음 날에 이미 예외가 있는지 확인
577- Optional < StudyPlanException > nextDayException = studyPlanExceptionRepository
578- . findByPlanIdAndDate ( studyPlan . getId (), nextDate );
579-
580- // 예외가 없을 때만 새로 생성
581- if (! nextDayException . isPresent () ) {
574+ // 다음 빈 날짜 찾기
575+ LocalDate availableDate = findNextAvailableDateForException (
576+ studyPlan ,
577+ selectedDate . plusDays ( 1 )
578+ );
579+
580+ // 빈 날짜가 있으면 FROM_THIS_DATE 예외 생성
581+ if (availableDate != null ) {
582582 StudyPlanException continuedException = new StudyPlanException ();
583583 continuedException .setStudyPlan (studyPlan );
584- continuedException .setExceptionDate (nextDate );
584+ continuedException .setExceptionDate (availableDate );
585585 continuedException .setExceptionType (StudyPlanException .ExceptionType .MODIFIED );
586586 continuedException .setApplyScope (ApplyScope .FROM_THIS_DATE );
587587
588- // 기존 수정 내용 복사
588+ // 기존 수정 내용 복사 (날짜는 availableDate로 조정)
589+ long daysDiff = ChronoUnit .DAYS .between (selectedDate , availableDate );
589590 continuedException .setModifiedSubject (exception .getModifiedSubject ());
590591 if (exception .getModifiedStartDate () != null ) {
591592 continuedException .setModifiedStartDate (
592- exception .getModifiedStartDate ().plusDays (1 ));
593+ exception .getModifiedStartDate ().plusDays (daysDiff ));
593594 }
594595 if (exception .getModifiedEndDate () != null ) {
595596 continuedException .setModifiedEndDate (
596- exception .getModifiedEndDate ().plusDays (1 ));
597+ exception .getModifiedEndDate ().plusDays (daysDiff ));
597598 }
598599 continuedException .setModifiedColor (exception .getModifiedColor ());
599600 continuedException .setModifiedRepeatRule (exception .getModifiedRepeatRule ());
@@ -719,4 +720,41 @@ private void getByDayInWeekly(StudyPlanRequest.RepeatRuleRequest request, LocalD
719720 }
720721 }
721722
723+ // THIS_ONLY로 FROM_THIS_DATE 예외를 삭제할 때 다음 빈 날짜 찾기 (재귀탐색)
724+ private LocalDate findNextAvailableDateForException (StudyPlan studyPlan , LocalDate startDate ) {
725+ LocalDate currentDate = startDate ;
726+ LocalDate untilDate = studyPlan .getRepeatRule ().getUntilDate ();
727+
728+ // untilDate가 있으면 그것을 최대 범위로, 없으면 1년
729+ int maxDays = untilDate != null
730+ ? (int ) ChronoUnit .DAYS .between (startDate , untilDate ) + 1
731+ : 365 ;
732+
733+ int daysChecked = 0 ;
734+
735+ while (daysChecked < maxDays ) {
736+ // untilDate 체크
737+ if (untilDate != null && currentDate .isAfter (untilDate )) {
738+ return null ;
739+ }
740+
741+ // 해당 날짜에 반복이 발생하는지 확인
742+ if (shouldRepeatOnDate (studyPlan , currentDate )) {
743+ // 해당 날짜에 예외가 있는지 확인
744+ Optional <StudyPlanException > exception = studyPlanExceptionRepository
745+ .findByPlanIdAndDate (studyPlan .getId (), currentDate );
746+
747+ if (!exception .isPresent ()) {
748+ return currentDate ; // 빈 날짜 찾음
749+ }
750+ }
751+
752+ currentDate = currentDate .plusDays (1 );
753+ daysChecked ++;
754+ }
755+
756+ // 1년 동안 빈 날짜를 찾지 못한 경우 예외 발생
757+ throw new CustomException (ErrorCode .PLAN_TOO_MANY_EXCEPTIONS );
758+ }
759+
722760}
0 commit comments