날짜 체크 수정
This commit is contained in:
@@ -23,6 +23,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.HashMap;
|
||||
@@ -135,6 +137,7 @@ public class BattleEventService {
|
||||
List<BattleEvent> existingList = battleMapper.getCheckBattleEventList(battleEventRequest);
|
||||
boolean isTime = isTimeOverlapping(existingList, battleEventRequest);
|
||||
if(isTime){
|
||||
log.warn("battle Schedule duplication start_dt: {}, end_dt: {}, operation_time: {}", battleEventRequest.getEventStartDt(), battleEventRequest.getEventEndDt(), operation_time);
|
||||
return BattleEventResponse.builder()
|
||||
.status(CommonCode.ERROR.getHttpStatus())
|
||||
.result(ErrorCode.ERROR_BATTLE_EVENT_TIME_OVER.toString())
|
||||
@@ -363,14 +366,205 @@ public class BattleEventService {
|
||||
}
|
||||
|
||||
private boolean isTimeOverlapping(List<BattleEvent> existingList, BattleEventRequest battleEventRequest){
|
||||
LocalTime newStartTime = battleEventRequest.getEventStartDt().toLocalTime();
|
||||
LocalDateTime newStartDt = battleEventRequest.getEventStartDt();
|
||||
LocalDateTime newEndDt = battleEventRequest.getEventEndDt();
|
||||
LocalDate newStartDate = newStartDt.toLocalDate();
|
||||
LocalDate newEndDate = newEndDt.toLocalDate();
|
||||
LocalTime newStartTime = newStartDt.toLocalTime();
|
||||
LocalTime newEndTime = newStartTime.plusSeconds(battleEventRequest.getEventOperationTime());
|
||||
BattleEvent.BATTLE_REPEAT_TYPE newRepeatType = battleEventRequest.getRepeatType();
|
||||
|
||||
return existingList.stream().anyMatch(schedule -> {
|
||||
LocalTime existingStartTime = schedule.getEventStartDt().toLocalTime();
|
||||
LocalTime existingEndTime = existingStartTime.plusSeconds(schedule.getEventOperationTime());
|
||||
return existingList.stream().anyMatch(existingEvent -> {
|
||||
// 자기 자신은 제외 (수정 시)
|
||||
if (battleEventRequest.getId() != null && battleEventRequest.getId().equals(existingEvent.getId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
// 기존 이벤트 정보
|
||||
LocalDateTime existingStartDt = existingEvent.getEventStartDt();
|
||||
LocalDateTime existingEndDt = existingEvent.getEventEndDt();
|
||||
LocalDate existingStartDate = existingStartDt.toLocalDate();
|
||||
LocalDate existingEndDate = existingEndDt.toLocalDate();
|
||||
LocalTime existingStartTime = existingStartDt.toLocalTime();
|
||||
LocalTime existingEndTime = existingStartTime.plusSeconds(existingEvent.getEventOperationTime());
|
||||
BattleEvent.BATTLE_REPEAT_TYPE existingRepeatType = existingEvent.getRepeatType();
|
||||
|
||||
// 1. 두 이벤트가 모두 NONE 타입인 경우
|
||||
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE &&
|
||||
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE) {
|
||||
// 같은 날짜인지 확인
|
||||
if (newStartDate.equals(existingStartDate)) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. NONE 타입과 DAY 타입 간의 중복 체크
|
||||
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE &&
|
||||
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY) {
|
||||
// NONE 이벤트의 날짜가 DAY 이벤트의 기간 내에 있는지 확인
|
||||
if (isDateInRange(newStartDate, existingStartDate, existingEndDate)) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. DAY 타입과 NONE 타입 간의 중복 체크
|
||||
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY &&
|
||||
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE) {
|
||||
// NONE 이벤트의 날짜가 DAY 이벤트의 기간 내에 있는지 확인
|
||||
if (isDateInRange(existingStartDate, newStartDate, newEndDate)) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 두 이벤트가 모두 DAY 타입인 경우
|
||||
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY &&
|
||||
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY) {
|
||||
// 날짜 범위가 겹치는지 확인
|
||||
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. NONE 타입과 요일 타입 간의 중복 체크
|
||||
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE &&
|
||||
isWeekdayType(existingRepeatType)) {
|
||||
// NONE 이벤트의 날짜가 요일 이벤트의 기간 내에 있는지 확인
|
||||
if (isDateInRange(newStartDate, existingStartDate, existingEndDate)) {
|
||||
// NONE 이벤트의 요일이 요일 이벤트의 요일과 일치하는지 확인
|
||||
DayOfWeek noneDayOfWeek = newStartDate.getDayOfWeek();
|
||||
DayOfWeek weekdayType = getDayOfWeekFromRepeatType(existingRepeatType);
|
||||
|
||||
if (noneDayOfWeek == weekdayType) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 6. 요일 타입과 NONE 타입 간의 중복 체크
|
||||
if (isWeekdayType(newRepeatType) &&
|
||||
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE) {
|
||||
// NONE 이벤트의 날짜가 요일 이벤트의 기간 내에 있는지 확인
|
||||
if (isDateInRange(existingStartDate, newStartDate, newEndDate)) {
|
||||
// NONE 이벤트의 요일이 요일 이벤트의 요일과 일치하는지 확인
|
||||
DayOfWeek noneDayOfWeek = existingStartDate.getDayOfWeek();
|
||||
DayOfWeek weekdayType = getDayOfWeekFromRepeatType(newRepeatType);
|
||||
|
||||
if (noneDayOfWeek == weekdayType) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 7. DAY 타입과 요일 타입 간의 중복 체크
|
||||
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY &&
|
||||
isWeekdayType(existingRepeatType)) {
|
||||
// 날짜 범위가 겹치는지 확인
|
||||
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
|
||||
// 날짜 범위 내에 해당 요일이 적어도 하나 있는지 확인
|
||||
if (hasOverlappingWeekday(newStartDate, newEndDate, existingStartDate, existingEndDate, getDayOfWeekFromRepeatType(existingRepeatType))) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 8. 요일 타입과 DAY 타입 간의 중복 체크
|
||||
if (isWeekdayType(newRepeatType) &&
|
||||
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY) {
|
||||
// 날짜 범위가 겹치는지 확인
|
||||
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
|
||||
// 날짜 범위 내에 해당 요일이 적어도 하나 있는지 확인
|
||||
if (hasOverlappingWeekday(newStartDate, newEndDate, existingStartDate, existingEndDate, getDayOfWeekFromRepeatType(newRepeatType))) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 9. 두 이벤트가 모두 요일 타입인 경우
|
||||
if (isWeekdayType(newRepeatType) && isWeekdayType(existingRepeatType)) {
|
||||
// 같은 요일인지 확인
|
||||
if (newRepeatType == existingRepeatType) {
|
||||
// 날짜 범위가 겹치는지 확인
|
||||
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
|
||||
// 시간이 겹치는지 확인
|
||||
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isDateInRange(LocalDate date, LocalDate rangeStart, LocalDate rangeEnd) {
|
||||
return !date.isBefore(rangeStart) && !date.isAfter(rangeEnd);
|
||||
}
|
||||
|
||||
private boolean datesOverlap(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
|
||||
return !start1.isAfter(end2) && !start2.isAfter(end1);
|
||||
}
|
||||
|
||||
private boolean isWeekdayType(BattleEvent.BATTLE_REPEAT_TYPE repeatType) {
|
||||
return repeatType == BattleEvent.BATTLE_REPEAT_TYPE.SUNDAY ||
|
||||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.MONDAY ||
|
||||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.TUESDAY ||
|
||||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.WEDNESDAY ||
|
||||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.THURSDAY ||
|
||||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.FRIDAY ||
|
||||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.SATURDAY;
|
||||
}
|
||||
|
||||
private DayOfWeek getDayOfWeekFromRepeatType(BattleEvent.BATTLE_REPEAT_TYPE repeatType) {
|
||||
switch (repeatType) {
|
||||
case MONDAY: return DayOfWeek.MONDAY;
|
||||
case TUESDAY: return DayOfWeek.TUESDAY;
|
||||
case WEDNESDAY: return DayOfWeek.WEDNESDAY;
|
||||
case THURSDAY: return DayOfWeek.THURSDAY;
|
||||
case FRIDAY: return DayOfWeek.FRIDAY;
|
||||
case SATURDAY: return DayOfWeek.SATURDAY;
|
||||
case SUNDAY: return DayOfWeek.SUNDAY;
|
||||
default: throw new IllegalArgumentException("Invalid repeat type: " + repeatType);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasOverlappingWeekday(
|
||||
LocalDate start1, LocalDate end1,
|
||||
LocalDate start2, LocalDate end2,
|
||||
DayOfWeek dayOfWeek) {
|
||||
|
||||
// 두 범위의 교집합 계산
|
||||
LocalDate overlapStart = start1.isAfter(start2) ? start1 : start2;
|
||||
LocalDate overlapEnd = end1.isBefore(end2) ? end1 : end2;
|
||||
|
||||
if (overlapStart.isAfter(overlapEnd)) {
|
||||
return false; // 겹치는 날짜 범위 없음
|
||||
}
|
||||
|
||||
// 겹치는 날짜 범위 내에 해당 요일이 있는지 확인
|
||||
LocalDate current = overlapStart;
|
||||
while (!current.isAfter(overlapEnd)) {
|
||||
if (current.getDayOfWeek() == dayOfWeek) {
|
||||
return true; // 해당 요일 발견
|
||||
}
|
||||
current = current.plusDays(1);
|
||||
}
|
||||
|
||||
return false; // 해당 요일 없음
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user