diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/dto/AppointHolidayPeriodRequest.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/dto/AppointHolidayPeriodRequest.kt new file mode 100644 index 00000000..8275ca3a --- /dev/null +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/dto/AppointHolidayPeriodRequest.kt @@ -0,0 +1,21 @@ +package team.comit.simtong.domain.holiday.dto + +import java.time.LocalDate + +/** + * + * 휴무표 작성 기간 설정 요청 정보를 전달하는 AppointHolidayPeriodRequest + * + * @author Chokyunghyeon + * @date 2022/12/22 + * @version 1.0.0 + **/ +data class AppointHolidayPeriodRequest( + val year: Int, + + val month: Int, + + val startAt: LocalDate, + + val endAt: LocalDate +) \ No newline at end of file diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/spi/CommandHolidayPeriodPort.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/spi/CommandHolidayPeriodPort.kt new file mode 100644 index 00000000..def343e6 --- /dev/null +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/spi/CommandHolidayPeriodPort.kt @@ -0,0 +1,17 @@ +package team.comit.simtong.domain.holiday.spi + +import team.comit.simtong.domain.holiday.model.HolidayPeriod + +/** + * + * 휴무표 작성 기간에 관한 명령을 하는 CommandHolidayPeriodPort + * + * @author Chokyunghyeon + * @date 2022/12/22 + * @version 1.0.0 + **/ +interface CommandHolidayPeriodPort { + + fun save(holidayPeriod: HolidayPeriod) : HolidayPeriod + +} \ No newline at end of file diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/spi/HolidayPeriodPort.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/spi/HolidayPeriodPort.kt index 6b81cc18..621fd8b6 100644 --- a/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/spi/HolidayPeriodPort.kt +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/spi/HolidayPeriodPort.kt @@ -8,4 +8,4 @@ package team.comit.simtong.domain.holiday.spi * @date 2022/12/21 * @version 1.0.0 **/ -interface HolidayPeriodPort : QueryHolidayPeriodPort \ No newline at end of file +interface HolidayPeriodPort : QueryHolidayPeriodPort, CommandHolidayPeriodPort \ No newline at end of file diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayPeriodUseCase.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayPeriodUseCase.kt new file mode 100644 index 00000000..48d8537a --- /dev/null +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayPeriodUseCase.kt @@ -0,0 +1,40 @@ +package team.comit.simtong.domain.holiday.usecase + +import team.comit.simtong.domain.holiday.dto.AppointHolidayPeriodRequest +import team.comit.simtong.domain.holiday.model.HolidayPeriod +import team.comit.simtong.domain.holiday.spi.CommandHolidayPeriodPort +import team.comit.simtong.domain.holiday.spi.HolidayQueryUserPort +import team.comit.simtong.domain.holiday.spi.HolidaySecurityPort +import team.comit.simtong.domain.user.exception.UserExceptions +import team.comit.simtong.global.annotation.UseCase + +/** + * + * 휴무표 작성 기간 설정을 담당하는 AppointHolidayPeriodUseCase + * + * @author Chokyunghyeon + * @date 2022/12/22 + * @version 1.0.0 + **/ +@UseCase +class AppointHolidayPeriodUseCase( + private val commandHolidayPeriodPort: CommandHolidayPeriodPort, + private val queryUserPort: HolidayQueryUserPort, + private val securityPort: HolidaySecurityPort +) { + + fun execute(request: AppointHolidayPeriodRequest) { + val user = queryUserPort.queryUserById(securityPort.getCurrentUserId()) + ?: throw UserExceptions.NotFound() + + commandHolidayPeriodPort.save( + HolidayPeriod( + year = request.year, + month = request.month, + startAt = request.startAt, + endAt = request.endAt, + spotId = user.spotId + ) + ) + } +} \ No newline at end of file diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayUseCase.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayUseCase.kt index 94372249..e7130cb9 100644 --- a/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayUseCase.kt +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayUseCase.kt @@ -35,7 +35,7 @@ class AppointHolidayUseCase( ?: throw UserExceptions.NotFound() val holidayPeriod = queryHolidayPeriodPort.queryHolidayPeriodByYearAndMonthAndSpotId(date.year, date.monthValue, user.spotId) - ?: throw HolidayExceptions.NotFound("아직 작성 기간이 등록되지 않았습니다.") + ?: throw HolidayExceptions.NotFound("휴무표 작성 기간이 등록되지 않았습니다.") val today = LocalDate.now() diff --git a/simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayPeriodUseCaseTests.kt b/simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayPeriodUseCaseTests.kt new file mode 100644 index 00000000..bf34bb4d --- /dev/null +++ b/simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/AppointHolidayPeriodUseCaseTests.kt @@ -0,0 +1,99 @@ +package team.comit.simtong.domain.holiday.usecase + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows +import org.mockito.kotlin.given +import org.springframework.boot.test.mock.mockito.MockBean +import team.comit.simtong.domain.holiday.dto.AppointHolidayPeriodRequest +import team.comit.simtong.domain.holiday.spi.CommandHolidayPeriodPort +import team.comit.simtong.domain.holiday.spi.HolidayQueryUserPort +import team.comit.simtong.domain.holiday.spi.HolidaySecurityPort +import team.comit.simtong.domain.user.exception.UserExceptions +import team.comit.simtong.domain.user.model.Authority +import team.comit.simtong.domain.user.model.User +import team.comit.simtong.global.annotation.SimtongTest +import java.time.LocalDate +import java.util.UUID + +@SimtongTest +class AppointHolidayPeriodUseCaseTests { + + @MockBean + private lateinit var commandHolidayPeriodPort: CommandHolidayPeriodPort + + @MockBean + private lateinit var queryUserPort: HolidayQueryUserPort + + @MockBean + private lateinit var securityPort: HolidaySecurityPort + + private lateinit var appointHolidayPeriodUseCase: AppointHolidayPeriodUseCase + + private val id: UUID = UUID.randomUUID() + + private val userStub: User by lazy { + User( + id = id, + nickname = "test nickname", + email = "test@test.com", + name = "test name", + password = "test password", + employeeNumber = 1234567890, + authority = Authority.ROLE_ADMIN, + spotId = id, + teamId = id, + profileImagePath = User.DEFAULT_IMAGE + ) + } + + private val requestStub: AppointHolidayPeriodRequest by lazy { + AppointHolidayPeriodRequest( + year = 2022, + month = 12, + startAt = LocalDate.now(), + endAt = LocalDate.now() + ) + } + + @BeforeEach + fun setUp() { + appointHolidayPeriodUseCase = AppointHolidayPeriodUseCase( + commandHolidayPeriodPort = commandHolidayPeriodPort, + queryUserPort = queryUserPort, + securityPort = securityPort + ) + } + + @Test + fun `휴무일 작성 기간 설정 성공`() { + // given + given(securityPort.getCurrentUserId()) + .willReturn(id) + + given(queryUserPort.queryUserById(id)) + .willReturn(userStub) + + // when & then + assertDoesNotThrow { + appointHolidayPeriodUseCase.execute(requestStub) + } + } + + @Test + fun `유저를 찾을 수 없음`() { + // given + given(securityPort.getCurrentUserId()) + .willReturn(id) + + given(queryUserPort.queryUserById(id)) + .willReturn(null) + + // when & then + assertThrows { + appointHolidayPeriodUseCase.execute(requestStub) + } + } + +} \ No newline at end of file diff --git a/simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/QueryQueryRemainAnnualUseCaseTests.kt b/simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/QueryRemainAnnualUseCaseTests.kt similarity index 97% rename from simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/QueryQueryRemainAnnualUseCaseTests.kt rename to simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/QueryRemainAnnualUseCaseTests.kt index c2f400f0..0167746c 100644 --- a/simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/QueryQueryRemainAnnualUseCaseTests.kt +++ b/simtong-application/src/test/kotlin/team/comit/simtong/domain/holiday/usecase/QueryRemainAnnualUseCaseTests.kt @@ -13,7 +13,7 @@ import team.comit.simtong.global.annotation.SimtongTest import java.util.UUID @SimtongTest -class QueryQueryRemainAnnualUseCaseTests { +class QueryRemainAnnualUseCaseTests { @MockBean private lateinit var queryHolidayPort: QueryHolidayPort diff --git a/simtong-infrastructure/src/main/kotlin/team/comit/simtong/global/security/SecurityConfig.kt b/simtong-infrastructure/src/main/kotlin/team/comit/simtong/global/security/SecurityConfig.kt index f4b803ef..bf504caf 100644 --- a/simtong-infrastructure/src/main/kotlin/team/comit/simtong/global/security/SecurityConfig.kt +++ b/simtong-infrastructure/src/main/kotlin/team/comit/simtong/global/security/SecurityConfig.kt @@ -101,6 +101,7 @@ class SecurityConfig( .antMatchers(HttpMethod.GET, "/holidays/annual/count").hasRole(ROLE_COMMON.role) .antMatchers(HttpMethod.GET, "/holidays/verification-period").hasRole(ROLE_COMMON.role) .antMatchers(HttpMethod.GET, "/holidays/employee").hasRole(ROLE_ADMIN.role) + .antMatchers(HttpMethod.PUT, "/holidays/period").hasRole(ROLE_ADMIN.role) // admins .antMatchers(HttpMethod.POST, "/admins/tokens").permitAll() diff --git a/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/holiday/HolidayPeriodPersistenceAdapter.kt b/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/holiday/HolidayPeriodPersistenceAdapter.kt index 3e85018e..e46b3973 100644 --- a/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/holiday/HolidayPeriodPersistenceAdapter.kt +++ b/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/holiday/HolidayPeriodPersistenceAdapter.kt @@ -47,4 +47,10 @@ class HolidayPeriodPersistenceAdapter( .fetchOne() != null } + override fun save(holidayPeriod: HolidayPeriod): HolidayPeriod { + return holidayPeriodJpaRepository.save( + holidayPeriodMapper.toEntity(holidayPeriod) + ).let { holidayPeriodMapper.toDomain(it)!! } + } + } \ No newline at end of file diff --git a/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/WebHolidayAdapter.kt b/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/WebHolidayAdapter.kt index 1df73682..076e3135 100644 --- a/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/WebHolidayAdapter.kt +++ b/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/WebHolidayAdapter.kt @@ -9,17 +9,20 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController +import team.comit.simtong.domain.holiday.dto.AppointHolidayPeriodRequest import team.comit.simtong.domain.holiday.dto.QueryEmployeeHolidayResponse import team.comit.simtong.domain.holiday.dto.QueryIndividualHolidaysResponse import team.comit.simtong.domain.holiday.dto.QueryIndividualRequest import team.comit.simtong.domain.holiday.dto.request.AppointAnnualWebRequest +import team.comit.simtong.domain.holiday.dto.request.AppointHolidayPeriodWebRequest import team.comit.simtong.domain.holiday.dto.request.AppointHolidayWebRequest -import team.comit.simtong.domain.holiday.dto.request.CancelHolidayRequest +import team.comit.simtong.domain.holiday.dto.request.CancelHolidayWebRequest import team.comit.simtong.domain.holiday.dto.request.ShareHolidayWebRequest import team.comit.simtong.domain.holiday.dto.request.WebHolidayQueryType import team.comit.simtong.domain.holiday.dto.request.WebHolidayStatus import team.comit.simtong.domain.holiday.dto.response.QueryRemainAnnualWebResponse import team.comit.simtong.domain.holiday.usecase.AppointAnnualUseCase +import team.comit.simtong.domain.holiday.usecase.AppointHolidayPeriodUseCase import team.comit.simtong.domain.holiday.usecase.AppointHolidayUseCase import team.comit.simtong.domain.holiday.usecase.CancelHolidayUseCase import team.comit.simtong.domain.holiday.usecase.CheckHolidayPeriodUseCase @@ -42,6 +45,7 @@ import javax.validation.Valid @RestController @RequestMapping("/holidays") class WebHolidayAdapter( + private val appointHolidayPeriodUseCase: AppointHolidayPeriodUseCase, private val checkHolidayPeriodUseCase: CheckHolidayPeriodUseCase, private val queryRemainAnnualUseCase: QueryRemainAnnualUseCase, private val appointAnnualUseCase: AppointAnnualUseCase, @@ -72,7 +76,7 @@ class WebHolidayAdapter( } @PutMapping("/work") - fun cancelHoliday(@RequestBody request: CancelHolidayRequest) { + fun cancelHoliday(@RequestBody request: CancelHolidayWebRequest) { cancelHolidayUseCase.execute(request.date) } @@ -119,4 +123,16 @@ class WebHolidayAdapter( teamId = teamId ) } + + @PutMapping("/period") + fun appointHolidayPeriod(@Valid @RequestBody request: AppointHolidayPeriodWebRequest) { + appointHolidayPeriodUseCase.execute( + AppointHolidayPeriodRequest( + year = request.year, + month = request.month, + startAt = request.startAt, + endAt = request.endAt + ) + ) + } } \ No newline at end of file diff --git a/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/AppointHolidayPeriodWebRequest.kt b/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/AppointHolidayPeriodWebRequest.kt new file mode 100644 index 00000000..06bf0219 --- /dev/null +++ b/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/AppointHolidayPeriodWebRequest.kt @@ -0,0 +1,29 @@ +package team.comit.simtong.domain.holiday.dto.request + +import org.hibernate.validator.constraints.Range +import java.time.LocalDate +import javax.validation.constraints.NotNull + +/** + * + * 휴무표 작성 기간 설정을 요청하는 AppointHolidayPeriodWebRequest + * + * @author Chokyunghyeon + * @date 2022/12/22 + * @version 1.0.0 + **/ +data class AppointHolidayPeriodWebRequest( + @field:NotNull + val year: Int, + + @field:NotNull + @field:Range( + min = 1, + max = 12 + ) + val month: Int, + + val startAt: LocalDate, + + val endAt: LocalDate +) \ No newline at end of file diff --git a/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/CancelHolidayRequest.kt b/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/CancelHolidayWebRequest.kt similarity index 65% rename from simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/CancelHolidayRequest.kt rename to simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/CancelHolidayWebRequest.kt index 752bfaab..c177fd7e 100644 --- a/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/CancelHolidayRequest.kt +++ b/simtong-presentation/src/main/kotlin/team/comit/simtong/domain/holiday/dto/request/CancelHolidayWebRequest.kt @@ -4,12 +4,12 @@ import java.time.LocalDate /** * - * 근무일 지정을 요청하는 CancelHolidayRequest + * 근무일 지정을 요청하는 CancelHolidayWebRequest * * @author kimbeomjin * @date 2022/12/20 * @version 1.0.0 **/ -data class CancelHolidayRequest( +data class CancelHolidayWebRequest( val date: LocalDate )