diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java index 64db37e3..94ca2c9e 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java @@ -43,9 +43,10 @@ public enum ErrorCode { SIGNUP_NOT_AVAILABLE(403, "S001", "회원가입 기간이 아닙니다."), INVALID_SIGNUP_DATE(400, "S002", "등록 마감일이 시작일보다 앞설 수 없습니다."), INVALID_INTERVIEW_DATE(400, "S003", "면접 마감일이 시작일보다 앞설 수 없습니다."), - INVALID_ANNOUNCE_DATE(400, "S004", "결과 발표일이 면접 마감일보다 앞설 수 없습니다."), - NOT_WRITE_PROFILE(400, "S005", "아직 회원 프로필을 생성하지 않아서 회원가입을 마무리 할 수 없습니다."), - NOT_WRITE_ANSWERS(400, "S006", "아직 면접 질문을 작성하지 않아서 회원가입을 마무리 할 수 없습니다."), + INCOMPLETE_INTERVIEW_DATE(400, "S004", "면접 시작일과 종료일 중 하나만 설정되어 있습니다."), + INVALID_ANNOUNCE_DATE(400, "S005", "결과 발표일이 면접 마감일 또는 모집 마감일보다 앞설 수 없습니다."), + NOT_WRITE_PROFILE(400, "S006", "아직 회원 프로필을 생성하지 않아서 회원가입을 마무리 할 수 없습니다."), + NOT_WRITE_ANSWERS(400, "S007", "아직 면접 질문을 작성하지 않아서 회원가입을 마무리 할 수 없습니다."), // Board WRITER_UNMODIFIABLE(403, "B001", "글 작성자를 변경 할 수 없습니다."), diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java index 2b28f7f6..fddf7b9c 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java @@ -36,10 +36,10 @@ public class SignUpSchedule { @Column(name = "SIGNUP_END", nullable = false) private LocalDateTime signupEndDate; - @Column(name = "INTERVIEW_START", nullable = false) + @Column(name = "INTERVIEW_START", nullable = true) private LocalDateTime interviewStartDate; - @Column(name = "INTERVIEW_END", nullable = false) + @Column(name = "INTERVIEW_END", nullable = true) private LocalDateTime interviewEndDate; @Column(name = "RESULT_ANNOUNCE_DATE", nullable = false) @@ -85,12 +85,24 @@ private void setSignUpDate(LocalDateTime signupStartDate, LocalDateTime signupEn } private void setInterviewDate(LocalDateTime interviewStartDate, LocalDateTime interviewEndDate) { - if (interviewEndDate.isAfter(interviewStartDate)) { - this.interviewStartDate = interviewStartDate; - this.interviewEndDate = interviewEndDate; - } else { - throw new InvalidDateException(ErrorCode.INVALID_INTERVIEW_DATE); + boolean isStartNull = interviewStartDate == null; + boolean isEndNull = interviewEndDate == null; + + // 면접 시작일과 종료일 중 하나만 null인 경우 오류 발생 + if (isStartNull ^ isEndNull) { + throw new InvalidDateException(ErrorCode.INCOMPLETE_INTERVIEW_DATE); } + + // 둘 다 null이 아니면, 종료일이 시작일 이후인지 검사 + if (!isStartNull && !isEndNull) { + if (!interviewEndDate.isAfter(interviewStartDate)) { + throw new InvalidDateException(ErrorCode.INVALID_INTERVIEW_DATE); + } + } + + // 모든 검사를 통과하면 필드 업데이트 + this.interviewStartDate = interviewStartDate; + this.interviewEndDate = interviewEndDate; } private void setResultAnnounceDate( @@ -98,10 +110,17 @@ private void setResultAnnounceDate( LocalDateTime interviewEndDate, LocalDateTime resultAnnounceDate) { - if (resultAnnounceDate.isAfter(signupEndDate) && resultAnnounceDate.isAfter(interviewEndDate)) { - this.resultAnnounceDate = resultAnnounceDate; - } else { + // 결과 발표일은 항상 회원가입 종료일 이후여야 한다. + if (!resultAnnounceDate.isAfter(signupEndDate)) { throw new InvalidDateException(ErrorCode.INVALID_ANNOUNCE_DATE); } + + // 면접 종료일이 null이 아닌 경우, 결과 발표일은 면접 종료일 이후여야 한다. + if (interviewEndDate != null && !resultAnnounceDate.isAfter(interviewEndDate)) { + throw new InvalidDateException(ErrorCode.INVALID_ANNOUNCE_DATE); + } + + // 위의 조건들을 모두 통과하면, 결과 발표일을 설정한다. + this.resultAnnounceDate = resultAnnounceDate; } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java index 14ee407d..7feeb016 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java @@ -33,12 +33,10 @@ public class SignUpScheduleDto { @Schema(type = "string", example = "2024-11-01T00:00:00") private LocalDateTime signupEndDate; - @NotNull @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") @Schema(type = "string", example = "2024-11-01T00:00:00") private LocalDateTime interviewStartDate; - @NotNull @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") @Schema(type = "string", example = "2024-11-01T00:00:00") private LocalDateTime interviewEndDate; diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java index 27740d64..e2ba3e02 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java @@ -1,6 +1,7 @@ package com.inhabas.api.domain.signUpSchedule.domain.entity; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.junit.jupiter.api.Assertions.assertThrows; import java.time.LocalDateTime; @@ -93,6 +94,34 @@ public void invalidInterviewScheduleTest() { assertThat(invalidDateException.getMessage()).isEqualTo("면접 마감일이 시작일보다 앞설 수 없습니다."); } + @DisplayName("면접 날짜가 누락된 스케줄 엔티티 생성을 시도한다.") + @Test + public void incompleteInterviewScheduleTest() { + // given + Integer generation = 1; + LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 1, 0, 0, 0); + LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 2, 0, 0, 0); + LocalDateTime interviewStart = null; + LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 3, 0, 0, 0); + LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 5, 0, 0, 0); + + // when + InvalidDateException invalidDateException = + assertThrows( + InvalidDateException.class, + () -> + new SignUpSchedule( + generation, + signUpStart, + signUpEnd, + interviewStart, + interviewEnd, + resultAnnounce)); + + // then + assertThat(invalidDateException.getMessage()).isEqualTo("면접 시작일과 종료일 중 하나만 설정되어 있습니다."); + } + @DisplayName("결과 공고 날짜가 잘못된 스케줄 엔티티 생성을 시도한다.") @Test public void invalidAnnounceScheduleTest() { @@ -118,6 +147,31 @@ public void invalidAnnounceScheduleTest() { resultAnnounce)); // then - assertThat(invalidDateException.getMessage()).isEqualTo("결과 발표일이 면접 마감일보다 앞설 수 없습니다."); + assertThat(invalidDateException.getMessage()) + .isEqualTo("결과 발표일이 면접 마감일 또는 모집 마감일보다 앞설 수 없습니다."); + } + + @DisplayName("면접 날짜 둘 다 누락되어있으면 결과 공고일 검사는 모집일정을 기준으로만 판단한다.") + @Test + public void AnnounceScheduleTestWhenInterviewDateIsIncomplete() { + // given + Integer generation = 1; + LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 1, 0, 0, 0); + LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 3, 0, 0, 0); + LocalDateTime interviewStart = null; + LocalDateTime interviewEnd = null; + LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 4, 0, 0, 0); + + // when & then + assertThatCode( + () -> + new SignUpSchedule( + generation, + signUpStart, + signUpEnd, + interviewStart, + interviewEnd, + resultAnnounce)) + .doesNotThrowAnyException(); } }