-
Notifications
You must be signed in to change notification settings - Fork 1
[feat] 반복옵션 로직 추가 #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
5477cb9
1444372
49eab29
ce80aef
76509f5
ef232b3
ad6baca
df6fcb3
962ddcf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,17 @@ | ||
| 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.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.study_plan.presentation.dto.request.StudyPlanCreateRequest; | ||
| 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; | ||
|
|
@@ -16,24 +23,68 @@ | |
| public class PlanService { | ||
|
|
||
| private final PlanRepository planRepository; | ||
| private final RecurringOptionRepository recurringOptionRepository; | ||
|
|
||
| public Long savePlan(Study study, PlanCategory planCategory, StudyPlanCreateRequest request) { | ||
| //TODO: 반복 옵션 설정시 DB에 여러 plan 저장 로직 추가 | ||
| public Long savePlan(Study study, PlanCategory planCategory, PlanCreateRequest request) { | ||
| Plan plan = request.toEntity(study, planCategory); | ||
| planRepository.save(plan); | ||
|
|
||
| if (plan.getRecurringOption() != null) { | ||
| List<Plan> recurringPlan = createPlansWithRecurringPlan(plan); | ||
| planRepository.saveAll(recurringPlan); | ||
| } | ||
|
|
||
| return plan.getId(); | ||
| } | ||
|
|
||
| private List<Plan> 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<Plan> 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(); | ||
|
Comment on lines
+51
to
+60
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 서비스 로직 코드 읽는데 빌더가 너무 길어서 |
||
|
|
||
| createdPlans.add(planRepository.save(newPlan)); | ||
| } | ||
|
|
||
| return createdPlans; | ||
| } | ||
|
|
||
| public List<Plan> findAllByStudyIdAndYearAndMonth(Long studyId, int year, int month) { | ||
| return planRepository.findAllByStudyIdAndYearAndMonth(studyId, year, month); | ||
| } | ||
|
|
||
| @Transactional | ||
| public void deleteById(Long planId) { | ||
| //TODO: 멤버의 권한 검증 로직 | ||
| //TODO: 반복옵션 전체 삭제 여부 | ||
| //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); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,67 @@ | ||
| package com.flytrap.venusplanner.api.plan.domain; | ||
|
|
||
| public enum Frequency { | ||
| WEEKLY, MONTHLY, YEARLY | ||
| 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; | ||
| import java.time.temporal.ChronoUnit; | ||
|
|
||
| public enum Frequency implements EndOptionCalculate { | ||
| WEEKLY(ChronoUnit.WEEKS) { | ||
| @Override | ||
| public Instant calculateEndDate(Instant startDate, int count) { | ||
| ZonedDateTime zdtStart = DateTimeUtils.toZonedDateTime(startDate); | ||
| return DateTimeUtils.toInstant(zdtStart.plusWeeks(count - 1)); | ||
| } | ||
|
|
||
| @Override | ||
| public int calculateCount(Instant startDate, Instant endDate) { | ||
| ZonedDateTime zdtStart = DateTimeUtils.toZonedDateTime(startDate); | ||
| ZonedDateTime zdtEnd = DateTimeUtils.toZonedDateTime(endDate); | ||
| return (int) ChronoUnit.WEEKS.between(zdtStart, zdtEnd) + 1; | ||
| } | ||
| }, | ||
|
Comment on lines
+11
to
+24
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 방식 보기 좋아요! |
||
| MONTHLY(ChronoUnit.MONTHS) { | ||
| @Override | ||
| public Instant calculateEndDate(Instant startDate, int count) { | ||
| ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); | ||
| ZonedDateTime zdtEnd = zdtStart.plusMonths(count - 1); | ||
| return zdtEnd.toInstant(); | ||
| } | ||
|
|
||
| @Override | ||
| public int calculateCount(Instant startDate, Instant 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(ChronoUnit.YEARS) { | ||
| @Override | ||
| public Instant calculateEndDate(Instant startDate, int count) { | ||
| ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); | ||
| ZonedDateTime zdtEnd = zdtStart.plusYears(count - 1); | ||
| return zdtEnd.toInstant(); | ||
| } | ||
|
|
||
| @Override | ||
| public int calculateCount(Instant startDate, Instant endDate) { | ||
| ZonedDateTime zdtStart = startDate.atZone(ZoneId.systemDefault()); | ||
| ZonedDateTime zdtEnd = endDate.atZone(ZoneId.systemDefault()); | ||
| long yearsBetween = ChronoUnit.YEARS.between(zdtStart, zdtEnd); | ||
| return (int) yearsBetween + 1; | ||
| } | ||
| }; | ||
|
|
||
| private final ChronoUnit chronoUnit; | ||
|
|
||
| Frequency(ChronoUnit chronoUnit) { | ||
| this.chronoUnit = chronoUnit; | ||
| } | ||
|
|
||
| public ChronoUnit getChronoUnit() { | ||
| return chronoUnit; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,4 +40,17 @@ public RecurringOption(Frequency frequency, EndOption endOption, | |
| this.recurrenceCount = recurrenceCount; | ||
| this.endDate = endDate; | ||
| } | ||
|
|
||
| public void calculate(Instant startDate) { | ||
|
Comment on lines
+43
to
+44
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. calculate 메서드명이 좀 더 구체적이면 좋을 것 같아요
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반복 옵션이 생성될 때 생성자에서 계산해서 넣어주면 안되나요?? calculate가 있어야 하는 이유가 궁금합니다 |
||
| //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) { | ||
| this.recurrenceCount = frequency.calculateCount(startDate, endDate); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<PlanReadResponse> from(List<Plan> 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()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calculate가 동사라서 Calculator나 Calculatable? 어떠세요?