@@ -308,31 +308,26 @@ public StudyPlanResponse updateStudyPlan(Long userId, Long planId, StudyPlanRequ
308308 }
309309 }
310310
311- // 원본과 요청을 비교
311+ // 원본과 요청(가상)을 비교
312312 private UpdateType determineUpdateType (StudyPlan originalPlan , StudyPlanRequest request ) {
313- // 1. 반복 룰 없음 -> 단발성 이므로 원본 수정
314- if (originalPlan .getRepeatRule () == null ) {
315- return UpdateType .ORIGINAL_PLAN_UPDATE ;
316- }
317-
318- // 2-1. 반복 계획에서 요청 날짜가 원본 날짜와 같음 -> 원본이므로 원본 수정
319313 LocalDate requestDate = request .getStartDate ().toLocalDate ();
320314 LocalDate originalDate = originalPlan .getStartDate ().toLocalDate ();
321315
316+ // 1-1. 반복 계획에서 요청 날짜가 원본 날짜와 같음 -> 원본이므로 원본 수정
322317 if (requestDate .equals (originalDate )) {
323318 return UpdateType .ORIGINAL_PLAN_UPDATE ;
324319 }
325320
326- // 2 -2. 반복 계획에서 다른 날짜인 경우 -> 기존 예외 확인
321+ // 1 -2. 반복 계획에서 다른 날짜인 경우 -> 기존 예외 확인
327322 Optional <StudyPlanException > existingException = studyPlanExceptionRepository
328323 .findByPlanIdAndDate (originalPlan .getId (), requestDate .atStartOfDay ());
329324
330325 if (existingException .isPresent ()) {
331- return UpdateType .REPEAT_INSTANCE_UPDATE ; // 기존 예외 수정
332- } else {
333- return UpdateType .REPEAT_INSTANCE_CREATE ; // 새 예외 생성
334- }
326+ return UpdateType .REPEAT_INSTANCE_UPDATE ; // 기존 예외 수정
327+ } else {
328+ return UpdateType .REPEAT_INSTANCE_CREATE ; // 새 예외 생성
335329 }
330+ }
336331
337332 // 원본 계획 수정
338333 private StudyPlanResponse updateOriginalPlan (StudyPlan originalPlan , StudyPlanRequest request ) {
@@ -372,9 +367,27 @@ private StudyPlanResponse createRepeatException(StudyPlan originalPlan, StudyPla
372367 if (request .getEndDate () != null ) exception .setModifiedEndDate (request .getEndDate ());
373368 if (request .getColor () != null ) exception .setModifiedColor (request .getColor ());
374369
375- studyPlanExceptionRepository .save (exception );
370+ // 반복 규칙 수정. 요청에 반복 규칙이 있으면 설정
371+ if (request .getRepeatRule () != null ) {
372+ RepeatRuleEmbeddable embeddable = new RepeatRuleEmbeddable ();
373+ embeddable .setFrequency (request .getRepeatRule ().getFrequency ());
374+ embeddable .setIntervalValue (request .getRepeatRule ().getIntervalValue ());
375+ embeddable .setByDay (request .getRepeatRule ().getByDay ());
376+
377+ if (request .getRepeatRule ().getUntilDate () != null && !request .getRepeatRule ().getUntilDate ().isEmpty ()) {
378+ try {
379+ LocalDate untilDate = LocalDate .parse (request .getRepeatRule ().getUntilDate ());
380+ embeddable .setUntilDate (untilDate );
381+ } catch (Exception e ) {
382+ throw new CustomException (ErrorCode .BAD_REQUEST );
383+ }
384+ }
385+
386+ exception .setModifiedRepeatRule (embeddable );
387+ }
376388
377- // 수정된 가상 계획 반환
389+
390+ studyPlanExceptionRepository .save (exception );
378391 return createVirtualPlanForDate (originalPlan , exceptionDate );
379392 }
380393
@@ -395,23 +408,40 @@ private StudyPlanResponse updateExistingException(StudyPlan originalPlan, StudyP
395408 // ApplyScope도 업데이트 (사용자가 범위를 변경할 수 있음)
396409 existingException .setApplyScope (applyScope );
397410
398- studyPlanExceptionRepository .save (existingException );
411+ // 반복 규칙 수정사항 있으면 예외 안에 추가 (embeddable)
412+ if (request .getRepeatRule () != null ) {
413+ RepeatRuleEmbeddable embeddable = new RepeatRuleEmbeddable ();
414+ embeddable .setFrequency (request .getRepeatRule ().getFrequency ());
415+ embeddable .setIntervalValue (request .getRepeatRule ().getIntervalValue ());
416+ embeddable .setByDay (request .getRepeatRule ().getByDay ());
417+
418+ if (request .getRepeatRule ().getUntilDate () != null && !request .getRepeatRule ().getUntilDate ().isEmpty ()) {
419+ try {
420+ LocalDate untilDate = LocalDate .parse (request .getRepeatRule ().getUntilDate ());
421+ embeddable .setUntilDate (untilDate );
422+ } catch (Exception e ) {
423+ throw new CustomException (ErrorCode .BAD_REQUEST );
424+ }
425+ }
399426
400- // 수정된 가상 계획 반환
427+ existingException .setModifiedRepeatRule (embeddable );
428+ }
429+
430+ studyPlanExceptionRepository .save (existingException );
401431 return createVirtualPlanForDate (originalPlan , exceptionDate );
402432 }
403433
404434
405- // 반복 룰 수정
435+ // 원본의 반복 룰 수정 (엔티티)
406436 private void updateRepeatRule (RepeatRule repeatRule , StudyPlanRequest .RepeatRuleRequest request ) {
407437 if (request .getFrequency () != null ) repeatRule .setFrequency (request .getFrequency ());
408438 if (request .getIntervalValue () != null ) repeatRule .setRepeatInterval (request .getIntervalValue ());
409439 if (request .getByDay () != null ) repeatRule .setByDay (request .getByDay ());
410440
411441 if (request .getUntilDate () != null && !request .getUntilDate ().isEmpty ()) {
412442 try {
413- LocalDateTime untilDateTime = LocalDateTime .parse (request .getUntilDate () + "T23:59:59" );
414- repeatRule .setUntilDate (untilDateTime );
443+ LocalDate untilDate = LocalDate .parse (request .getUntilDate ());
444+ repeatRule .setUntilDate (untilDate );
415445 } catch (Exception e ) {
416446 throw new CustomException (ErrorCode .BAD_REQUEST );
417447 }
@@ -422,6 +452,7 @@ private void updateRepeatRule(RepeatRule repeatRule, StudyPlanRequest.RepeatRule
422452
423453
424454 // ==================== 유틸 ===================
455+ // 인가 (작성자 일치 확인)
425456 private void validateUserAccess (StudyPlan studyPlan , Long userId ) {
426457 if (!studyPlan .getUser ().getId ().equals (userId )) {
427458 throw new CustomException (ErrorCode .FORBIDDEN );
0 commit comments