Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,19 @@ public static RecurrenceException toRecurrenceExceptionForDelete(
public static RecurrenceException toRecurrenceExceptionForUpdate(
EventReqDTO.UpdateReq req,
RecurrenceGroup recurrenceGroup,
LocalDateTime occurrenceDate
LocalDateTime occurrenceDate,
Integer duration
) {
LocalDateTime startTime = req.startTime() != null ? req.startTime() : null;
LocalDateTime endTime = req.endTime() != null
? req.endTime()
: startTime != null ? startTime.plusMinutes(duration) : null;
return RecurrenceException.builder()
.exceptionDate(occurrenceDate)
.title(req.title() != null ? req.title() : null)
.content(req.content() != null ? req.content() : null)
.startTime(req.startTime() != null ? req.startTime() : null)
.endTime(req.endTime() != null ? req.endTime() : null)
.startTime(startTime)
.endTime(endTime)
.exceptionType(ExceptionType.OVERRIDE)
.location(req.location() != null ? req.location() : null)
.color(req.color() != null ? req.color() : null)
Expand Down Expand Up @@ -345,13 +350,15 @@ private static void normalizeFrequencyForUpdate(

b.frequency(frequency);

Integer interval;
int interval;
if (frequency == RecurrenceFrequency.WEEKLY) {
// WEEKLY는 무조건 1
interval = 1;
} else {
// WEEKLY가 아닌 경우만 req → rg 순으로 선택
interval = req.intervalValue() != null ? req.intervalValue() : rg.getIntervalValue();
interval = req.intervalValue() != null
? req.intervalValue()
: rg != null ? rg.getIntervalValue() : 1;
}

b.interval(interval);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,9 @@ public void updateRecurrenceGroup(RecurrenceGroup recurrenceGroup) {
this.recurrenceGroup = recurrenceGroup;
this.recurrenceFrequency = recurrenceGroup.getFrequency();
}

public void updateTime(LocalDateTime startTime, LocalDateTime endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,27 +178,44 @@ private static LocalDateTime adjustMonthlyByNthWeekday(
return base;
}

// 이번 달 먼저, 후보가 base보다 이전이면 다음 달로 1번 더 시도
YearMonth month = YearMonth.from(base);

// 해당 월의 n번째 주 시작 (월요일 기준)
LocalDate startOfNthWeek = getNthWeekday(month, week, DayOfWeek.MONDAY);
if (startOfNthWeek == null) {
throw new IllegalStateException("Invalid weekOfMonth");
LocalDate candidateDate = findNthWeekCandidate(month, week, targetDays);
if (candidateDate != null) {
LocalDateTime candidate = LocalDateTime.of(candidateDate, base.toLocalTime());
if (!candidate.isBefore(base)) {
return candidate; // candidate >= base 이면 이번 달 확정
}
}

LocalDate endOfNthWeek = startOfNthWeek.plusDays(6);
// 이번 달 후보가 base보다 이전이거나(= 과거), 아예 없으면 다음 달
YearMonth nextMonth = month.plusMonths(1);
LocalDate nextCandidateDate = findNthWeekCandidate(nextMonth, week, targetDays);
if (nextCandidateDate != null) {
return LocalDateTime.of(nextCandidateDate, base.toLocalTime());
}

throw new RecurrenceGroupException(RecurrenceGroupErrorCode.FAIL_ADJUSTMENT_DAY_OF_WEEK);
}

// 그 주 안에서 rule에 맞는 첫 번째 요일 선택
for (LocalDate d = startOfNthWeek;
!d.isAfter(endOfNthWeek);
d = d.plusDays(1)) {
private static LocalDate findNthWeekCandidate(
YearMonth month,
int week,
List<DayOfWeek> targetDays
) {
// 해당 월의 n번째 주 시작(월요일 기준)
LocalDate startOfNthWeek = getNthWeekday(month, week, DayOfWeek.MONDAY);
if (startOfNthWeek == null) return null;

LocalDate endOfNthWeek = startOfNthWeek.plusDays(6);

for (LocalDate d = startOfNthWeek; !d.isAfter(endOfNthWeek); d = d.plusDays(1)) {
if (targetDays.contains(d.getDayOfWeek())) {
return LocalDateTime.of(d, base.toLocalTime());
return d; // 그 주 안에서 rule에 맞는 첫 날짜
}
}

throw new RecurrenceGroupException(RecurrenceGroupErrorCode.FAIL_ADJUSTMENT_DAY_OF_WEEK);
return null;
}

private static LocalDate getNthWeekday(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void updateEvent(
RecurrenceGroupReqDTO.CreateReq createReq =
RecurrenceGroupConverter.toCreateReq(req.recurrenceGroup());
rgValidator.validateCreate(createReq, start);
RecurrenceGroup rg = updateToRecurrenceEvent(req, req.recurrenceGroup(), member, start);
RecurrenceGroup rg = updateToRecurrenceEvent(req, req.recurrenceGroup(), event, member, start);
event.updateRecurrenceGroup(rg);
rg.updateEvent(event);
// 이벤트 + 반복 생성에 따른 리스너 수정 로직 실행
Expand Down Expand Up @@ -424,9 +424,16 @@ private void updateRecurrenceException(EventReqDTO.UpdateReq req, RecurrenceExce
private RecurrenceGroup updateToRecurrenceEvent(
EventReqDTO.UpdateReq eventReq,
RecurrenceGroupReqDTO.UpdateReq rgReq,
Event event,
Member member,
LocalDateTime start) {
RecurrenceGroupSpec rgSpec = RecurrenceGroupConverter.from(eventReq, rgReq, null, start);

AdjustedTime adjusted = RecurrenceTimeAdjuster.adjust(event.getStartTime(), event.getEndTime(), rgSpec);

// 생성된 반복에 따른 일정 start,endTime 업데이트
event.updateTime(adjusted.start(), adjusted.end());

return createRecurrenceGroup(rgSpec, member);
}

Expand Down Expand Up @@ -466,7 +473,8 @@ private void updateThisEventOnly(
return;
}

RecurrenceException ex = RecurrenceGroupConverter.toRecurrenceExceptionForUpdate(req, rg, occurrenceDate);
RecurrenceException ex = RecurrenceGroupConverter.toRecurrenceExceptionForUpdate(
req, rg, occurrenceDate, event.getDurationMinutes());
recurrenceExRepository.save(ex);
rg.addExceptionDate(ex); // 해당 event가 속했던 반복 객체에 예외 날짜 추가

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ public EventResDTO.DetailRes getEventDetail(

eventValidator.validateRead(event, occurrenceDate);

// 찾고자 하는 것이 부모 이벤트인 경우
if (event.getStartTime().isEqual(occurrenceDate)) {
return EventConverter.toDetailRes(event);
}
// // 찾고자 하는 것이 부모 이벤트인 경우
// if (event.getStartTime().isEqual(occurrenceDate)) {
// return EventConverter.toDetailRes(event);
// }

return eventOccurrenceResolver.resolveForRead(event, occurrenceDate);
}
Expand Down Expand Up @@ -335,10 +335,39 @@ private List<EventResDTO.DetailRes> expandEvents(
recurrenceExceptions =
recurrenceExceptionRepository.findAllByRecurrenceGroupId(event.getRecurrenceGroup().getId());
}
// 부모가 검색 범위에 포함되어 있지 않다면 시간만 추출하고 폐기
if (!event.getEndTime().isBefore(startRange) && !event.getStartTime().isAfter(endRange)) {
expandedEvents.add(EventConverter.toDetailRes(event));
LocalDateTime tempStartTime = event.getStartTime();
LocalDateTime tempEndTime = event.getEndTime();
RecurrenceException tempEx = null;
boolean isSkip = false;
for (RecurrenceException ex : recurrenceExceptions) {
// 만약 부모 익셉션이 존재한다면
if (ex.getExceptionDate().isEqual(event.getStartTime())) {
log.debug("부모 익셉션 존재");
tempEx = ex;
}
}
if (tempEx != null) {
if (tempEx.getExceptionType() == OVERRIDE) {
log.debug("오버라이드 존재");
tempStartTime = tempEx.getStartTime() != null ? tempEx.getStartTime() : event.getStartTime();
tempEndTime = tempEx.getEndTime() != null ? tempEx.getEndTime() : event.getEndTime();
}
else if (tempEx.getExceptionType() == SKIP) {
log.debug("스킵 존재");
isSkip = true;
}
// 부모가 검색 범위에 포함되어 있지 않다면 시간만 추출하고 폐기
if (!isSkip && !tempStartTime.isBefore(startRange) && !tempEndTime.isAfter(endRange)) {
log.debug("예외 부모가 범위에 포함되었습니다");
expandedEvents.add(EventConverter.toDetailRes(tempEx, event));
}
} else {
if (!tempStartTime.isBefore(startRange) && !tempEndTime.isAfter(endRange)) {
log.debug("원본 부모가 범위에 포함되었습니다");
expandedEvents.add(EventConverter.toDetailRes(event));
}
}

// 부모 이벤트 포함
int count = 1;
// 생성기에 최초로 들어갈 기준 시간
Expand Down