Skip to content

Commit 13c6c36

Browse files
KSH0326jueunk617
andauthored
Feat: 플래너 조회, 생성, 수정 (#52) (#69)
* feat: 일자별 조회기능 구현 * feat: 기간별 계획 조회 * feat: 기간별 계획 조회 누락 기록 추가 * feat: 단일 수정, 이후도 모두 수정 구현 * feat: exception에 반복 룰 embeddable 추가 및 생성조회 수정 * feat: exception의 반복 룰 추가에 따른 수정기능 변경 --------- Co-authored-by: jueunk617 <[email protected]>
1 parent cf5330c commit 13c6c36

File tree

10 files changed

+586
-37
lines changed

10 files changed

+586
-37
lines changed
Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,89 @@
11
package com.back.domain.study.plan.controller;
22

3-
import com.back.domain.study.plan.dto.StudyPlanCreateRequest;
3+
import com.back.domain.study.plan.dto.StudyPlanRequest;
4+
import com.back.domain.study.plan.dto.StudyPlanListResponse;
45
import com.back.domain.study.plan.dto.StudyPlanResponse;
6+
import com.back.domain.study.plan.entity.StudyPlanException;
57
import com.back.domain.study.plan.service.StudyPlanService;
68
import com.back.global.common.dto.RsData;
9+
import com.back.global.security.CustomUserDetails;
710
import lombok.RequiredArgsConstructor;
11+
import org.springframework.format.annotation.DateTimeFormat;
812
import org.springframework.http.ResponseEntity;
913
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1014
import org.springframework.web.bind.annotation.*;
1115

16+
import java.time.LocalDate;
17+
import java.util.List;
18+
1219
@RestController
1320
@RequiredArgsConstructor
1421
@RequestMapping("/api/plans")
1522
public class StudyPlanController {
1623
private final StudyPlanService studyPlanService;
17-
24+
// ==================== 생성 ===================
1825
@PostMapping
1926
public ResponseEntity<RsData<StudyPlanResponse>> createStudyPlan(
2027
// 로그인 유저 정보 받기 @AuthenticationPrincipal CustomUserDetails user,
21-
@RequestBody StudyPlanCreateRequest request) {
28+
@RequestBody StudyPlanRequest request) {
2229
//커스텀 디테일 구현 시 사용 int userId = user.getId();
2330
Long userId = 1L; // 임시로 userId를 1로 설정
2431
StudyPlanResponse response = studyPlanService.createStudyPlan(userId, request);
2532
return ResponseEntity.ok(RsData.success("학습 계획이 성공적으로 생성되었습니다.", response));
2633
}
2734

35+
// ==================== 조회 ===================
36+
// 특정 날짜의 계획들 조회. date 형식: YYYY-MM-DD
37+
@GetMapping("/date/{date}")
38+
public ResponseEntity<RsData<StudyPlanListResponse>> getStudyPlansForDate(
39+
@AuthenticationPrincipal CustomUserDetails user,
40+
@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
41+
// 유저 아이디 추출. 지금은 임시값 적용
42+
// Long userId = user.getId();
43+
Long userId = 1L; // 임시로 userId를 1로 설정
44+
45+
List<StudyPlanResponse> plans = studyPlanService.getStudyPlansForDate(userId, date);
46+
StudyPlanListResponse response = new StudyPlanListResponse(date, plans, plans.size());
47+
48+
return ResponseEntity.ok(RsData.success("해당 날짜의 계획을 조회했습니다.", response));
49+
}
50+
51+
// 기간별 계획 조회. start, end 형식: YYYY-MM-DD
52+
@GetMapping
53+
public ResponseEntity<RsData<List<StudyPlanResponse>>> getStudyPlansForPeriod(
54+
// @AuthenticationPrincipal CustomUserDetails user,
55+
@RequestParam("start") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
56+
@RequestParam("end") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
57+
// Long userId = user.getId();
58+
Long userId = 1L; // 임시
59+
60+
List<StudyPlanResponse> plans = studyPlanService.getStudyPlansForPeriod(userId, startDate, endDate);
61+
62+
return ResponseEntity.ok(RsData.success("기간별 계획을 조회했습니다.", plans));
63+
}
64+
65+
66+
67+
// ==================== 수정 ===================
68+
// 플랜 아이디는 원본의 아이디를 받음
69+
// 가상인지 원본인지는 서비스에서 원본과 날짜를 대조해 판단
70+
// 수정 적용 범위를 쿼리 파라미터로 받음 (THIS_ONLY, FROM_THIS_DATE)
71+
@PutMapping("/{planId}")
72+
public ResponseEntity<RsData<StudyPlanResponse>> updateStudyPlan(
73+
// @AuthenticationPrincipal CustomUserDetails user,
74+
@PathVariable Long planId,
75+
@RequestBody StudyPlanRequest request,
76+
@RequestParam(required = false, defaultValue = "THIS_ONLY") StudyPlanException.ApplyScope applyScope) {
77+
// Long userId = user.getId();
78+
Long userId = 1L; // 임시
79+
80+
StudyPlanResponse response = studyPlanService.updateStudyPlan(userId, planId, request, applyScope);
81+
return ResponseEntity.ok(RsData.success("학습 계획이 성공적으로 수정되었습니다.", response));
82+
}
83+
84+
85+
86+
// ==================== 삭제 ===================
2887
@DeleteMapping("/{planId}")
2988
public ResponseEntity<RsData<Void>> deleteStudyPlan(@PathVariable Long planId) {
3089
//studyPlanService.deleteStudyPlan(planId);
@@ -33,5 +92,4 @@ public ResponseEntity<RsData<Void>> deleteStudyPlan(@PathVariable Long planId) {
3392

3493

3594

36-
3795
}
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+
import java.time.LocalDate;
9+
import java.util.List;
10+
11+
@Getter
12+
@Setter
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
public class StudyPlanListResponse {
16+
private LocalDate date;
17+
private List<StudyPlanResponse> plans;
18+
private int totalCount;
19+
}

src/main/java/com/back/domain/study/plan/dto/StudyPlanCreateRequest.java renamed to src/main/java/com/back/domain/study/plan/dto/StudyPlanRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
@Setter
1515
@NoArgsConstructor
1616
@AllArgsConstructor
17-
public class StudyPlanCreateRequest {
17+
public class StudyPlanRequest {
1818
private String subject;
1919

2020
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss")

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import lombok.NoArgsConstructor;
1111
import lombok.Setter;
1212

13+
import java.time.LocalDate;
1314
import java.time.LocalDateTime;
1415
import java.util.Arrays;
1516
import java.util.List;
@@ -31,9 +32,6 @@ public class StudyPlanResponse {
3132

3233
private Color color;
3334

34-
private Long parentPlanId;
35-
private List<StudyPlanResponse> childPlans;
36-
3735
// RepeatRule 정보
3836
private RepeatRuleResponse repeatRule;
3937

@@ -47,14 +45,14 @@ public static class RepeatRuleResponse {
4745
private String byDay; // "MON" 형태의 문자열
4846

4947
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss")
50-
private LocalDateTime until;
48+
private LocalDate untilDate;
5149

5250
public RepeatRuleResponse(com.back.domain.study.plan.entity.RepeatRule repeatRule) {
5351
if (repeatRule != null) {
5452
this.frequency = repeatRule.getFrequency();
5553
this.repeatInterval = repeatRule.getRepeatInterval();
5654
this.byDay = repeatRule.getByDay();
57-
this.until = repeatRule.getUntilDate();
55+
this.untilDate = repeatRule.getUntilDate();
5856
}
5957
}
6058

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import lombok.NoArgsConstructor;
88
import lombok.Setter;
99

10-
import java.time.LocalDateTime;
10+
import java.time.LocalDate;
1111

1212
@Entity
1313
@Getter
@@ -25,10 +25,9 @@ public class RepeatRule extends BaseEntity {
2525
@Column(name = "interval_value", nullable = false)
2626
private int RepeatInterval;
2727

28-
//필요 시 요일 지정. 여러 요일 지정 시 ,로 구분
29-
//현재는 요일 하나만 지정하는 형태로 구현
28+
//요일은 계획 날짜에 따라 자동 설정
3029
@Column(name = "by_day")
3130
private String byDay;
3231

33-
private LocalDateTime untilDate;
32+
private LocalDate untilDate;
3433
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.back.domain.study.plan.entity;
2+
3+
import jakarta.persistence.Embeddable;
4+
import jakarta.persistence.EnumType;
5+
import jakarta.persistence.Enumerated;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
import lombok.Setter;
10+
11+
import java.time.LocalDate;
12+
13+
@Embeddable
14+
@Getter
15+
@Setter
16+
@NoArgsConstructor
17+
@AllArgsConstructor
18+
public class RepeatRuleEmbeddable {
19+
@Enumerated(EnumType.STRING)
20+
private Frequency frequency;
21+
22+
private Integer intervalValue;
23+
private String byDay;
24+
private LocalDate untilDate; // LocalDateTime → LocalDate 변경
25+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import lombok.NoArgsConstructor;
88
import lombok.Setter;
99

10+
import java.time.LocalDate;
1011
import java.time.LocalDateTime;
1112

1213
@Entity
@@ -60,4 +61,13 @@ public enum ApplyScope {
6061
THIS_ONLY, // 이 날짜만
6162
FROM_THIS_DATE // 이 날짜부터 이후 모든 날짜
6263
}
64+
65+
@Embedded
66+
@AttributeOverrides({
67+
@AttributeOverride(name = "frequency", column = @Column(name = "modified_frequency")),
68+
@AttributeOverride(name = "intervalValue", column = @Column(name = "modified_repeat_interval")),
69+
@AttributeOverride(name = "byDay", column = @Column(name = "modified_by_day")),
70+
@AttributeOverride(name = "untilDate", column = @Column(name = "modified_until_date"))
71+
})
72+
private RepeatRuleEmbeddable modifiedRepeatRule;
6373
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.back.domain.study.plan.repository;
2+
3+
import com.back.domain.study.plan.entity.StudyPlanException;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
7+
import org.springframework.stereotype.Repository;
8+
9+
import java.time.LocalDateTime;
10+
import java.util.List;
11+
import java.util.Optional;
12+
13+
@Repository
14+
public interface StudyPlanExceptionRepository extends JpaRepository<StudyPlanException, Long> {
15+
// FROM_THIS_DATE 범위의 예외들 중 특정 날짜 이전의 예외 조회
16+
@Query("SELECT spe FROM StudyPlanException spe WHERE spe.studyPlan.id = :planId " +
17+
"AND spe.applyScope = :applyScope " +
18+
"AND spe.exceptionDate <= :targetDate " +
19+
"ORDER BY spe.exceptionDate DESC")
20+
List<StudyPlanException> findByStudyPlanIdAndApplyScopeAndExceptionDateBefore(
21+
@Param("planId") Long planId,
22+
@Param("applyScope") StudyPlanException.ApplyScope applyScope,
23+
@Param("targetDate") LocalDateTime targetDate);
24+
// 특정 계획의 특정 기간 동안(start~end)의 예외를 조회
25+
@Query("SELECT spe FROM StudyPlanException spe WHERE spe.studyPlan.id = :planId " +
26+
"AND spe.exceptionDate BETWEEN :startDate AND :endDate " +
27+
"ORDER BY spe.exceptionDate")
28+
List<StudyPlanException> findByStudyPlanIdAndExceptionDateBetween(@Param("planId") Long planId,
29+
@Param("startDate") LocalDateTime startDate,
30+
@Param("endDate") LocalDateTime endDate);
31+
// 특정 계획의 특정 날짜 예외 조회
32+
@Query("SELECT spe FROM StudyPlanException spe WHERE spe.studyPlan.id = :planId " +
33+
"AND DATE(spe.exceptionDate) = DATE(:targetDate)")
34+
Optional<StudyPlanException> findByPlanIdAndDate(@Param("planId") Long planId,
35+
@Param("targetDate") LocalDateTime targetDate);
36+
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import org.springframework.data.jpa.repository.JpaRepository;
55
import org.springframework.stereotype.Repository;
66

7-
@Repository
8-
public interface StudyPlanRepository extends JpaRepository<StudyPlan, Integer> {
7+
import java.util.List;
98

9+
@Repository
10+
public interface StudyPlanRepository extends JpaRepository<StudyPlan, Long> {
11+
List<StudyPlan> findByUserId(Long userId);
1012
}

0 commit comments

Comments
 (0)