11package com .back .domain .study .plan .service ;
22
3- import com .back .domain .study .plan .dto .StudyPlanDeleteRequest ;
3+ import com .back .domain .study .plan .dto .StudyPlanDeleteResponse ;
44import com .back .domain .study .plan .dto .StudyPlanRequest ;
55import com .back .domain .study .plan .dto .StudyPlanResponse ;
66import com .back .domain .study .plan .entity .*;
@@ -69,19 +69,9 @@ private RepeatRule createRepeatRule(StudyPlanRequest.RepeatRuleRequest request,
6969 repeatRule .setStudyPlan (studyPlan );
7070 repeatRule .setFrequency (request .getFrequency ());
7171 repeatRule .setRepeatInterval (request .getIntervalValue () != null ? request .getIntervalValue () : 1 );
72+ // byDay 설정 (WEEKLY인 경우에만 의미 있음)
73+ getByDayInWeekly (request , studyPlan , repeatRule );
7274
73- // byDay 설정 (WEEKLY 인 경우에만)
74- if (request .getFrequency () == Frequency .WEEKLY ) {
75- // 1. byDay가 없으면 시작일 요일을 자동으로 설정 (현재 구현 의도 반영)
76- if (request .getByDay () == null || request .getByDay ().isEmpty ()) {
77- String startDayOfWeek = studyPlan .getStartDate ().getDayOfWeek ().name ().substring (0 , 3 );
78- // *가정: RepeatRule.byDay는 List<String> 타입으로 가정
79- repeatRule .setByDay (List .of (startDayOfWeek ));
80- } else {
81- // 2. byDay가 있다면 요청 값을 사용 (List<String> to List<String> 매핑 확인)
82- repeatRule .setByDay (request .getByDay ());
83- }
84- }
8575 // untilDate 설정 및 검증
8676 LocalDate untilDate ;
8777
@@ -335,6 +325,10 @@ public StudyPlanResponse updateStudyPlan(Long userId, Long planId, StudyPlanRequ
335325
336326 switch (updateType ) {
337327 case ORIGINAL_PLAN_UPDATE :
328+ // 요청에 반복 규칙이 있으면 반복 규칙 수정 후 원본 계획 수정
329+ if (request .getRepeatRule () != null ) {
330+ updateRepeatRule (originalPlan .getRepeatRule (), request .getRepeatRule (), originalPlan );
331+ }
338332 return updateOriginalPlan (originalPlan , request );
339333
340334 case REPEAT_INSTANCE_CREATE :
@@ -390,11 +384,6 @@ private StudyPlanResponse updateOriginalPlan(StudyPlan originalPlan, StudyPlanRe
390384 if (request .getEndDate () != null ) originalPlan .setEndDate (request .getEndDate ());
391385 if (request .getColor () != null ) originalPlan .setColor (request .getColor ());
392386
393- // 요청에 반복 규칙이 있고 원본 반복성 계획인 경우에만 반복 규칙 수정
394- if (request .getRepeatRule () != null && originalPlan .getRepeatRule () != null ) {
395- updateRepeatRule (originalPlan .getRepeatRule (), request .getRepeatRule ());
396- }
397-
398387 StudyPlan savedPlan = studyPlanRepository .save (originalPlan );
399388 return new StudyPlanResponse (savedPlan );
400389 }
@@ -412,7 +401,7 @@ private StudyPlanResponse createRepeatException(StudyPlan originalPlan, StudyPla
412401 exception .setStudyPlan (originalPlan );
413402 exception .setExceptionDate (exceptionDate );
414403 exception .setExceptionType (StudyPlanException .ExceptionType .MODIFIED );
415- exception .setApplyScope (applyScope ); // 파라미터로 받은 applyScope
404+ exception .setApplyScope (applyScope );
416405
417406 // 수정된 내용 설정
418407 if (request .getSubject () != null ) exception .setModifiedSubject (request .getSubject ());
@@ -422,24 +411,10 @@ private StudyPlanResponse createRepeatException(StudyPlan originalPlan, StudyPla
422411
423412 // 반복 규칙 수정. 요청에 반복 규칙이 있으면 설정
424413 if (request .getRepeatRule () != null ) {
425- RepeatRuleEmbeddable embeddable = new RepeatRuleEmbeddable ();
426- embeddable .setFrequency (request .getRepeatRule ().getFrequency ());
427- embeddable .setIntervalValue (request .getRepeatRule ().getIntervalValue ());
428- embeddable .setByDay (request .getRepeatRule ().getByDay ());
429-
430- if (request .getRepeatRule ().getUntilDate () != null && !request .getRepeatRule ().getUntilDate ().isEmpty ()) {
431- try {
432- LocalDate untilDate = LocalDate .parse (request .getRepeatRule ().getUntilDate ());
433- embeddable .setUntilDate (untilDate );
434- } catch (Exception e ) {
435- throw new CustomException (ErrorCode .INVALID_DATE_FORMAT );
436- }
437- }
438-
414+ RepeatRuleEmbeddable embeddable = createRepeatRuleEmbeddable (request .getRepeatRule (), request .getStartDate ());
439415 exception .setModifiedRepeatRule (embeddable );
440416 }
441417
442-
443418 studyPlanExceptionRepository .save (exception );
444419 return createVirtualPlanForDate (originalPlan , exceptionDate );
445420 }
@@ -458,38 +433,26 @@ private StudyPlanResponse updateExistingException(StudyPlan originalPlan, StudyP
458433 if (request .getEndDate () != null ) existingException .setModifiedEndDate (request .getEndDate ());
459434 if (request .getColor () != null ) existingException .setModifiedColor (request .getColor ());
460435
461- // ApplyScope도 업데이트 (사용자가 범위를 변경할 수 있음)
436+ // ApplyScope도 업데이트
462437 existingException .setApplyScope (applyScope );
463438
464439 // 반복 규칙 수정사항 있으면 예외 안에 추가 (embeddable)
465440 if (request .getRepeatRule () != null ) {
466- RepeatRuleEmbeddable embeddable = new RepeatRuleEmbeddable ();
467- embeddable .setFrequency (request .getRepeatRule ().getFrequency ());
468- embeddable .setIntervalValue (request .getRepeatRule ().getIntervalValue ());
469- embeddable .setByDay (request .getRepeatRule ().getByDay ());
470-
471- if (request .getRepeatRule ().getUntilDate () != null && !request .getRepeatRule ().getUntilDate ().isEmpty ()) {
472- try {
473- LocalDate untilDate = LocalDate .parse (request .getRepeatRule ().getUntilDate ());
474- embeddable .setUntilDate (untilDate );
475- } catch (Exception e ) {
476- throw new CustomException (ErrorCode .INVALID_DATE_FORMAT );
477- }
478- }
479-
441+ RepeatRuleEmbeddable embeddable = createRepeatRuleEmbeddable (request .getRepeatRule (), request .getStartDate ());
480442 existingException .setModifiedRepeatRule (embeddable );
481443 }
482444
483445 studyPlanExceptionRepository .save (existingException );
484446 return createVirtualPlanForDate (originalPlan , exceptionDate );
485447 }
486448
487-
488449 // 원본의 반복 룰 수정 (엔티티)
489- private void updateRepeatRule (RepeatRule repeatRule , StudyPlanRequest .RepeatRuleRequest request ) {
450+ private void updateRepeatRule (RepeatRule repeatRule , StudyPlanRequest .RepeatRuleRequest request , StudyPlan studyPlan ) {
490451 if (request .getFrequency () != null ) repeatRule .setFrequency (request .getFrequency ());
491452 if (request .getIntervalValue () != null ) repeatRule .setRepeatInterval (request .getIntervalValue ());
492- if (request .getByDay () != null ) repeatRule .setByDay (request .getByDay ());
453+
454+ // byDay 자동 설정 (기존 메서드 재사용)
455+ getByDayInWeekly (request , studyPlan , repeatRule );
493456
494457 if (request .getUntilDate () != null && !request .getUntilDate ().isEmpty ()) {
495458 try {
@@ -501,22 +464,52 @@ private void updateRepeatRule(RepeatRule repeatRule, StudyPlanRequest.RepeatRule
501464 }
502465 }
503466
467+ // RepeatRuleEmbeddable 생성 헬퍼 메서드 (중복 코드 제거)
468+ private RepeatRuleEmbeddable createRepeatRuleEmbeddable (StudyPlanRequest .RepeatRuleRequest request , LocalDateTime startDate ) {
469+ RepeatRuleEmbeddable embeddable = new RepeatRuleEmbeddable ();
470+ embeddable .setFrequency (request .getFrequency ());
471+ embeddable .setIntervalValue (request .getIntervalValue ());
472+
473+ // byDay 자동 설정 (오버로딩된 메서드 사용)
474+ getByDayInWeekly (request , startDate , embeddable );
475+
476+ if (request .getUntilDate () != null && !request .getUntilDate ().isEmpty ()) {
477+ try {
478+ LocalDate untilDate = LocalDate .parse (request .getUntilDate ());
479+ embeddable .setUntilDate (untilDate );
480+ } catch (Exception e ) {
481+ throw new CustomException (ErrorCode .INVALID_DATE_FORMAT );
482+ }
483+ }
484+
485+ return embeddable ;
486+ }
487+
504488 // ==================== 삭제 ===================
505489 @ Transactional
506- public void deleteStudyPlan (Long userId , Long planId , LocalDate selectedDate , ApplyScope applyScope ) {
490+ public StudyPlanDeleteResponse deleteStudyPlan (Long userId , Long planId , LocalDate selectedDate , ApplyScope applyScope ) {
507491 StudyPlan studyPlan = studyPlanRepository .findById (planId )
508492 .orElseThrow (() -> new CustomException (ErrorCode .PLAN_NOT_FOUND ));
509493
510494 validateUserAccess (studyPlan , userId );
511495
512- // 단발성 계획 삭제 (반복 룰이 null이거나 applyScope가 null인 경우)
496+ // 삭제 전 정보 조회
497+ StudyPlanResponse deletedPlan ;
498+
513499 if (studyPlan .getRepeatRule () == null || applyScope == null ) {
500+ // 단발성 계획
501+ deletedPlan = new StudyPlanResponse (studyPlan );
514502 studyPlanRepository .delete (studyPlan );
515- return ;
503+ } else {
504+ // 반복성 계획 - 가상 계획 조회
505+ deletedPlan = createVirtualPlanForDate (studyPlan , selectedDate );
506+ if (deletedPlan == null ) {
507+ throw new CustomException (ErrorCode .PLAN_NOT_FOUND );
508+ }
509+ deleteRepeatPlan (studyPlan , selectedDate , applyScope );
516510 }
517511
518- // 반복성 계획 삭제 - applyScope에 따른 처리
519- deleteRepeatPlan (studyPlan , selectedDate , applyScope );
512+ return new StudyPlanDeleteResponse (deletedPlan , applyScope );
520513 }
521514
522515 private void deleteRepeatPlan (StudyPlan studyPlan , LocalDate selectedDate , ApplyScope applyScope ) {
@@ -617,5 +610,30 @@ private void validateRepeatRuleDate(StudyPlan studyPlan, LocalDate untilDate) {
617610 throw new CustomException (ErrorCode .REPEAT_INVALID_UNTIL_DATE );
618611 }
619612 }
613+ // WEEKLY인 경우 빈 byDay 처리 메서드 (RepeatRule용)
614+ private void getByDayInWeekly (StudyPlanRequest .RepeatRuleRequest request , StudyPlan studyPlan , RepeatRule repeatRule ) {
615+ // byDay 설정 (WEEKLY 인 경우에만)
616+ if (request .getFrequency () == Frequency .WEEKLY ) {
617+ // 1. byDay가 없으면 시작일 요일을 자동으로 설정
618+ if (request .getByDay () == null || request .getByDay ().isEmpty ()) {
619+ DayOfWeek startDay = DayOfWeek .valueOf (studyPlan .getStartDate ().getDayOfWeek ().name ().substring (0 ,3 ));
620+ repeatRule .setByDay (List .of (startDay ));
621+ } else {
622+ // 2. byDay가 있다면 요청 값을 사용
623+ repeatRule .setByDay (request .getByDay ());
624+ }
625+ }
626+ }
627+ // WEEKLY인 경우 빈 byDay 처리 메서드 (RepeatRuleEmbeddable용 - 오버로딩)
628+ private void getByDayInWeekly (StudyPlanRequest .RepeatRuleRequest request , LocalDateTime startDate , RepeatRuleEmbeddable embeddable ) {
629+ if (request .getFrequency () == Frequency .WEEKLY ) {
630+ if (request .getByDay () == null || request .getByDay ().isEmpty ()) {
631+ DayOfWeek startDay = DayOfWeek .valueOf (startDate .getDayOfWeek ().name ().substring (0 , 3 ));
632+ embeddable .setByDay (List .of (startDay ));
633+ } else {
634+ embeddable .setByDay (request .getByDay ());
635+ }
636+ }
637+ }
620638
621639}
0 commit comments