From 5477cb9269085fe279411d2d789eda7f059294be Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Thu, 28 Mar 2024 04:07:46 +0900 Subject: [PATCH 1/9] =?UTF-8?q?rename:=20studyPlan=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20plan=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan/business/service/PlanService.java | 4 ++-- .../service/StudyPlanFacadeService.java | 8 +++---- .../controller/PlanController.java} | 18 +++++++-------- .../dto/request/PlanCreateRequest.java} | 4 ++-- .../dto/request/PlanReadConditionRequest.java | 2 +- .../dto/request/RecurringOptionRequest.java | 2 +- .../dto/response/PlanReadResponse.java | 23 +++++++++++++++++++ .../dto/response/StudyPlanReadResponse.java | 23 ------------------- 8 files changed, 41 insertions(+), 43 deletions(-) rename src/main/java/com/flytrap/venusplanner/api/{study_plan => plan}/business/service/StudyPlanFacadeService.java (80%) rename src/main/java/com/flytrap/venusplanner/api/{study_plan/presentation/controller/StudyPlanController.java => plan/presentation/controller/PlanController.java} (70%) rename src/main/java/com/flytrap/venusplanner/api/{study_plan/presentation/dto/request/StudyPlanCreateRequest.java => plan/presentation/dto/request/PlanCreateRequest.java} (92%) rename src/main/java/com/flytrap/venusplanner/api/{study_plan => plan}/presentation/dto/request/PlanReadConditionRequest.java (76%) rename src/main/java/com/flytrap/venusplanner/api/{study_plan => plan}/presentation/dto/request/RecurringOptionRequest.java (90%) create mode 100644 src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/response/PlanReadResponse.java delete mode 100644 src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/response/StudyPlanReadResponse.java diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java index b951b7f..43ba195 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java @@ -4,7 +4,7 @@ import com.flytrap.venusplanner.api.plan.infrastructure.repository.PlanRepository; import com.flytrap.venusplanner.api.plan_category.domain.PlanCategory; import com.flytrap.venusplanner.api.study.domain.Study; -import com.flytrap.venusplanner.api.study_plan.presentation.dto.request.StudyPlanCreateRequest; +import com.flytrap.venusplanner.api.plan.presentation.dto.request.PlanCreateRequest; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -17,7 +17,7 @@ public class PlanService { private final PlanRepository planRepository; - public Long savePlan(Study study, PlanCategory planCategory, StudyPlanCreateRequest request) { + public Long savePlan(Study study, PlanCategory planCategory, PlanCreateRequest request) { //TODO: 반복 옵션 설정시 DB에 여러 plan 저장 로직 추가 Plan plan = request.toEntity(study, planCategory); planRepository.save(plan); diff --git a/src/main/java/com/flytrap/venusplanner/api/study_plan/business/service/StudyPlanFacadeService.java b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java similarity index 80% rename from src/main/java/com/flytrap/venusplanner/api/study_plan/business/service/StudyPlanFacadeService.java rename to src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java index c42e80d..3fddf73 100644 --- a/src/main/java/com/flytrap/venusplanner/api/study_plan/business/service/StudyPlanFacadeService.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java @@ -1,13 +1,11 @@ -package com.flytrap.venusplanner.api.study_plan.business.service; +package com.flytrap.venusplanner.api.plan.business.service; -import com.flytrap.venusplanner.api.plan.business.service.PlanService; import com.flytrap.venusplanner.api.plan.domain.Plan; +import com.flytrap.venusplanner.api.plan.presentation.dto.request.PlanCreateRequest; import com.flytrap.venusplanner.api.plan_category.business.service.PlanCategoryService; import com.flytrap.venusplanner.api.plan_category.domain.PlanCategory; -import com.flytrap.venusplanner.api.study.business.service.StudyService; +import com.flytrap.venusplanner.api.study.business.service.StudyValid; import com.flytrap.venusplanner.api.study.domain.Study; -import com.flytrap.venusplanner.api.study_plan.presentation.dto.request.StudyPlanCreateRequest; -import com.flytrap.venusplanner.api.study_plan.presentation.dto.response.StudyPlanReadResponse; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/controller/StudyPlanController.java b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/controller/PlanController.java similarity index 70% rename from src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/controller/StudyPlanController.java rename to src/main/java/com/flytrap/venusplanner/api/plan/presentation/controller/PlanController.java index 9f07830..d65c783 100644 --- a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/controller/StudyPlanController.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/controller/PlanController.java @@ -1,10 +1,10 @@ -package com.flytrap.venusplanner.api.study_plan.presentation.controller; +package com.flytrap.venusplanner.api.plan.presentation.controller; import com.flytrap.venusplanner.api.plan.domain.Plan; -import com.flytrap.venusplanner.api.study_plan.business.service.StudyPlanFacadeService; -import com.flytrap.venusplanner.api.study_plan.presentation.dto.request.PlanReadConditionRequest; -import com.flytrap.venusplanner.api.study_plan.presentation.dto.request.StudyPlanCreateRequest; -import com.flytrap.venusplanner.api.study_plan.presentation.dto.response.StudyPlanReadResponse; +import com.flytrap.venusplanner.api.plan.presentation.dto.request.PlanReadConditionRequest; +import com.flytrap.venusplanner.api.plan.presentation.dto.request.PlanCreateRequest; +import com.flytrap.venusplanner.api.plan.presentation.dto.response.PlanReadResponse; +import com.flytrap.venusplanner.api.plan.business.service.StudyPlanFacadeService; import jakarta.validation.Valid; import java.util.List; import lombok.RequiredArgsConstructor; @@ -20,13 +20,13 @@ @RestController @RequiredArgsConstructor -public class StudyPlanController { +public class PlanController { private final StudyPlanFacadeService studyPlanFacadeService; @PostMapping("/api/v1/studies/{studyId}/plans") public ResponseEntity createPlan(@PathVariable Long studyId, - @Valid @RequestBody StudyPlanCreateRequest request) { + @Valid @RequestBody PlanCreateRequest request) { Long memberId = 1L; Long planId = studyPlanFacadeService.savePlan(studyId, request); @@ -35,13 +35,13 @@ public ResponseEntity createPlan(@PathVariable Long studyId, } @GetMapping("/api/v1/studies/{studyId}/plans") - public ResponseEntity> readPlans( + public ResponseEntity> readPlans( @PathVariable Long studyId, @Valid @ModelAttribute PlanReadConditionRequest params) { List studyPlans = studyPlanFacadeService.findAllBy(studyId, params.year(), params.month()); return ResponseEntity.ok() - .body(StudyPlanReadResponse.from(studyPlans)); + .body(PlanReadResponse.from(studyPlans)); } @DeleteMapping("/api/v1/studies/{studyId}/plans/{planId}") diff --git a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/StudyPlanCreateRequest.java b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/PlanCreateRequest.java similarity index 92% rename from src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/StudyPlanCreateRequest.java rename to src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/PlanCreateRequest.java index 8fdd45c..f0c4a62 100644 --- a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/StudyPlanCreateRequest.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/PlanCreateRequest.java @@ -1,4 +1,4 @@ -package com.flytrap.venusplanner.api.study_plan.presentation.dto.request; +package com.flytrap.venusplanner.api.plan.presentation.dto.request; import com.flytrap.venusplanner.api.plan.domain.Plan; import com.flytrap.venusplanner.api.plan.domain.RecurringOption; @@ -10,7 +10,7 @@ import java.time.Instant; import java.util.Optional; -public record StudyPlanCreateRequest( +public record PlanCreateRequest( @NotNull Long categoryId, diff --git a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/PlanReadConditionRequest.java b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/PlanReadConditionRequest.java similarity index 76% rename from src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/PlanReadConditionRequest.java rename to src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/PlanReadConditionRequest.java index 162c3a3..416ae8c 100644 --- a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/PlanReadConditionRequest.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/PlanReadConditionRequest.java @@ -1,4 +1,4 @@ -package com.flytrap.venusplanner.api.study_plan.presentation.dto.request; +package com.flytrap.venusplanner.api.plan.presentation.dto.request; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; diff --git a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/RecurringOptionRequest.java b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/RecurringOptionRequest.java similarity index 90% rename from src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/RecurringOptionRequest.java rename to src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/RecurringOptionRequest.java index e704ee3..90ad8ce 100644 --- a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/request/RecurringOptionRequest.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/request/RecurringOptionRequest.java @@ -1,4 +1,4 @@ -package com.flytrap.venusplanner.api.study_plan.presentation.dto.request; +package com.flytrap.venusplanner.api.plan.presentation.dto.request; import com.flytrap.venusplanner.api.plan.domain.EndOption; import com.flytrap.venusplanner.api.plan.domain.Frequency; diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/response/PlanReadResponse.java b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/response/PlanReadResponse.java new file mode 100644 index 0000000..2f840d5 --- /dev/null +++ b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/dto/response/PlanReadResponse.java @@ -0,0 +1,23 @@ +package com.flytrap.venusplanner.api.plan.presentation.dto.response; + +import com.flytrap.venusplanner.api.plan.domain.Plan; +import java.time.Instant; +import java.util.List; + +public record PlanReadResponse( + Long planId, + Long categoryId, + String title, + Instant startTime, + Instant endTime +) { + public static List from(List plans) { + return plans.stream() + .map(PlanReadResponse::from) + .toList(); + } + + private static PlanReadResponse from(Plan plan) { + return new PlanReadResponse(plan.getId(), plan.getPlanCategory().getId(), plan.getTitle(), plan.getStartTime(), plan.getEndTime()); + } +} diff --git a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/response/StudyPlanReadResponse.java b/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/response/StudyPlanReadResponse.java deleted file mode 100644 index c3e7eb3..0000000 --- a/src/main/java/com/flytrap/venusplanner/api/study_plan/presentation/dto/response/StudyPlanReadResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.flytrap.venusplanner.api.study_plan.presentation.dto.response; - -import com.flytrap.venusplanner.api.plan.domain.Plan; -import java.time.Instant; -import java.util.List; - -public record StudyPlanReadResponse( - Long planId, - Long categoryId, - String title, - Instant startTime, - Instant endTime -) { - public static List from(List plans) { - return plans.stream() - .map(StudyPlanReadResponse::from) - .toList(); - } - - private static StudyPlanReadResponse from(Plan plan) { - return new StudyPlanReadResponse(plan.getId(), plan.getPlanCategory().getId(), plan.getTitle(), plan.getStartTime(), plan.getEndTime()); - } -} From 1444372b34cc8d9f9c87fb916d59ed70fe3b49b5 Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Thu, 28 Mar 2024 04:08:12 +0900 Subject: [PATCH 2/9] =?UTF-8?q?refactor:=20studyValid=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/plan/business/service/StudyPlanFacadeService.java | 8 ++++---- .../api/study/business/service/StudyService.java | 3 ++- .../api/study/business/service/StudyValid.java | 7 +++++++ 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyValid.java diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java index 3fddf73..e9aab24 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java @@ -16,20 +16,20 @@ @Transactional(readOnly = true) public class StudyPlanFacadeService { - private final StudyService studyService; + private final StudyValid studyValid; private final PlanCategoryService planCategoryService; private final PlanService planService; @Transactional - public Long savePlan(Long studyId, StudyPlanCreateRequest request) { - Study study = studyService.findById(studyId); + public Long savePlan(Long studyId, PlanCreateRequest request) { + Study study = studyValid.findById(studyId); PlanCategory planCategory = planCategoryService.findById(request.categoryId()); return planService.savePlan(study, planCategory, request); } @Transactional public List findAllBy(Long studyId, int year, int month) { - Study study = studyService.findById(studyId); + Study study = studyValid.findById(studyId); List plans = planService.findAllByStudyIdAndYearAndMonth(studyId, year, month); return plans; diff --git a/src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyService.java b/src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyService.java index 50ae1eb..c6850c5 100644 --- a/src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyService.java +++ b/src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyService.java @@ -9,7 +9,7 @@ @Service @RequiredArgsConstructor @Transactional(readOnly = true) -public class StudyService { +public class StudyService implements StudyValid { private final StudyRepository studyRepository; @@ -18,6 +18,7 @@ public Study saveStudy(Study study) { return studyRepository.save(study); } + @Override public Study findById(Long studyId) { //TODO: optional null 처리 return studyRepository.findById(studyId).get(); diff --git a/src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyValid.java b/src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyValid.java new file mode 100644 index 0000000..1aca55c --- /dev/null +++ b/src/main/java/com/flytrap/venusplanner/api/study/business/service/StudyValid.java @@ -0,0 +1,7 @@ +package com.flytrap.venusplanner.api.study.business.service; + +import com.flytrap.venusplanner.api.study.domain.Study; + +public interface StudyValid { + Study findById(Long id); +} From 49eab293671d3ae5f857d548ae0e42248f1ff608 Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Mon, 11 Mar 2024 19:06:56 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=EC=A2=85=EB=A3=8C=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EA=B4=80=EB=A0=A8=20=EA=B3=84=EC=82=B0=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=B0=8F=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/service/EndOptionCalculate.java | 8 ++++ .../api/plan/domain/Frequency.java | 43 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/flytrap/venusplanner/api/plan/business/service/EndOptionCalculate.java diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/EndOptionCalculate.java b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/EndOptionCalculate.java new file mode 100644 index 0000000..a21a6d8 --- /dev/null +++ b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/EndOptionCalculate.java @@ -0,0 +1,8 @@ +package com.flytrap.venusplanner.api.plan.business.service; + +import java.time.Instant; + +public interface EndOptionCalculate { + Instant calculateEndDate(Instant startDate, int count); + int calculateCount(Instant startDate, Instant endDate); +} diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java index 89cefb1..69fc937 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java @@ -1,5 +1,44 @@ package com.flytrap.venusplanner.api.plan.domain; -public enum Frequency { - WEEKLY, MONTHLY, YEARLY +import com.flytrap.venusplanner.api.plan.business.service.EndOptionCalculate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +public enum Frequency implements EndOptionCalculate { + WEEKLY { + @Override + public Instant calculateEndDate(Instant startDate, int count) { + return startDate.plus((count - 1) * 7, ChronoUnit.DAYS); + } + + @Override + public int calculateCount(Instant startDate, Instant endDate) { + long weeksBetween = ChronoUnit.WEEKS.between(startDate, endDate); + return (int) weeksBetween + 1; + } + }, + MONTHLY { + @Override + public Instant calculateEndDate(Instant startDate, int count) { + return startDate.plus(count - 1, ChronoUnit.MONTHS); + } + + @Override + public int calculateCount(Instant startDate, Instant endDate) { + long monthsBetween = ChronoUnit.MONTHS.between(startDate, endDate); + return (int) monthsBetween + 1; + } + }, + YEARLY { + @Override + public Instant calculateEndDate(Instant startDate, int count) { + return startDate.plus(count - 1, ChronoUnit.YEARS); + } + + @Override + public int calculateCount(Instant startDate, Instant endDate) { + long yearsBetween = ChronoUnit.YEARS.between(startDate, endDate); + return (int) yearsBetween + 1; + } + }; } From ce80aef6d533ec0f2679f08117301f3975f517c2 Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Tue, 12 Mar 2024 14:25:40 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20`Plan`=20=EC=A0=80=EC=9E=A5=20?= =?UTF-8?q?=EC=A0=84=20=EB=B0=98=EB=B3=B5=EC=98=B5=EC=85=98=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=97=B0=EC=82=B0=20=EB=A1=9C=EC=A7=81=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/flytrap/venusplanner/api/plan/domain/Plan.java | 9 ++++++++- .../venusplanner/api/plan/domain/RecurringOption.java | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Plan.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Plan.java index 428b2da..4e68383 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Plan.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Plan.java @@ -67,7 +67,6 @@ private Plan(Study study, PlanCategory planCategory, RecurringOption recurringOp this.notificationTime = notificationTime; } - @PrePersist @PreUpdate public void validateTitle() { final String DEFAULT_TILE = "새로운 일정"; @@ -76,4 +75,12 @@ public void validateTitle() { title = DEFAULT_TILE; } } + + @PrePersist + private void beforeSave() { + if (recurringOption != null) { + recurringOption.calculate(startTime); + } + validateTitle(); + } } diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java index 8996d54..8cad993 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java @@ -40,4 +40,13 @@ public RecurringOption(Frequency frequency, EndOption endOption, this.recurrenceCount = recurrenceCount; this.endDate = endDate; } + + public void calculate(Instant startDate) { + //TODO:(의견1) endOption에서 계산 로직 실행 + if (endOption == EndOption.COUNT && recurrenceCount != null) { + this.endDate = frequency.calculateEndDate(startDate, recurrenceCount); + } else if (endOption == EndOption.DATE && endDate != null) { + this.recurrenceCount = frequency.calculateCount(startDate, endDate); + } + } } From 76509f5f946a4810fd3c1404cab54287ad41693e Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Thu, 28 Mar 2024 04:44:25 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=EC=97=B0,=EC=9B=94=20=EC=97=B0?= =?UTF-8?q?=EC=82=B0=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EB=B3=80=ED=99=98=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/plan/domain/Frequency.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java index 69fc937..b5d824e 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java @@ -2,6 +2,8 @@ import com.flytrap.venusplanner.api.plan.business.service.EndOptionCalculate; import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; public enum Frequency implements EndOptionCalculate { @@ -20,24 +22,32 @@ public int calculateCount(Instant startDate, Instant endDate) { MONTHLY { @Override public Instant calculateEndDate(Instant startDate, int count) { - return startDate.plus(count - 1, ChronoUnit.MONTHS); + ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); + ZonedDateTime zdtEnd = zdtStart.plusMonths(count - 1); + return zdtEnd.toInstant(); } @Override public int calculateCount(Instant startDate, Instant endDate) { - long monthsBetween = ChronoUnit.MONTHS.between(startDate, endDate); + ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); + ZonedDateTime zdtEnd = endDate.atZone(ZoneId.systemDefault()); + long monthsBetween = ChronoUnit.MONTHS.between(zdtStart, zdtEnd); return (int) monthsBetween + 1; } }, YEARLY { @Override public Instant calculateEndDate(Instant startDate, int count) { - return startDate.plus(count - 1, ChronoUnit.YEARS); + ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); + ZonedDateTime zdtEnd = zdtStart.plusYears(count - 1); + return zdtEnd.toInstant(); } @Override public int calculateCount(Instant startDate, Instant endDate) { - long yearsBetween = ChronoUnit.YEARS.between(startDate, endDate); + ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); + ZonedDateTime zdtEnd = endDate.atZone(ZoneId.systemDefault()); + long yearsBetween = ChronoUnit.YEARS.between(zdtStart, zdtEnd); return (int) yearsBetween + 1; } }; From ef232b35d45be9c7732abe502848c4dabc9993f5 Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Thu, 28 Mar 2024 04:47:54 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=EC=A3=BC=20=EB=B0=98=EB=B3=B5=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=ED=83=80=EC=9E=85=20=EB=B3=80=ED=99=98=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flytrap/venusplanner/api/plan/domain/Frequency.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java index b5d824e..d16a4ac 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java @@ -10,12 +10,16 @@ public enum Frequency implements EndOptionCalculate { WEEKLY { @Override public Instant calculateEndDate(Instant startDate, int count) { - return startDate.plus((count - 1) * 7, ChronoUnit.DAYS); + ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); + ZonedDateTime zdtEnd = zdtStart.plusWeeks(count - 1); + return zdtEnd.toInstant(); } @Override public int calculateCount(Instant startDate, Instant endDate) { - long weeksBetween = ChronoUnit.WEEKS.between(startDate, endDate); + ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); + ZonedDateTime zdtEnd = endDate.atZone(ZoneId.systemDefault()); + long weeksBetween = ChronoUnit.WEEKS.between(zdtStart, zdtEnd); return (int) weeksBetween + 1; } }, From ad6baca47c82ea209b822878e7d44ec20e1ce896 Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Thu, 28 Mar 2024 05:55:07 +0900 Subject: [PATCH 7/9] =?UTF-8?q?refactor:=20=EC=8B=9C=EA=B0=84=20=EB=B3=80?= =?UTF-8?q?=ED=99=98=20=EC=9C=A0=ED=8B=B8=ED=95=A8=EC=88=98=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../venusplanner/api/plan/domain/Frequency.java | 13 ++++++------- .../venusplanner/api/plan/util/DateTimeUtils.java | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/flytrap/venusplanner/api/plan/util/DateTimeUtils.java diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java index d16a4ac..b66331f 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java @@ -1,6 +1,7 @@ package com.flytrap.venusplanner.api.plan.domain; import com.flytrap.venusplanner.api.plan.business.service.EndOptionCalculate; +import com.flytrap.venusplanner.api.plan.util.DateTimeUtils; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -10,17 +11,15 @@ public enum Frequency implements EndOptionCalculate { WEEKLY { @Override public Instant calculateEndDate(Instant startDate, int count) { - ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); - ZonedDateTime zdtEnd = zdtStart.plusWeeks(count - 1); - return zdtEnd.toInstant(); + ZonedDateTime zdtStart = DateTimeUtils.toZonedDateTime(startDate); + return DateTimeUtils.toInstant(zdtStart.plusWeeks(count - 1)); } @Override public int calculateCount(Instant startDate, Instant endDate) { - ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); - ZonedDateTime zdtEnd = endDate.atZone(ZoneId.systemDefault()); - long weeksBetween = ChronoUnit.WEEKS.between(zdtStart, zdtEnd); - return (int) weeksBetween + 1; + ZonedDateTime zdtStart = DateTimeUtils.toZonedDateTime(startDate); + ZonedDateTime zdtEnd = DateTimeUtils.toZonedDateTime(endDate); + return (int) ChronoUnit.WEEKS.between(zdtStart, zdtEnd) + 1; } }, MONTHLY { diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/util/DateTimeUtils.java b/src/main/java/com/flytrap/venusplanner/api/plan/util/DateTimeUtils.java new file mode 100644 index 0000000..5762779 --- /dev/null +++ b/src/main/java/com/flytrap/venusplanner/api/plan/util/DateTimeUtils.java @@ -0,0 +1,15 @@ +package com.flytrap.venusplanner.api.plan.util; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +public class DateTimeUtils { + public static ZonedDateTime toZonedDateTime(Instant instant) { + return instant.atZone(ZoneId.systemDefault()); + } + + public static Instant toInstant(ZonedDateTime zonedDateTime) { + return zonedDateTime.toInstant(); + } +} From df6fcb3a666bf905dc7ba081b85a4cec26c1f335 Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Thu, 28 Mar 2024 05:58:23 +0900 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20=EB=B0=98=EB=B3=B5=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=A0=84=EC=B2=B4=20=EC=82=AD=EC=A0=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/plan/business/service/PlanService.java | 15 +++++++++++++++ .../business/service/StudyPlanFacadeService.java | 9 +++++++-- .../infrastructure/repository/PlanRepository.java | 2 ++ .../presentation/controller/PlanController.java | 6 ++++-- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java index 43ba195..619c79b 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java @@ -1,7 +1,9 @@ package com.flytrap.venusplanner.api.plan.business.service; import com.flytrap.venusplanner.api.plan.domain.Plan; +import com.flytrap.venusplanner.api.plan.domain.RecurringOption; import com.flytrap.venusplanner.api.plan.infrastructure.repository.PlanRepository; +import com.flytrap.venusplanner.api.plan.infrastructure.repository.RecurringOptionRepository; import com.flytrap.venusplanner.api.plan_category.domain.PlanCategory; import com.flytrap.venusplanner.api.study.domain.Study; import com.flytrap.venusplanner.api.plan.presentation.dto.request.PlanCreateRequest; @@ -16,6 +18,7 @@ public class PlanService { private final PlanRepository planRepository; + private final RecurringOptionRepository recurringOptionRepository; public Long savePlan(Study study, PlanCategory planCategory, PlanCreateRequest request) { //TODO: 반복 옵션 설정시 DB에 여러 plan 저장 로직 추가 @@ -36,4 +39,16 @@ public void deleteById(Long planId) { //TODO: plan이 없을 때 예외처리 planRepository.deleteById(planId); } + + public void deleteAllByRecurringId(Long planId) { + //Todo: plan 없을 때 예외처리 + Plan plan = planRepository.findById(planId).get(); + RecurringOption recurringOption = plan.getRecurringOption(); + if (recurringOption != null) { + planRepository.deleteAllByRecurringOptionId(recurringOption.getId()); + recurringOptionRepository.deleteById(recurringOption.getId()); + } else { + planRepository.deleteById(planId); + } + } } diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java index e9aab24..5c60ee0 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/StudyPlanFacadeService.java @@ -35,7 +35,12 @@ public List findAllBy(Long studyId, int year, int month) { return plans; } - public void deleteById(Long planId) { - planService.deleteById(planId); + @Transactional + public void delete(Long planId, boolean applyAll) { + if (applyAll) { + planService.deleteAllByRecurringId(planId); + } else { + planService.deleteById(planId); + } } } diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/infrastructure/repository/PlanRepository.java b/src/main/java/com/flytrap/venusplanner/api/plan/infrastructure/repository/PlanRepository.java index 99b5665..f4891f6 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/infrastructure/repository/PlanRepository.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/infrastructure/repository/PlanRepository.java @@ -13,4 +13,6 @@ public interface PlanRepository extends JpaRepository { "OR (YEAR(p.end_time) = :year AND MONTH(p.end_time) = :month)", nativeQuery = true) List findAllByStudyIdAndYearAndMonth(Long studyId, int year, int month); + + void deleteAllByRecurringOptionId(Long recurringOptionId); } diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/presentation/controller/PlanController.java b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/controller/PlanController.java index d65c783..898dced 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/presentation/controller/PlanController.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/presentation/controller/PlanController.java @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -46,9 +47,10 @@ public ResponseEntity> readPlans( @DeleteMapping("/api/v1/studies/{studyId}/plans/{planId}") public ResponseEntity deletePlan( - @PathVariable Long planId + @PathVariable Long planId, + @RequestParam boolean applyAll ) { - studyPlanFacadeService.deleteById(planId); + studyPlanFacadeService.delete(planId, applyAll); return ResponseEntity.ok() .build(); From 962ddcfb35fdf8acd7306c4c1e69c11ba3b5dbf4 Mon Sep 17 00:00:00 2001 From: jaea-kim Date: Thu, 28 Mar 2024 08:19:08 +0900 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=EB=B0=98=EB=B3=B5=20=EC=88=98?= =?UTF-8?q?=EB=A7=8C=ED=81=BC=20plan=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=A0=80=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan/business/service/PlanService.java | 42 +++++++++++++++++-- .../api/plan/domain/Frequency.java | 16 +++++-- .../api/plan/domain/RecurringOption.java | 4 ++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java index 619c79b..d3ab494 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/business/service/PlanService.java @@ -4,9 +4,14 @@ import com.flytrap.venusplanner.api.plan.domain.RecurringOption; import com.flytrap.venusplanner.api.plan.infrastructure.repository.PlanRepository; import com.flytrap.venusplanner.api.plan.infrastructure.repository.RecurringOptionRepository; +import com.flytrap.venusplanner.api.plan.presentation.dto.request.PlanCreateRequest; +import com.flytrap.venusplanner.api.plan.util.DateTimeUtils; import com.flytrap.venusplanner.api.plan_category.domain.PlanCategory; import com.flytrap.venusplanner.api.study.domain.Study; -import com.flytrap.venusplanner.api.plan.presentation.dto.request.PlanCreateRequest; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,13 +26,45 @@ public class PlanService { private final RecurringOptionRepository recurringOptionRepository; public Long savePlan(Study study, PlanCategory planCategory, PlanCreateRequest request) { - //TODO: 반복 옵션 설정시 DB에 여러 plan 저장 로직 추가 Plan plan = request.toEntity(study, planCategory); planRepository.save(plan); + if (plan.getRecurringOption() != null) { + List recurringPlan = createPlansWithRecurringPlan(plan); + planRepository.saveAll(recurringPlan); + } + return plan.getId(); } + private List createPlansWithRecurringPlan(Plan planTemplate) { + int recurrenceCount = planTemplate.getRecurringOption().getRecurrenceCount(); + ZonedDateTime startTimeZDT = DateTimeUtils.toZonedDateTime(planTemplate.getStartTime()); + ZonedDateTime endTimeZDT = DateTimeUtils.toZonedDateTime(planTemplate.getEndTime()); + ChronoUnit chronoUnit = planTemplate.getRecurringOption().getFrequency().getChronoUnit(); + + List createdPlans = new ArrayList<>(); + for (int i = 1; i < recurrenceCount; i++) { + Instant startTime = DateTimeUtils.toInstant(startTimeZDT.plus(i, chronoUnit)); + Instant endTime = DateTimeUtils.toInstant(endTimeZDT.plus(i, chronoUnit)); + + Plan newPlan = Plan.builder() + .study(planTemplate.getStudy()) + .planCategory(planTemplate.getPlanCategory()) + .recurringOption(planTemplate.getRecurringOption()) + .title(planTemplate.getTitle()) + .description(planTemplate.getDescription()) + .startTime(startTime) + .endTime(endTime) + .notificationTime(planTemplate.getNotificationTime()) + .build(); + + createdPlans.add(planRepository.save(newPlan)); + } + + return createdPlans; + } + public List findAllByStudyIdAndYearAndMonth(Long studyId, int year, int month) { return planRepository.findAllByStudyIdAndYearAndMonth(studyId, year, month); } @@ -35,7 +72,6 @@ public List findAllByStudyIdAndYearAndMonth(Long studyId, int year, int mo @Transactional public void deleteById(Long planId) { //TODO: 멤버의 권한 검증 로직 - //TODO: 반복옵션 전체 삭제 여부 //TODO: plan이 없을 때 예외처리 planRepository.deleteById(planId); } diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java index b66331f..a6aaa88 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/Frequency.java @@ -8,7 +8,7 @@ import java.time.temporal.ChronoUnit; public enum Frequency implements EndOptionCalculate { - WEEKLY { + WEEKLY(ChronoUnit.WEEKS) { @Override public Instant calculateEndDate(Instant startDate, int count) { ZonedDateTime zdtStart = DateTimeUtils.toZonedDateTime(startDate); @@ -22,7 +22,7 @@ public int calculateCount(Instant startDate, Instant endDate) { return (int) ChronoUnit.WEEKS.between(zdtStart, zdtEnd) + 1; } }, - MONTHLY { + MONTHLY(ChronoUnit.MONTHS) { @Override public Instant calculateEndDate(Instant startDate, int count) { ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); @@ -38,7 +38,7 @@ public int calculateCount(Instant startDate, Instant endDate) { return (int) monthsBetween + 1; } }, - YEARLY { + YEARLY(ChronoUnit.YEARS) { @Override public Instant calculateEndDate(Instant startDate, int count) { ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); @@ -54,4 +54,14 @@ public int calculateCount(Instant startDate, Instant endDate) { return (int) yearsBetween + 1; } }; + + private final ChronoUnit chronoUnit; + + Frequency(ChronoUnit chronoUnit) { + this.chronoUnit = chronoUnit; + } + + public ChronoUnit getChronoUnit() { + return chronoUnit; + } } diff --git a/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java b/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java index 8cad993..de462b7 100644 --- a/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java +++ b/src/main/java/com/flytrap/venusplanner/api/plan/domain/RecurringOption.java @@ -43,6 +43,10 @@ public RecurringOption(Frequency frequency, EndOption endOption, public void calculate(Instant startDate) { //TODO:(의견1) endOption에서 계산 로직 실행 + if (recurrenceCount != null && endDate != null) { + return; + } + if (endOption == EndOption.COUNT && recurrenceCount != null) { this.endDate = frequency.calculateEndDate(startDate, recurrenceCount); } else if (endOption == EndOption.DATE && endDate != null) {