Skip to content

Commit 4bb3c4d

Browse files
committed
feat: 삭제 기능 구현 및 타입 불일치 수정
1 parent 7179479 commit 4bb3c4d

File tree

7 files changed

+81
-11
lines changed

7 files changed

+81
-11
lines changed

src/main/java/com/back/domain/study/plan/controller/StudyPlanController.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.back.domain.study.plan.controller;
22

3+
import com.back.domain.study.plan.dto.StudyPlanDeleteRequest;
34
import com.back.domain.study.plan.dto.StudyPlanRequest;
45
import com.back.domain.study.plan.dto.StudyPlanListResponse;
56
import com.back.domain.study.plan.dto.StudyPlanResponse;
@@ -85,9 +86,15 @@ public ResponseEntity<RsData<StudyPlanResponse>> updateStudyPlan(
8586

8687
// ==================== 삭제 ===================
8788
@DeleteMapping("/{planId}")
88-
public ResponseEntity<RsData<Void>> deleteStudyPlan(@PathVariable Long planId) {
89-
//studyPlanService.deleteStudyPlan(planId);
90-
return ResponseEntity.ok(RsData.success("학습 계획이 성공적으로 삭제되었습니다.", null));
89+
public ResponseEntity<RsData<Void>> deleteStudyPlan(
90+
// @AuthenticationPrincipal CustomUserDetails user,
91+
@PathVariable Long planId,
92+
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate selectedDate,
93+
@RequestBody(required = false) StudyPlanDeleteRequest request) {
94+
Long userId = 1L; // 임시
95+
96+
studyPlanService.deleteStudyPlan(userId, planId, selectedDate, request);
97+
return ResponseEntity.ok(RsData.success("학습 계획이 성공적으로 삭제되었습니다."));
9198
}
9299

93100

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.back.domain.study.plan.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
import lombok.Setter;
7+
8+
@Getter
9+
@Setter
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
public class StudyPlanDeleteRequest {
13+
private DeleteScope deleteScope;
14+
15+
public enum DeleteScope {
16+
THIS_ONLY, // 이 날짜만
17+
FROM_THIS_DATE // 이 날짜부터 이후 모든 날짜
18+
}
19+
}

src/main/java/com/back/domain/study/plan/dto/StudyPlanResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static class RepeatRuleResponse {
4444
private Integer repeatInterval;
4545
private String byDay; // "MON" 형태의 문자열
4646

47-
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss")
47+
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
4848
private LocalDate untilDate;
4949

5050
public RepeatRuleResponse(com.back.domain.study.plan.entity.RepeatRule repeatRule) {

src/main/java/com/back/domain/study/plan/entity/RepeatRule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class RepeatRule extends BaseEntity {
2323
private Frequency frequency;
2424

2525
@Column(name = "interval_value", nullable = false)
26-
private int RepeatInterval;
26+
private int repeatInterval;
2727

2828
//요일은 계획 날짜에 따라 자동 설정
2929
@Column(name = "by_day")

src/main/java/com/back/domain/study/plan/entity/StudyPlanException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class StudyPlanException extends BaseEntity {
2626

2727
// 예외가 발생한 날짜
2828
@Column(name = "exception_date", nullable = false)
29-
private LocalDateTime exceptionDate;
29+
private LocalDate exceptionDate;
3030

3131
//예외 유형 (수정 / 삭제)
3232
@Enumerated(EnumType.STRING)

src/main/java/com/back/domain/study/plan/repository/StudyPlanExceptionRepository.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.springframework.data.repository.query.Param;
77
import org.springframework.stereotype.Repository;
88

9+
import java.time.LocalDate;
910
import java.time.LocalDateTime;
1011
import java.util.List;
1112
import java.util.Optional;
@@ -32,5 +33,5 @@ List<StudyPlanException> findByStudyPlanIdAndExceptionDateBetween(@Param("planId
3233
@Query("SELECT spe FROM StudyPlanException spe WHERE spe.studyPlan.id = :planId " +
3334
"AND DATE(spe.exceptionDate) = DATE(:targetDate)")
3435
Optional<StudyPlanException> findByPlanIdAndDate(@Param("planId") Long planId,
35-
@Param("targetDate") LocalDateTime targetDate);
36+
@Param("targetDate") LocalDate targetDate);
3637
}

src/main/java/com/back/domain/study/plan/service/StudyPlanService.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.back.domain.study.plan.service;
22

3+
import com.back.domain.study.plan.dto.StudyPlanDeleteRequest;
34
import com.back.domain.study.plan.dto.StudyPlanRequest;
45
import com.back.domain.study.plan.dto.StudyPlanResponse;
56
import com.back.domain.study.plan.entity.RepeatRule;
@@ -201,7 +202,7 @@ private boolean shouldRepeatOnDate(StudyPlan originalPlan, LocalDate targetDate)
201202
private StudyPlanException getEffectiveException(Long planId, LocalDate targetDate) {
202203
// 해당 날짜에 직접적인 예외가 있는지 확인
203204
Optional<StudyPlanException> directException = studyPlanExceptionRepository
204-
.findByPlanIdAndDate(planId, targetDate.atStartOfDay());
205+
.findByPlanIdAndDate(planId, targetDate);
205206
if (directException.isPresent()) {
206207
return directException.get();
207208
}
@@ -320,7 +321,7 @@ private UpdateType determineUpdateType(StudyPlan originalPlan, StudyPlanRequest
320321

321322
// 1-2. 반복 계획에서 다른 날짜인 경우 -> 기존 예외 확인
322323
Optional<StudyPlanException> existingException = studyPlanExceptionRepository
323-
.findByPlanIdAndDate(originalPlan.getId(), requestDate.atStartOfDay());
324+
.findByPlanIdAndDate(originalPlan.getId(), requestDate);
324325

325326
if (existingException.isPresent()) {
326327
return UpdateType.REPEAT_INSTANCE_UPDATE; // 기존 예외 수정
@@ -357,7 +358,7 @@ private StudyPlanResponse createRepeatException(StudyPlan originalPlan, StudyPla
357358

358359
StudyPlanException exception = new StudyPlanException();
359360
exception.setStudyPlan(originalPlan);
360-
exception.setExceptionDate(exceptionDate.atStartOfDay());
361+
exception.setExceptionDate(exceptionDate);
361362
exception.setExceptionType(StudyPlanException.ExceptionType.MODIFIED);
362363
exception.setApplyScope(applyScope); // 파라미터로 받은 applyScope
363364

@@ -396,7 +397,7 @@ private StudyPlanResponse updateExistingException(StudyPlan originalPlan, StudyP
396397
LocalDate exceptionDate = request.getStartDate().toLocalDate();
397398

398399
StudyPlanException existingException = studyPlanExceptionRepository
399-
.findByPlanIdAndDate(originalPlan.getId(), exceptionDate.atStartOfDay())
400+
.findByPlanIdAndDate(originalPlan.getId(), exceptionDate)
400401
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND));
401402

402403
// 기존 예외 정보 업데이트
@@ -449,7 +450,49 @@ private void updateRepeatRule(RepeatRule repeatRule, StudyPlanRequest.RepeatRule
449450
}
450451

451452
// ==================== 삭제 ===================
453+
@Transactional
454+
public void deleteStudyPlan(Long userId, Long planId, LocalDate selectedDate, StudyPlanDeleteRequest request) {
455+
StudyPlan studyPlan = studyPlanRepository.findById(planId)
456+
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND));
457+
458+
validateUserAccess(studyPlan, userId);
452459

460+
// 단발성 계획 삭제 (request가 null이거나 deleteScope가 없는 경우)
461+
if (studyPlan.getRepeatRule() == null || request == null || request.getDeleteScope() == null) {
462+
studyPlanRepository.delete(studyPlan);
463+
return;
464+
}
465+
466+
// 반복성 계획 삭제 - deleteScope에 따른 처리
467+
deleteRepeatPlan(studyPlan, selectedDate, request.getDeleteScope());
468+
}
469+
470+
private void deleteRepeatPlan(StudyPlan studyPlan, LocalDate selectedDate, StudyPlanDeleteRequest.DeleteScope deleteScope) {
471+
switch (deleteScope) {
472+
case FROM_THIS_DATE:
473+
// 원본 날짜부터 삭제하는 경우 = 전체 계획 삭제
474+
if (selectedDate.equals(studyPlan.getStartDate().toLocalDate())) {
475+
studyPlanRepository.delete(studyPlan); // CASCADE로 RepeatRule, Exception 모두 삭제
476+
} else {
477+
// 중간 날짜부터 삭제하는 경우 = untilDate 수정
478+
RepeatRule repeatRule = studyPlan.getRepeatRule();
479+
LocalDate newUntilDate = selectedDate.minusDays(1);
480+
repeatRule.setUntilDate(newUntilDate);
481+
studyPlanRepository.save(studyPlan);
482+
}
483+
break;
484+
485+
case THIS_ONLY:
486+
// 선택한 날짜만 삭제 - 예외 생성
487+
StudyPlanException exception = new StudyPlanException();
488+
exception.setStudyPlan(studyPlan);
489+
exception.setExceptionDate(selectedDate);
490+
exception.setExceptionType(StudyPlanException.ExceptionType.DELETED);
491+
exception.setApplyScope(StudyPlanException.ApplyScope.THIS_ONLY);
492+
studyPlanExceptionRepository.save(exception);
493+
break;
494+
}
495+
}
453496

454497
// ==================== 유틸 ===================
455498
// 인가 (작성자 일치 확인)

0 commit comments

Comments
 (0)