diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9c22fb62d..995b252ad 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -7,6 +7,7 @@ on: - develop pull_request: branches: + - main - develop jobs: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d1541160..c5c8fa762 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,7 @@ on: - develop pull_request: branches: + - main - develop jobs: diff --git a/build.gradle.kts b/build.gradle.kts index c903cdfdb..e9ab134c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,8 +37,11 @@ subprojects { implementation(Dependencies.JAVA_SERVLET) // test - implementation(Dependencies.SPRING_TEST) - implementation(Dependencies.MOCKK) + testImplementation(Dependencies.SPRING_TEST) + testImplementation(Dependencies.MOCKK) + testImplementation(Dependencies.SPRING_KOTEST) + testImplementation(Dependencies.KOTEST) + testImplementation(Dependencies.KOTEST_ASSERTIONS) detektPlugins(Dependencies.DETEKT) } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 1c98fa47e..6b308ac5e 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -51,6 +51,9 @@ object Dependencies { // test const val SPRING_TEST = "org.springframework.boot:spring-boot-starter-test:${PluginVersions.SPRING_BOOT_VERSION}" const val MOCKK = "io.mockk:mockk:${DependencyVersions.MOCKK_VERSION}" + const val SPRING_KOTEST = "io.kotest.extensions:kotest-extensions-spring:${DependencyVersions.SPRING_KOTEST_VERSION}" + const val KOTEST = "io.kotest:kotest-runner-junit5:${DependencyVersions.KOTEST_VERSION}" + const val KOTEST_ASSERTIONS = "io.kotest:kotest-assertions-core:${DependencyVersions.KOTEST_VERSION}" // time based uuid const val UUID_TIME = "com.fasterxml.uuid:java-uuid-generator:${DependencyVersions.UUID_TIME_VERSION}" diff --git a/buildSrc/src/main/kotlin/DependencyVersions.kt b/buildSrc/src/main/kotlin/DependencyVersions.kt index efa851eaf..214cb320f 100644 --- a/buildSrc/src/main/kotlin/DependencyVersions.kt +++ b/buildSrc/src/main/kotlin/DependencyVersions.kt @@ -12,7 +12,9 @@ object DependencyVersions { const val JAKARTA_PERSISTENCE_VERSION = "3.1.0" const val MYSQL = "8.0.28" const val APACHE_POI_VERSION = "3.7" - const val MOCKK_VERSION = "1.13.2" + const val MOCKK_VERSION = "1.13.10" + const val SPRING_KOTEST_VERSION = "1.1.3" + const val KOTEST_VERSION = "5.7.2" const val OPEN_FEIGN_VERSION = "4.1.0" const val SENTRY_VERSION = "6.2.1" const val ASPECTJ_VERSION = "1.9.7" diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/file/service/WriteFileServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/file/service/WriteFileServiceImpl.kt index 58feec089..5d4493f97 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/file/service/WriteFileServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/file/service/WriteFileServiceImpl.kt @@ -1,6 +1,6 @@ package team.aliens.dms.domain.file.service -import org.springframework.stereotype.Service +import team.aliens.dms.common.annotation.Service import team.aliens.dms.domain.file.spi.WriteFilePort import team.aliens.dms.domain.manager.spi.vo.StudentWithTag import team.aliens.dms.domain.outing.spi.vo.OutingApplicationVO diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/manager/spi/vo/StudentWithTag.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/manager/spi/vo/StudentWithTag.kt index eb3ad7cb2..266a8a040 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/manager/spi/vo/StudentWithTag.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/manager/spi/vo/StudentWithTag.kt @@ -14,6 +14,8 @@ data class StudentWithTag( val roomNumber: String, val profileImageUrl: String, val sex: Sex, + val bonusPoint: Int, + val minusPoint: Int, val tags: List ) { val gcn: String = Student.processGcn(this.grade, this.classRoom, this.number) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/ApplyOutingRequest.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/ApplyOutingRequest.kt index b69d52203..5d2776b5b 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/ApplyOutingRequest.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/ApplyOutingRequest.kt @@ -1,14 +1,14 @@ -package team.aliens.dms.domain.outing.dto - -import java.time.LocalDate -import java.time.LocalTime -import java.util.UUID - -data class ApplyOutingRequest( - val outAt: LocalDate, - val outingTime: LocalTime, - val arrivalTime: LocalTime, - val outingTypeTitle: String, - val reason: String?, - val companionIds: List? -) +package team.aliens.dms.domain.outing.dto + +import java.time.LocalDate +import java.time.LocalTime +import java.util.UUID + +data class ApplyOutingRequest( + val outingDate: LocalDate, + val outingTime: LocalTime, + val arrivalTime: LocalTime, + val outingTypeTitle: String, + val reason: String?, + val companionIds: List? +) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/OutingResponse.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/OutingResponse.kt index 2401985be..5aa2a41d5 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/OutingResponse.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/dto/OutingResponse.kt @@ -1,12 +1,16 @@ package team.aliens.dms.domain.outing.dto import com.fasterxml.jackson.annotation.JsonInclude +import team.aliens.dms.domain.outing.model.OutingApplication import team.aliens.dms.domain.outing.model.OutingStatus import team.aliens.dms.domain.outing.spi.vo.CurrentOutingApplicationVO import team.aliens.dms.domain.outing.spi.vo.OutingAvailableTimeVO +import team.aliens.dms.domain.outing.spi.vo.OutingCompanionDetailsVO import team.aliens.dms.domain.outing.spi.vo.OutingHistoryVO +import team.aliens.dms.domain.student.model.Student import java.time.LocalDate import java.time.LocalTime +import java.util.UUID data class GetAllOutingTypeTitlesResponse( val titles: List @@ -18,7 +22,8 @@ data class ExportAllOutingApplicationsResponse( ) data class GetCurrentOutingApplicationResponse( - val outAt: LocalDate, + val id: UUID, + val outingDate: LocalDate, val outingTypeTitle: String, val status: OutingStatus, val outingTime: LocalTime, @@ -31,7 +36,8 @@ data class GetCurrentOutingApplicationResponse( fun of(currentOutingApplicationVO: CurrentOutingApplicationVO) = currentOutingApplicationVO.run { GetCurrentOutingApplicationResponse( - outAt = outAt, + id = id, + outingDate = outingDate, outingTypeTitle = outingTypeTitle, status = status, outingTime = outingTime, @@ -50,3 +56,56 @@ data class OutingApplicationHistoriesResponse( data class OutingAvailableTimesResponse( val outingAvailableTimes: List ) + +data class OutingHistoryDetailsResponse( + val studentName: String, + val studentGcn: String, + val studentRoomNumber: String, + val outingTime: LocalTime, + val arrivalTime: LocalTime, + val outingStatus: OutingStatus, + @field:JsonInclude(JsonInclude.Include.ALWAYS) + val reason: String?, + val outingType: String, + val students: List +) { + companion object { + fun of( + outingHistory: OutingApplication, + outingCompanions: List, + student: Student + ): OutingHistoryDetailsResponse { + return OutingHistoryDetailsResponse( + studentName = student.name, + studentGcn = student.gcn, + studentRoomNumber = student.roomNumber, + outingTime = outingHistory.outingTime, + arrivalTime = outingHistory.arrivalTime, + outingStatus = outingHistory.status, + reason = outingHistory.reason, + outingType = outingHistory.outingTypeTitle, + students = outingCompanions.map { + OutingCompanionsResponse.of(it) + } + ) + } + } +} + +data class OutingCompanionsResponse( + val id: UUID, + val studentName: String, + val roomNumber: String, + val studentGcn: String +) { + companion object { + fun of(outingCompanions: OutingCompanionDetailsVO): OutingCompanionsResponse { + return OutingCompanionsResponse( + id = outingCompanions.id, + studentName = outingCompanions.studentName, + roomNumber = outingCompanions.roomNumber, + studentGcn = outingCompanions.studentGcn + ) + } + } +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingApplication.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingApplication.kt index 11c493d63..23fee4be5 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingApplication.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingApplication.kt @@ -17,7 +17,7 @@ data class OutingApplication( val createdAt: LocalDateTime, - val outAt: LocalDate, + val outingDate: LocalDate, val outingTime: LocalTime, @@ -35,10 +35,8 @@ data class OutingApplication( ) : SchoolIdDomain { - fun checkCancelable( - status: OutingStatus - ) { - if (status != OutingStatus.REQUESTED) { + fun checkCancelable(status: OutingStatus) { + if (status != OutingStatus.APPROVED) { throw OutingTypeMismatchException } } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingStatus.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingStatus.kt index 56de53df4..4e9b2452d 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingStatus.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/model/OutingStatus.kt @@ -3,5 +3,6 @@ package team.aliens.dms.domain.outing.model enum class OutingStatus { REQUESTED, OUTING, - DONE + DONE, + APPROVED } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingService.kt index 41be15474..6d628b240 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingService.kt @@ -9,7 +9,7 @@ interface CheckOutingService { fun checkOutingApplicationAvailable( studentId: UUID, - outAt: LocalDate, + outingDate: LocalDate, outingTime: LocalTime, arrivalTime: LocalTime ) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingServiceImpl.kt index 3d326a66b..d4fd8a317 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/CheckOutingServiceImpl.kt @@ -21,26 +21,26 @@ class CheckOutingServiceImpl( override fun checkOutingApplicationAvailable( studentId: UUID, - outAt: LocalDate, + outingDate: LocalDate, outingTime: LocalTime, arrivalTime: LocalTime ) { - checkOutingAvailableTime(outAt, outingTime, arrivalTime) - checkOutingApplicationExistsByOutAtAndStudentId(outAt, studentId) + checkOutingAvailableTime(outingDate, outingTime, arrivalTime) + checkOutingApplicationExistsByOutingDateAndStudentId(outingDate, studentId) } private fun checkOutingAvailableTime( - outAt: LocalDate, + outingDate: LocalDate, outingTime: LocalTime, arrivalTime: LocalTime ) { - queryOutingAvailableTimePort.queryOutingAvailableTimeByDayOfWeek(outAt.dayOfWeek) - ?.checkAvailable(outAt.dayOfWeek, outingTime, arrivalTime) + queryOutingAvailableTimePort.queryOutingAvailableTimeByDayOfWeek(outingDate.dayOfWeek) + ?.checkAvailable(outingDate.dayOfWeek, outingTime, arrivalTime) ?: throw OutingAvailableTimeMismatchException } - private fun checkOutingApplicationExistsByOutAtAndStudentId(outAt: LocalDate, studentId: UUID) { - if (queryOutingApplicationPort.existOutingApplicationByOutAtAndStudentId(outAt, studentId)) { + private fun checkOutingApplicationExistsByOutingDateAndStudentId(outingDate: LocalDate, studentId: UUID) { + if (queryOutingApplicationPort.existOutingApplicationByOutingDateAndStudentId(outingDate, studentId)) { throw OutingApplicationAlreadyExistsException } } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingService.kt index 341660141..6e815f6e4 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingService.kt @@ -5,6 +5,7 @@ import team.aliens.dms.domain.outing.model.OutingType import team.aliens.dms.domain.outing.spi.vo.CurrentOutingApplicationVO import team.aliens.dms.domain.outing.spi.vo.OutingApplicationVO import team.aliens.dms.domain.outing.spi.vo.OutingAvailableTimeVO +import team.aliens.dms.domain.outing.spi.vo.OutingCompanionDetailsVO import team.aliens.dms.domain.outing.spi.vo.OutingHistoryVO import java.time.DayOfWeek import java.time.LocalDate @@ -25,4 +26,6 @@ interface GetOutingService { fun getOutingHistoriesByStudentNameAndDate(studentName: String?, date: LocalDate): List fun getOutingAvailableTimesByDayOfWeek(dayOfWeek: DayOfWeek): List + + fun getOutingCompanionsByApplicationId(outingApplicationId: UUID): List } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingServiceImpl.kt index eac617127..e1a0851ef 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/service/GetOutingServiceImpl.kt @@ -1,51 +1,57 @@ -package team.aliens.dms.domain.outing.service - -import org.springframework.stereotype.Service -import team.aliens.dms.domain.outing.exception.OutingApplicationNotFoundException -import team.aliens.dms.domain.outing.exception.OutingTypeNotFoundException -import team.aliens.dms.domain.outing.model.OutingApplication -import team.aliens.dms.domain.outing.model.OutingType -import team.aliens.dms.domain.outing.spi.QueryOutingApplicationPort -import team.aliens.dms.domain.outing.spi.QueryOutingAvailableTimePort -import team.aliens.dms.domain.outing.spi.QueryOutingTypePort -import team.aliens.dms.domain.outing.spi.vo.CurrentOutingApplicationVO -import team.aliens.dms.domain.outing.spi.vo.OutingHistoryVO -import java.time.DayOfWeek -import java.time.LocalDate -import java.util.UUID - -@Service -class GetOutingServiceImpl( - private val queryOutingTypePort: QueryOutingTypePort, - private val queryOutingApplicationPort: QueryOutingApplicationPort, - private val queryOutingAvailableTimePort: QueryOutingAvailableTimePort -) : GetOutingService { - - override fun getOutingType(outingType: OutingType) = - queryOutingTypePort.queryOutingType(outingType) ?: throw OutingTypeNotFoundException - - override fun getAllOutingTypeTitlesBySchoolIdAndKeyword(schoolId: UUID, keyword: String?) = - queryOutingTypePort.queryAllOutingTypeTitlesBySchoolIdAndKeyword(schoolId, keyword) - - override fun getOutingApplicationById(outingApplicationId: UUID): OutingApplication = - queryOutingApplicationPort.queryOutingApplicationById(outingApplicationId) - ?: throw OutingApplicationNotFoundException - - override fun getAllOutingApplicationVOsBetweenStartAndEnd(start: LocalDate, end: LocalDate) = - queryOutingApplicationPort.queryAllOutingApplicationVOsBetweenStartAndEnd(start, end) - - override fun getCurrentOutingApplication(studentId: UUID): CurrentOutingApplicationVO = - queryOutingApplicationPort.queryCurrentOutingApplicationVO(studentId) - ?: throw OutingApplicationNotFoundException - - override fun getOutingHistoriesByStudentNameAndDate( - studentName: String?, - date: LocalDate - ): List = queryOutingApplicationPort.queryOutingHistoriesByStudentNameAndDate(studentName, date) - - override fun getOutingAvailableTimesByDayOfWeek( - dayOfWeek: DayOfWeek - ) = queryOutingAvailableTimePort.queryOutingAvailableTimesByDayOfWeek( - dayOfWeek = dayOfWeek - ) -} +package team.aliens.dms.domain.outing.service + +import team.aliens.dms.common.annotation.Service +import team.aliens.dms.domain.outing.exception.OutingApplicationNotFoundException +import team.aliens.dms.domain.outing.exception.OutingTypeNotFoundException +import team.aliens.dms.domain.outing.model.OutingApplication +import team.aliens.dms.domain.outing.model.OutingType +import team.aliens.dms.domain.outing.spi.QueryOutingApplicationPort +import team.aliens.dms.domain.outing.spi.QueryOutingAvailableTimePort +import team.aliens.dms.domain.outing.spi.QueryOutingCompanionPort +import team.aliens.dms.domain.outing.spi.QueryOutingTypePort +import team.aliens.dms.domain.outing.spi.vo.CurrentOutingApplicationVO +import team.aliens.dms.domain.outing.spi.vo.OutingCompanionDetailsVO +import team.aliens.dms.domain.outing.spi.vo.OutingHistoryVO +import java.time.DayOfWeek +import java.time.LocalDate +import java.util.UUID + +@Service +class GetOutingServiceImpl( + private val queryOutingTypePort: QueryOutingTypePort, + private val queryOutingApplicationPort: QueryOutingApplicationPort, + private val queryOutingAvailableTimePort: QueryOutingAvailableTimePort, + private val queryOutingCompanionPort: QueryOutingCompanionPort +) : GetOutingService { + + override fun getOutingType(outingType: OutingType) = + queryOutingTypePort.queryOutingType(outingType) ?: throw OutingTypeNotFoundException + + override fun getAllOutingTypeTitlesBySchoolIdAndKeyword(schoolId: UUID, keyword: String?) = + queryOutingTypePort.queryAllOutingTypeTitlesBySchoolIdAndKeyword(schoolId, keyword) + + override fun getOutingApplicationById(outingApplicationId: UUID): OutingApplication = + queryOutingApplicationPort.queryOutingApplicationById(outingApplicationId) + ?: throw OutingApplicationNotFoundException + + override fun getAllOutingApplicationVOsBetweenStartAndEnd(start: LocalDate, end: LocalDate) = + queryOutingApplicationPort.queryAllOutingApplicationVOsBetweenStartAndEnd(start, end) + + override fun getCurrentOutingApplication(studentId: UUID): CurrentOutingApplicationVO = + queryOutingApplicationPort.queryCurrentOutingApplicationVO(studentId) + ?: throw OutingApplicationNotFoundException + + override fun getOutingHistoriesByStudentNameAndDate( + studentName: String?, + date: LocalDate + ): List = queryOutingApplicationPort.queryOutingHistoriesByStudentNameAndDate(studentName, date) + + override fun getOutingAvailableTimesByDayOfWeek( + dayOfWeek: DayOfWeek + ) = queryOutingAvailableTimePort.queryOutingAvailableTimesByDayOfWeek( + dayOfWeek = dayOfWeek + ) + + override fun getOutingCompanionsByApplicationId(outingApplicationId: UUID): List = + queryOutingCompanionPort.queryOutingCompanionsById(outingApplicationId) +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/OutingCompanionPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/OutingCompanionPort.kt index a08494d95..e18241364 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/OutingCompanionPort.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/OutingCompanionPort.kt @@ -1,4 +1,5 @@ package team.aliens.dms.domain.outing.spi interface OutingCompanionPort : + QueryOutingCompanionPort, CommandOutingCompanionPort diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/QueryOutingApplicationPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/QueryOutingApplicationPort.kt index 5ab09973b..0e19be051 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/QueryOutingApplicationPort.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/QueryOutingApplicationPort.kt @@ -9,7 +9,7 @@ import java.util.UUID interface QueryOutingApplicationPort { - fun existOutingApplicationByOutAtAndStudentId(outAt: LocalDate, studentId: UUID): Boolean + fun existOutingApplicationByOutingDateAndStudentId(outingDate: LocalDate, studentId: UUID): Boolean fun queryOutingApplicationById(outingApplicationId: UUID): OutingApplication? diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/QueryOutingCompanionPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/QueryOutingCompanionPort.kt new file mode 100644 index 000000000..c33f2e633 --- /dev/null +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/QueryOutingCompanionPort.kt @@ -0,0 +1,9 @@ +package team.aliens.dms.domain.outing.spi + +import team.aliens.dms.domain.outing.spi.vo.OutingCompanionDetailsVO +import java.util.UUID + +interface QueryOutingCompanionPort { + + fun queryOutingCompanionsById(outingApplicationId: UUID): List +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/CurrentOutingApplicationVO.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/CurrentOutingApplicationVO.kt index f33e0e6ea..a42b3c33a 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/CurrentOutingApplicationVO.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/CurrentOutingApplicationVO.kt @@ -1,15 +1,17 @@ -package team.aliens.dms.domain.outing.spi.vo - -import team.aliens.dms.domain.outing.model.OutingStatus -import java.time.LocalDate -import java.time.LocalTime - -open class CurrentOutingApplicationVO( - val outAt: LocalDate, - val outingTypeTitle: String, - val status: OutingStatus, - val outingTime: LocalTime, - val arrivalTime: LocalTime, - val reason: String?, - val outingCompanions: List -) +package team.aliens.dms.domain.outing.spi.vo + +import team.aliens.dms.domain.outing.model.OutingStatus +import java.time.LocalDate +import java.time.LocalTime +import java.util.UUID + +open class CurrentOutingApplicationVO( + val id: UUID, + val outingDate: LocalDate, + val outingTypeTitle: String, + val status: OutingStatus, + val outingTime: LocalTime, + val arrivalTime: LocalTime, + val reason: String?, + val outingCompanions: List +) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/OutingApplicationVO.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/OutingApplicationVO.kt index cda8a7fe8..44623470a 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/OutingApplicationVO.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/OutingApplicationVO.kt @@ -9,7 +9,7 @@ open class OutingApplicationVO( val studentGrade: Int, val studentClassRoom: Int, val studentNumber: Int, - val outAt: LocalDate, + val outingDate: LocalDate, val outingTime: LocalTime, val arrivalTime: LocalTime, val outingCompanionVOs: List diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/OutingCompanionDetailsVO.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/OutingCompanionDetailsVO.kt new file mode 100644 index 000000000..1f3db9ece --- /dev/null +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/spi/vo/OutingCompanionDetailsVO.kt @@ -0,0 +1,15 @@ +package team.aliens.dms.domain.outing.spi.vo + +import team.aliens.dms.domain.student.model.Student +import java.util.UUID + +open class OutingCompanionDetailsVO( + val id: UUID, + val studentName: String, + val studentGrade: Int, + val studentClassRoom: Int, + val studentNumber: Int, + val roomNumber: String +) { + val studentGcn: String = Student.processGcn(studentGrade, studentClassRoom, studentNumber) +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/usecase/ApplyOutingUseCase.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/usecase/ApplyOutingUseCase.kt index 5537066ca..a817eb7a0 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/usecase/ApplyOutingUseCase.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/usecase/ApplyOutingUseCase.kt @@ -1,47 +1,47 @@ -package team.aliens.dms.domain.outing.usecase - -import team.aliens.dms.common.annotation.UseCase -import team.aliens.dms.common.service.security.SecurityService -import team.aliens.dms.domain.outing.dto.ApplyOutingRequest -import team.aliens.dms.domain.outing.dto.ApplyOutingResponse -import team.aliens.dms.domain.outing.model.OutingApplication -import team.aliens.dms.domain.outing.model.OutingStatus -import team.aliens.dms.domain.outing.service.OutingService -import team.aliens.dms.domain.student.service.StudentService -import java.time.LocalDateTime - -@UseCase -class ApplyOutingUseCase( - private val outingService: OutingService, - private val studentService: StudentService, - private val securityService: SecurityService, -) { - - fun execute(request: ApplyOutingRequest): ApplyOutingResponse { - val student = studentService.getCurrentStudent() - - outingService.checkOutingApplicationAvailable( - studentId = student.id, - outAt = request.outAt, - outingTime = request.outingTime, - arrivalTime = request.arrivalTime - ) - - val outing = outingService.saveOutingApplication( - OutingApplication( - studentId = student.id, - createdAt = LocalDateTime.now(), - outAt = request.outAt, - outingTime = request.outingTime, - arrivalTime = request.arrivalTime, - status = OutingStatus.REQUESTED, - reason = request.reason, - outingTypeTitle = request.outingTypeTitle, - schoolId = securityService.getCurrentSchoolId(), - companionIds = request.companionIds - ) - ) - - return ApplyOutingResponse(outing.id) - } -} +package team.aliens.dms.domain.outing.usecase + +import team.aliens.dms.common.annotation.UseCase +import team.aliens.dms.common.service.security.SecurityService +import team.aliens.dms.domain.outing.dto.ApplyOutingRequest +import team.aliens.dms.domain.outing.dto.ApplyOutingResponse +import team.aliens.dms.domain.outing.model.OutingApplication +import team.aliens.dms.domain.outing.model.OutingStatus +import team.aliens.dms.domain.outing.service.OutingService +import team.aliens.dms.domain.student.service.StudentService +import java.time.LocalDateTime + +@UseCase +class ApplyOutingUseCase( + private val outingService: OutingService, + private val studentService: StudentService, + private val securityService: SecurityService, +) { + + fun execute(request: ApplyOutingRequest): ApplyOutingResponse { + val student = studentService.getCurrentStudent() + + outingService.checkOutingApplicationAvailable( + studentId = student.id, + outingDate = request.outingDate, + outingTime = request.outingTime, + arrivalTime = request.arrivalTime + ) + + val outing = outingService.saveOutingApplication( + OutingApplication( + studentId = student.id, + createdAt = LocalDateTime.now(), + outingDate = request.outingDate, + outingTime = request.outingTime, + arrivalTime = request.arrivalTime, + status = OutingStatus.APPROVED, + reason = request.reason, + outingTypeTitle = request.outingTypeTitle, + schoolId = securityService.getCurrentSchoolId(), + companionIds = request.companionIds + ) + ) + + return ApplyOutingResponse(outing.id) + } +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/usecase/GetOutingHistoryDetailsUseCase.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/usecase/GetOutingHistoryDetailsUseCase.kt new file mode 100644 index 000000000..0adba0244 --- /dev/null +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/outing/usecase/GetOutingHistoryDetailsUseCase.kt @@ -0,0 +1,23 @@ +package team.aliens.dms.domain.outing.usecase + +import team.aliens.dms.common.annotation.ReadOnlyUseCase +import team.aliens.dms.domain.outing.dto.OutingHistoryDetailsResponse +import team.aliens.dms.domain.outing.service.OutingService +import team.aliens.dms.domain.student.service.StudentService +import java.util.UUID + +@ReadOnlyUseCase +class GetOutingHistoryDetailsUseCase( + private val outingService: OutingService, + private val studentService: StudentService +) { + + fun execute(outingApplicationId: UUID): OutingHistoryDetailsResponse { + val outingHistory = outingService.getOutingApplicationById(outingApplicationId) + + val outingCompanions = outingService.getOutingCompanionsByApplicationId(outingApplicationId) + + val student = studentService.getStudentById(outingHistory.studentId) + return OutingHistoryDetailsResponse.of(outingHistory, outingCompanions, student) + } +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointService.kt index 5ca4f2cc1..c55859dcf 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointService.kt @@ -7,6 +7,7 @@ import team.aliens.dms.domain.point.model.PointOption import team.aliens.dms.domain.point.model.PointType import team.aliens.dms.domain.point.spi.vo.PointHistoryVO import team.aliens.dms.domain.point.spi.vo.StudentPointHistoryVO +import team.aliens.dms.domain.point.spi.vo.StudentTotalVO import team.aliens.dms.domain.point.spi.vo.StudentWithPointVO import java.time.LocalDateTime import java.util.UUID @@ -62,4 +63,6 @@ interface GetPointService { pointOption: PointOption, schoolId: UUID ): List + + fun getPointTotalsGroupByStudent(): List } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointServiceImpl.kt index d6e755baa..47fc41860 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/service/GetPointServiceImpl.kt @@ -11,6 +11,7 @@ import team.aliens.dms.domain.point.spi.QueryPhrasePort import team.aliens.dms.domain.point.spi.QueryPointHistoryPort import team.aliens.dms.domain.point.spi.QueryPointOptionPort import team.aliens.dms.domain.point.spi.vo.StudentPointHistoryVO +import team.aliens.dms.domain.point.spi.vo.StudentTotalVO import team.aliens.dms.domain.point.spi.vo.StudentWithPointVO import java.time.LocalDateTime import java.util.UUID @@ -19,7 +20,7 @@ import java.util.UUID class GetPointServiceImpl( private val queryPhrasePort: QueryPhrasePort, private val queryPointHistoryPort: QueryPointHistoryPort, - private val queryPointOptionPort: QueryPointOptionPort + private val queryPointOptionPort: QueryPointOptionPort, ) : GetPointService { override fun queryAllPhraseByPointTypeAndStandardPoint(type: PointType, standardPoint: Int) = @@ -115,4 +116,8 @@ class GetPointServiceImpl( ) } } + + override fun getPointTotalsGroupByStudent(): List { + return queryPointHistoryPort.queryPointTotalsGroupByStudent() + } } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/point/spi/QueryPointHistoryPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/spi/QueryPointHistoryPort.kt index 6b4b5f49d..694eb554b 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/point/spi/QueryPointHistoryPort.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/spi/QueryPointHistoryPort.kt @@ -5,6 +5,7 @@ import team.aliens.dms.domain.point.model.PointHistory import team.aliens.dms.domain.point.model.PointType import team.aliens.dms.domain.point.spi.vo.PointHistoryVO import team.aliens.dms.domain.point.spi.vo.StudentPointHistoryVO +import team.aliens.dms.domain.point.spi.vo.StudentTotalVO import java.time.LocalDateTime import java.util.UUID @@ -43,4 +44,6 @@ interface QueryPointHistoryPort { fun queryPointHistoryByGcnIn( gcns: List ): List + + fun queryPointTotalsGroupByStudent(): List } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/point/spi/vo/StudentTotalVO.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/spi/vo/StudentTotalVO.kt new file mode 100644 index 000000000..a6100114c --- /dev/null +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/point/spi/vo/StudentTotalVO.kt @@ -0,0 +1,9 @@ +package team.aliens.dms.domain.point.spi.vo + +import java.util.UUID + +open class StudentTotalVO( + val studentId: UUID, + val bonusTotal: Int, + val minusTotal: Int +) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/model/RemainAvailableTime.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/model/RemainAvailableTime.kt index 46ea8be23..07e499f12 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/model/RemainAvailableTime.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/model/RemainAvailableTime.kt @@ -22,8 +22,7 @@ data class RemainAvailableTime( ) { - fun checkAvailable() { - val currentDateTime = LocalDateTime.now() + fun checkAvailable(currentDateTime: LocalDateTime) { val dayOfWeek = currentDateTime.dayOfWeek.value val now = currentDateTime.toLocalTime() diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ApplyRemainUseCase.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ApplyRemainUseCase.kt index ccb49ca74..2711d7225 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ApplyRemainUseCase.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ApplyRemainUseCase.kt @@ -19,7 +19,7 @@ class ApplyRemainUseCase( val remainOption = remainService.getRemainOptionById(remainOptionId) remainService.getRemainAvailableTimeBySchoolId(student.schoolId) - .apply { checkAvailable() } + .apply { checkAvailable(LocalDateTime.now()) } remainService.saveRemainStatus( RemainStatus( diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ExportRemainStatusUseCase.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ExportRemainStatusUseCase.kt index 715174487..cf136fe8f 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ExportRemainStatusUseCase.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/remain/usecase/ExportRemainStatusUseCase.kt @@ -22,7 +22,6 @@ class ExportRemainStatusUseCase( ) { fun execute(): ExportRemainStatusResponse { - val user = userService.getCurrentUser() val school = schoolService.getSchoolById(user.schoolId) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/CommandRoomServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/CommandRoomServiceImpl.kt index b50792d89..bafc1a9af 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/CommandRoomServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/CommandRoomServiceImpl.kt @@ -1,6 +1,6 @@ package team.aliens.dms.domain.room.service -import org.springframework.stereotype.Service +import team.aliens.dms.common.annotation.Service import team.aliens.dms.domain.room.model.Room import team.aliens.dms.domain.room.spi.CommandRoomPort import team.aliens.dms.domain.room.spi.QueryRoomPort diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt index 12beb096f..e5c22d442 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt @@ -1,6 +1,6 @@ package team.aliens.dms.domain.room.service -import org.springframework.stereotype.Service +import team.aliens.dms.common.annotation.Service @Service class RoomService( diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/school/dto/SchoolResponse.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/school/dto/SchoolResponse.kt index 3cb7ca134..9373c1bfa 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/school/dto/SchoolResponse.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/school/dto/SchoolResponse.kt @@ -30,7 +30,8 @@ data class AvailableFeaturesResponse( val noticeService: Boolean, val pointService: Boolean, val studyRoomService: Boolean, - val remainService: Boolean + val remainService: Boolean, + val outingService: Boolean ) data class NeisSchoolResponse( diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/school/model/AvailableFeature.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/school/model/AvailableFeature.kt index 45e5da87b..0e7971a8b 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/school/model/AvailableFeature.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/school/model/AvailableFeature.kt @@ -16,6 +16,8 @@ data class AvailableFeature( val studyRoomService: Boolean, - val remainService: Boolean + val remainService: Boolean, + + val outingService: Boolean ) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/school/usecase/QueryAvailableFeaturesUseCase.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/school/usecase/QueryAvailableFeaturesUseCase.kt index cefc2ba7c..d2ee93684 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/school/usecase/QueryAvailableFeaturesUseCase.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/school/usecase/QueryAvailableFeaturesUseCase.kt @@ -20,7 +20,8 @@ class QueryAvailableFeaturesUseCase( noticeService = availableFeatures.noticeService, pointService = availableFeatures.pointService, studyRoomService = availableFeatures.studyRoomService, - remainService = availableFeatures.remainService + remainService = availableFeatures.remainService, + outingService = availableFeatures.outingService ) } } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/student/dto/StudentResponse.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/student/dto/StudentResponse.kt index f8e621767..3fba13841 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/student/dto/StudentResponse.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/student/dto/StudentResponse.kt @@ -112,6 +112,8 @@ data class StudentsResponse( roomNumber = it.roomNumber, profileImageUrl = it.profileImageUrl, sex = it.sex, + bonusPoint = it.bonusPoint, + minusPoint = it.minusPoint, tags = it.tags.map { tag -> TagResponse.of(tag) } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentService.kt index 5e24d9ff9..45d78ce65 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentService.kt @@ -38,6 +38,8 @@ interface GetStudentService { fun getStudentsBySchoolId(schoolId: UUID): List + fun getAllStudentWithMinusPoint(): List> + fun getAllStudentsByIdsIn(studentIds: List): List fun getGcnUpdatedStudent( diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentServiceImpl.kt index 0c1cbc8bf..9c8089d58 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/student/service/GetStudentServiceImpl.kt @@ -5,6 +5,7 @@ import team.aliens.dms.common.spi.SecurityPort import team.aliens.dms.domain.file.spi.vo.ExcelStudentVO import team.aliens.dms.domain.manager.dto.PointFilter import team.aliens.dms.domain.manager.dto.Sort +import team.aliens.dms.domain.point.spi.QueryPointHistoryPort import team.aliens.dms.domain.room.exception.RoomNotFoundException import team.aliens.dms.domain.room.model.Room import team.aliens.dms.domain.student.exception.StudentNotFoundException @@ -17,7 +18,8 @@ import java.util.function.Function @Service class GetStudentServiceImpl( private val securityPort: SecurityPort, - private val queryStudentPort: QueryStudentPort + private val queryStudentPort: QueryStudentPort, + private val queryPointHistoryPort: QueryPointHistoryPort ) : GetStudentService { override fun getCurrentStudent(): Student { @@ -65,6 +67,15 @@ class GetStudentServiceImpl( override fun getStudentsBySchoolId(schoolId: UUID) = queryStudentPort.queryStudentsBySchoolId(schoolId) + override fun getAllStudentWithMinusPoint(): List> = + queryStudentPort.queryAllStudentsByName("").map { student -> + val minusTotalPoint = queryPointHistoryPort.queryBonusAndMinusTotalPointByStudentGcnAndName( + gcn = student.gcn, + studentName = student.name + ).second + Pair(student.id, minusTotalPoint) + } + override fun getAllStudentsByIdsIn(studentIds: List) = queryStudentPort.queryAllStudentsByIdsIn(studentIds) .also { students -> diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/model/AvailableTime.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/model/AvailableTime.kt index 303a8770f..2a53048bc 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/model/AvailableTime.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/model/AvailableTime.kt @@ -14,9 +14,7 @@ data class AvailableTime( val endAt: LocalTime ) { - fun isAvailable(): Boolean { - val now = LocalTime.now() - + fun isAvailable(now: LocalTime): Boolean { if ((startAt < endAt && (isBeforeStartTime(now) || isAfterEndTime(now))) || startAt > endAt && (isBeforeStartTime(now) && isAfterEndTime(now)) ) { diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/service/CheckStudyRoomServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/service/CheckStudyRoomServiceImpl.kt index ff816ffab..1fae14830 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/service/CheckStudyRoomServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/service/CheckStudyRoomServiceImpl.kt @@ -6,6 +6,7 @@ import team.aliens.dms.domain.studyroom.exception.SeatCanNotAppliedException import team.aliens.dms.domain.studyroom.exception.StudyRoomAlreadyExistsException import team.aliens.dms.domain.studyroom.exception.StudyRoomTimeSlotNotFoundException import team.aliens.dms.domain.studyroom.spi.QueryStudyRoomPort +import java.time.LocalTime import java.util.UUID @Service @@ -32,7 +33,7 @@ class CheckStudyRoomServiceImpl( override fun checkStudyRoomApplicationTimeAvailable(schoolId: UUID) { val availableTime = queryStudyRoomPort.queryAvailableTimeBySchoolId(schoolId) ?: throw AvailableTimeNotFoundException - if (!availableTime.isAvailable()) { + if (!availableTime.isAvailable(LocalTime.now())) { throw SeatCanNotAppliedException } } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/ApplySeatUseCase.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/ApplySeatUseCase.kt index 7ddbf9ecc..3e9c68760 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/ApplySeatUseCase.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/studyroom/usecase/ApplySeatUseCase.kt @@ -13,7 +13,6 @@ class ApplySeatUseCase( ) { fun execute(seatId: UUID, timeSlotId: UUID) { - val student = studentService.getCurrentStudent() val seat = studyRoomService.getSeatById(seatId) diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/model/WarningTag.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/model/WarningTag.kt new file mode 100644 index 000000000..d6619e471 --- /dev/null +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/model/WarningTag.kt @@ -0,0 +1,32 @@ +package team.aliens.dms.domain.tag.model + +enum class WarningTag(warningMessage: String) { + SAFE(""), + FIRST_WARNING("1차 경고"), + SECOND_WARNING("2차 경고"), + THIRD_WARNING("3차 경고"), + ONE_OUT("OUT 1"), + TWO_OUT("OUT 2"), + THREE_OUT("OUT 3"); + + companion object { + fun byPoint(minusPoint: Int) = when { + 40 <= minusPoint -> THREE_OUT + 35 <= minusPoint -> TWO_OUT + 30 <= minusPoint -> ONE_OUT + 25 <= minusPoint -> THIRD_WARNING + 20 <= minusPoint -> SECOND_WARNING + 15 <= minusPoint -> FIRST_WARNING + else -> SAFE + } + + fun getAllNames(): List = listOf( + FIRST_WARNING.name, + SECOND_WARNING.name, + THIRD_WARNING.name, + ONE_OUT.name, + TWO_OUT.name, + THREE_OUT.name + ) + } +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagService.kt index 845f8370e..41268d8ae 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagService.kt @@ -6,11 +6,15 @@ import java.util.UUID interface CommandTagService { + fun deleteAllStudentTagsByTagIdIn(tagIds: List) + fun deleteStudentTagById(studentId: UUID, tagId: UUID) fun deleteStudentTagAndTagById(tagId: UUID) fun saveTag(tag: Tag): Tag + fun saveStudentTag(studentTag: StudentTag): StudentTag + fun saveAllStudentTags(studentTags: List) } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagServiceImpl.kt index 62557152c..e3405afa8 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/CommandTagServiceImpl.kt @@ -13,6 +13,10 @@ class CommandTagServiceImpl( private val commandTagPort: CommandTagPort ) : CommandTagService { + override fun deleteAllStudentTagsByTagIdIn(tagIds: List) { + commandStudentTagPort.deleteAllStudentTagsByTagIdIn(tagIds) + } + override fun deleteStudentTagById(studentId: UUID, tagId: UUID) { commandStudentTagPort.deleteStudentTagById(studentId, tagId) } @@ -26,6 +30,9 @@ class CommandTagServiceImpl( return commandTagPort.saveTag(tag) } + override fun saveStudentTag(studentTag: StudentTag): StudentTag = + commandStudentTagPort.saveStudentTag(studentTag) + override fun saveAllStudentTags(studentTags: List) { commandStudentTagPort.saveAllStudentTags(studentTags) } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagService.kt index 0a1dd1eeb..492bfd346 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagService.kt @@ -1,10 +1,17 @@ package team.aliens.dms.domain.tag.service +import team.aliens.dms.domain.tag.model.StudentTag import team.aliens.dms.domain.tag.model.Tag import java.util.UUID interface GetTagService { + fun getStudentTagsByStudentId(studentId: UUID): List + + fun getAllWarningTags(names: List): List + + fun getTagByName(name: String): Tag + fun getTagById(tagId: UUID): Tag fun getTagsBySchoolId(schoolId: UUID): List diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagServiceImpl.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagServiceImpl.kt index d6724a194..3b406bd4b 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagServiceImpl.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/service/GetTagServiceImpl.kt @@ -2,15 +2,27 @@ package team.aliens.dms.domain.tag.service import team.aliens.dms.common.annotation.Service import team.aliens.dms.domain.tag.exception.TagNotFoundException +import team.aliens.dms.domain.tag.model.StudentTag import team.aliens.dms.domain.tag.model.Tag +import team.aliens.dms.domain.tag.spi.QueryStudentTagPort import team.aliens.dms.domain.tag.spi.QueryTagPort import java.util.UUID @Service class GetTagServiceImpl( - private val queryTagPort: QueryTagPort + private val queryTagPort: QueryTagPort, + private val queryStudentTagPort: QueryStudentTagPort ) : GetTagService { + override fun getStudentTagsByStudentId(studentId: UUID): List = + queryStudentTagPort.queryStudentTagsByStudentId(studentId) + + override fun getAllWarningTags(names: List): List = + queryTagPort.queryAllWarningTags(names) + + override fun getTagByName(name: String) = + queryTagPort.queryTagByName(name) ?: throw TagNotFoundException + override fun getTagById(tagId: UUID) = queryTagPort.queryTagById(tagId) ?: throw TagNotFoundException diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/CommandStudentTagPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/CommandStudentTagPort.kt index 09531fbb8..1fc2919de 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/CommandStudentTagPort.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/CommandStudentTagPort.kt @@ -5,9 +5,13 @@ import java.util.UUID interface CommandStudentTagPort { + fun deleteAllStudentTagsByTagIdIn(tagIds: List) + fun deleteStudentTagById(studentId: UUID, tagId: UUID) fun deleteStudentTagByTagId(tagId: UUID) + fun saveStudentTag(studentTag: StudentTag): StudentTag + fun saveAllStudentTags(studentTags: List) } diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/QueryStudentTagPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/QueryStudentTagPort.kt new file mode 100644 index 000000000..5b762065b --- /dev/null +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/QueryStudentTagPort.kt @@ -0,0 +1,9 @@ +package team.aliens.dms.domain.tag.spi + +import team.aliens.dms.domain.tag.model.StudentTag +import java.util.UUID + +interface QueryStudentTagPort { + + fun queryStudentTagsByStudentId(studentId: UUID): List +} diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/QueryTagPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/QueryTagPort.kt index 8c1db8718..a5289be62 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/QueryTagPort.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/QueryTagPort.kt @@ -5,10 +5,14 @@ import java.util.UUID interface QueryTagPort { + fun queryAllWarningTags(names: List): List + fun queryTagsBySchoolId(schoolId: UUID): List fun queryTagById(tagId: UUID): Tag? + fun queryTagByName(name: String): Tag? + fun existsByNameAndSchoolId(name: String, schoolId: UUID): Boolean fun queryTagsByStudentId(studentId: UUID): List diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/StudentTagPort.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/StudentTagPort.kt index 48ecb05c6..dfa099039 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/StudentTagPort.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/spi/StudentTagPort.kt @@ -1,4 +1,5 @@ package team.aliens.dms.domain.tag.spi interface StudentTagPort : + QueryStudentTagPort, CommandStudentTagPort diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/usecase/UpdateStudentTagsUseCase.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/usecase/UpdateStudentTagsUseCase.kt new file mode 100644 index 000000000..d8395c7a4 --- /dev/null +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/tag/usecase/UpdateStudentTagsUseCase.kt @@ -0,0 +1,36 @@ +package team.aliens.dms.domain.tag.usecase + +import team.aliens.dms.common.annotation.SchedulerUseCase +import team.aliens.dms.domain.point.service.PointService +import team.aliens.dms.domain.tag.model.StudentTag +import team.aliens.dms.domain.tag.model.WarningTag +import team.aliens.dms.domain.tag.service.TagService +import java.time.LocalDateTime +import java.util.UUID + +@SchedulerUseCase +class UpdateStudentTagsUseCase( + private val pointService: PointService, + private val tagService: TagService, +) { + fun execute() { + val warningTagMap: Map = tagService.getAllWarningTags( + WarningTag.getAllNames() + ).associate { it.name to it.id } + + tagService.deleteAllStudentTagsByTagIdIn(warningTagMap.values.toList()) + + val saveList: List = pointService.getPointTotalsGroupByStudent().mapNotNull { + val warningTag = WarningTag.byPoint(it.minusTotal) + if (warningTag != WarningTag.SAFE) { + StudentTag( + it.studentId, + warningTagMap[warningTag.name]!!, + LocalDateTime.now() + ) + } else null + } + + tagService.saveAllStudentTags(saveList) + } +} diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/auth/model/AuthCodeTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/auth/model/AuthCodeTest.kt new file mode 100644 index 000000000..d6ba5f9ef --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/auth/model/AuthCodeTest.kt @@ -0,0 +1,34 @@ +package team.aliens.dms.domain.auth.model + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import team.aliens.dms.domain.auth.exception.AuthCodeMismatchException +import team.aliens.dms.domain.auth.stub.createAuthCodeStub + +class AuthCodeTest : DescribeSpec({ + + describe("validateAuthCode") { + val authCode = createAuthCodeStub() + + context("인증 코드가 같다면") { + val code = "123546" + + it("인증에 성공한다") { + shouldNotThrowAny { + authCode.validateAuthCode(code) + } + } + } + + context("인증 코드가 다르면") { + val wrongAuthCOde = "000000" + + it("인증에 실패한다") { + shouldThrow { + authCode.validateAuthCode(wrongAuthCOde) + } + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/model/OutingApplicationTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/model/OutingApplicationTest.kt new file mode 100644 index 000000000..f278a196e --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/model/OutingApplicationTest.kt @@ -0,0 +1,32 @@ +package team.aliens.dms.domain.outing.model + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import team.aliens.dms.domain.outing.exception.OutingTypeMismatchException +import team.aliens.dms.domain.outing.stub.createOutingApplicationStub + +class OutingApplicationTest : DescribeSpec({ + + describe("checkCancelable") { + context("외출 신청 상태가 REQUESTED이면") { + val outingApplication = createOutingApplicationStub(outingStatus = OutingStatus.APPROVED) + + it("외출 취소가 가능하다") { + shouldNotThrowAny { + outingApplication.checkCancelable(OutingStatus.APPROVED) + } + } + } + + context("외출 신청 상태가 REQUESTED가 아니면") { + val outingApplication = createOutingApplicationStub(outingStatus = OutingStatus.APPROVED) + + it("외출 취소가 불가능하다") { + shouldThrow { + outingApplication.checkCancelable(OutingStatus.DONE) + } + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/model/OutingAvailableTimeTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/model/OutingAvailableTimeTest.kt new file mode 100644 index 000000000..f969c61bd --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/model/OutingAvailableTimeTest.kt @@ -0,0 +1,68 @@ +package team.aliens.dms.domain.outing.model + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import team.aliens.dms.domain.outing.exception.OutingAvailableTimeMismatchException +import team.aliens.dms.domain.outing.stub.createOutingAvailableTimeStub +import java.time.DayOfWeek +import java.time.LocalTime + +class OutingAvailableTimeTest : DescribeSpec({ + + describe("checkAvailable") { + val outingAvailableTime = createOutingAvailableTimeStub( + dayOfWeek = DayOfWeek.SUNDAY, + outingTime = LocalTime.of(12, 0, 0), + arrivalTime = LocalTime.of(20, 30, 0) + ) + + context("외출 신청한 시간이 외출 가능 시간이면") { + it("외출 신청이 가능하다") { + shouldNotThrowAny { + outingAvailableTime.checkAvailable( + dayOfWeek = DayOfWeek.SUNDAY, + outingTime = LocalTime.of(12, 0, 0), + arrivalTime = LocalTime.of(20, 30, 0) + ) + } + } + } + + context("외출하는 날이 아닐 때 외출 신청을 하면") { + it("예외가 발생한다") { + shouldThrow { + outingAvailableTime.checkAvailable( + dayOfWeek = DayOfWeek.SATURDAY, + outingTime = LocalTime.of(14, 0, 0), + arrivalTime = LocalTime.of(20, 0, 0) + ) + } + } + } + + context("외출 가능 시간 전에 외출 신청을 하면") { + it("예외가 발생한다") { + shouldThrow { + outingAvailableTime.checkAvailable( + dayOfWeek = DayOfWeek.SATURDAY, + outingTime = LocalTime.of(11, 59, 59), + arrivalTime = LocalTime.of(20, 0, 0) + ) + } + } + } + + context("외출 도착 시간 후에 외출 신청을 하면") { + it("예외가 발생한다") { + shouldThrow { + outingAvailableTime.checkAvailable( + dayOfWeek = DayOfWeek.SATURDAY, + outingTime = LocalTime.of(14, 0, 0), + arrivalTime = LocalTime.of(20, 30, 1) + ) + } + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/stub/OutingStub.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/stub/OutingStub.kt new file mode 100644 index 000000000..db6b0ef40 --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/outing/stub/OutingStub.kt @@ -0,0 +1,51 @@ +package team.aliens.dms.domain.outing.stub + +import team.aliens.dms.domain.outing.model.OutingApplication +import team.aliens.dms.domain.outing.model.OutingAvailableTime +import team.aliens.dms.domain.outing.model.OutingStatus +import java.time.DayOfWeek +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.UUID + +internal fun createOutingApplicationStub( + id: UUID = UUID.randomUUID(), + studentId: UUID = UUID.randomUUID(), + createdAt: LocalDateTime = LocalDateTime.now(), + outingDate: LocalDate = LocalDate.now(), + outingTime: LocalTime = LocalTime.now(), + arrivalTime: LocalTime = LocalTime.now(), + outingStatus: OutingStatus = OutingStatus.REQUESTED, + reason: String? = null, + outingTypeTitle: String = "식사 외출", + schoolId: UUID = UUID.randomUUID(), + companionIds: List? = null +) = OutingApplication( + id = id, + studentId = studentId, + createdAt = createdAt, + outingDate = outingDate, + outingTime = outingTime, + arrivalTime = arrivalTime, + status = outingStatus, + reason = reason, + outingTypeTitle = outingTypeTitle, + schoolId = schoolId +) + +internal fun createOutingAvailableTimeStub( + id: UUID = UUID.randomUUID(), + schoolId: UUID = UUID.randomUUID(), + outingTime: LocalTime = LocalTime.now(), + arrivalTime: LocalTime = LocalTime.now(), + enabled: Boolean = true, + dayOfWeek: DayOfWeek = DayOfWeek.SUNDAY +) = OutingAvailableTime( + id = id, + schoolId = schoolId, + outingTime = outingTime, + arrivalTime = arrivalTime, + enabled = enabled, + dayOfWeek = dayOfWeek +) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/point/model/PointHistoryTests.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/point/model/PointHistoryTests.kt index c6b7defc5..737768bba 100644 --- a/dms-core/src/test/kotlin/team/aliens/dms/domain/point/model/PointHistoryTests.kt +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/point/model/PointHistoryTests.kt @@ -1,65 +1,82 @@ package team.aliens.dms.domain.point.model -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertAll -import org.junit.jupiter.api.assertThrows +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe +import team.aliens.dms.domain.point.dto.PointRequestType import team.aliens.dms.domain.point.exception.PointHistoryCanNotCancelException -import java.time.LocalDateTime -import java.util.UUID - -class PointHistoryTests { - - @Test - fun `취소 내역 반환`() { - // given - val pointHistory = PointHistory( - studentName = "김은빈", - studentGcn = "2106", - bonusTotal = 3, - minusTotal = 0, - isCancel = false, - pointName = "분리수거", - pointScore = 3, - pointType = PointType.BONUS, - createdAt = LocalDateTime.of(2023, 3, 5, 12, 0), - schoolId = UUID.randomUUID() - ) +import team.aliens.dms.domain.point.stub.createPointHistoryStub +class PointHistoryTests : DescribeSpec({ + + describe("cancelHistory") { val pointTotal = Pair(6, 5) - // when - val canceledHistory = pointHistory.cancelHistory(pointTotal) + context("상벌점 내역을 취소하지 않았다면") { + val pointHistory = createPointHistoryStub() + + val canceledPointHistory = pointHistory.cancelHistory(pointTotal) + + it("상벌점 내역을 취소 후 반환한다") { + canceledPointHistory.isCancel shouldBe true + } + } + + context("상벌점 내역을 이미 취소했다면") { + val pointHistory = createPointHistoryStub(isCancel = true) - // then - assertAll( - { assertEquals(canceledHistory.bonusTotal, 3) }, - { assertEquals(canceledHistory.minusTotal, 5) }, - { assertEquals(canceledHistory.isCancel, true) } - ) + it("예외가 발생한다") { + shouldThrow { + pointHistory.cancelHistory(pointTotal) + } + } + } } - @Test - fun `취소할 수 없는 내역`() { - // given - val canceledPointHistory = PointHistory( - studentName = "김은빈", - studentGcn = "2106", - bonusTotal = 3, - minusTotal = 0, - isCancel = true, - pointName = "분리수거", - pointScore = 3, - pointType = PointType.BONUS, - createdAt = LocalDateTime.of(2023, 3, 5, 12, 0), - schoolId = UUID.randomUUID() - ) - - val pointTotal = Pair(3, 0) - - // when & then - assertThrows { - canceledPointHistory.cancelHistory(pointTotal) + describe("getTotalPoint") { + val bonusTotal = 10 + val minusTotal = 0 + + context("상벌점 타입이 BONUS이면") { + val pointType = PointRequestType.BONUS + + val totalPoint = PointHistory.getTotalPoint( + type = pointType, + bonusTotal = bonusTotal, + minusTotal = minusTotal + ) + + it("상점만 반환한다") { + totalPoint shouldBe bonusTotal + } + } + + context("상벌점 타입이 MINUS이면") { + val pointType = PointRequestType.MINUS + + val totalPoint = PointHistory.getTotalPoint( + type = pointType, + bonusTotal = bonusTotal, + minusTotal = minusTotal + ) + + it("벌점만 반환한다") { + totalPoint shouldBe minusTotal + } + } + + context("상벌점 타입이 ALL이면") { + val pointType = PointRequestType.ALL + + val totalPoint = PointHistory.getTotalPoint( + type = pointType, + bonusTotal = bonusTotal, + minusTotal = minusTotal + ) + + it("상벌점 총합을 반환한다") { + totalPoint shouldBe bonusTotal + minusTotal + } } } -} +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/remain/model/RemainAvailableTimeTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/remain/model/RemainAvailableTimeTest.kt new file mode 100644 index 000000000..0f627b04c --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/remain/model/RemainAvailableTimeTest.kt @@ -0,0 +1,62 @@ +package team.aliens.dms.domain.remain.model + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import team.aliens.dms.domain.remain.exception.RemainCanNotAppliedException +import team.aliens.dms.domain.remain.stub.createRemainAvailableTimeStub +import java.time.DayOfWeek +import java.time.LocalDateTime +import java.time.LocalTime + +class RemainAvailableTimeTest : DescribeSpec({ + + describe("checkAvailable") { + val remainAvailableTime = createRemainAvailableTimeStub( + startDayOfWeek = DayOfWeek.THURSDAY, + startTime = LocalTime.of(8, 30, 0), + endDayOfWeek = DayOfWeek.THURSDAY, + endTime = LocalTime.of(10, 0, 0) + ) + + context("잔류 신청한 시간이 잔류 신청 가능 시간이면") { + it("잔류 신청이 가능하다") { + shouldNotThrowAny { + remainAvailableTime.checkAvailable( + LocalDateTime.of(2024, 3, 28, 8, 30) + ) + } + } + } + + context("잔류 신청하는 날이 아니면") { + it("잔류 신청이 불가능하다") { + shouldThrow { + remainAvailableTime.checkAvailable( + LocalDateTime.of(2024, 3, 28, 8, 29) + ) + } + } + } + + context("잔류 신청 시간 이전에 외출 신청하면") { + it("잔류 신청이 불가능하다") { + shouldThrow { + remainAvailableTime.checkAvailable( + LocalDateTime.of(2024, 3, 28, 8, 29) + ) + } + } + } + + context("잔류 신청 시간 이후에 외출 신청하면") { + it("잔류 신청이 불가능하다") { + shouldThrow { + remainAvailableTime.checkAvailable( + LocalDateTime.of(2024, 3, 28, 10, 1) + ) + } + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/school/stub/SchoolStub.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/school/stub/SchoolStub.kt index 95288cd45..ed765ce0f 100644 --- a/dms-core/src/test/kotlin/team/aliens/dms/domain/school/stub/SchoolStub.kt +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/school/stub/SchoolStub.kt @@ -32,11 +32,13 @@ internal fun createAvailableFeatureStub( remainService: Boolean = true, pointService: Boolean = true, noticeService: Boolean = true, + outingService: Boolean = true ) = AvailableFeature( schoolId = schoolId, mealService = mealService, studyRoomService = studyRoomService, remainService = remainService, pointService = pointService, - noticeService = noticeService + noticeService = noticeService, + outingService = outingService ) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/student/model/SexTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/student/model/SexTest.kt new file mode 100644 index 000000000..5caddbe1a --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/student/model/SexTest.kt @@ -0,0 +1,35 @@ +package team.aliens.dms.domain.student.model + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe +import team.aliens.dms.domain.student.exception.SexMismatchException + +class SexTest : DescribeSpec({ + + describe("transferToSex") { + context("성별이 남자면") { + val sex = Sex.transferToSex("남") + + it("MALE을 반환한다") { + sex shouldBe Sex.MALE + } + } + + context("성별이 여자면") { + val sex = Sex.transferToSex("여") + + it("FEMALE을 반환한다") { + sex shouldBe Sex.FEMALE + } + } + + context("성별 타입이 전체이면") { + it("에러가 발생한다") { + shouldThrow { + Sex.transferToSex("전체") + } + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/student/model/StudentTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/student/model/StudentTest.kt new file mode 100644 index 000000000..cc2df6488 --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/student/model/StudentTest.kt @@ -0,0 +1,17 @@ +package team.aliens.dms.domain.student.model + +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe + +class StudentTest : DescribeSpec({ + + describe("processGcn") { + context("학년, 반, 번호를 받으면") { + val gcn = Student.processGcn(3, 2, 1) + + it("학번 4자리를 반환한다") { + gcn shouldBe "3201" + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/AvailableTimeTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/AvailableTimeTest.kt new file mode 100644 index 000000000..b8f564aec --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/AvailableTimeTest.kt @@ -0,0 +1,40 @@ +package team.aliens.dms.domain.studyroom.model + +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe +import team.aliens.dms.domain.studyroom.stub.createAvailableTime +import java.time.LocalTime + +class AvailableTimeTest : DescribeSpec({ + + describe("isAvailable") { + val availableTime = createAvailableTime( + startAt = LocalTime.of(20, 30, 0), + endAt = LocalTime.of(23, 50, 0) + ) + + context("자습실을 신청한 시간이 자습실 신청 가능 시간이라면") { + val isAvailable = availableTime.isAvailable(LocalTime.of(20, 30, 0)) + + it("자습실 신청이 가능하다") { + isAvailable shouldBe true + } + } + + context("자습실을 신청한 시간이 자습실 신청 가능 시간 이전이면") { + val isAvailable = availableTime.isAvailable(LocalTime.of(20, 29, 59)) + + it("자습실 신청이 불가능하다") { + isAvailable shouldBe false + } + } + + context("자습실을 신청한 시간이 자습실 신청 가능 시간 이후이면") { + val isAvailable = availableTime.isAvailable(LocalTime.of(23, 50, 1)) + + it("자습실 신청이 불가능하다") { + isAvailable shouldBe false + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/SeatTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/SeatTest.kt new file mode 100644 index 000000000..798f3c360 --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/SeatTest.kt @@ -0,0 +1,42 @@ +package team.aliens.dms.domain.studyroom.model + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import team.aliens.dms.domain.studyroom.exception.SeatCanNotAppliedException +import team.aliens.dms.domain.studyroom.stub.createSeatStub + +class SeatTest : DescribeSpec({ + + describe("checkAvailable") { + context("자리 상태가 AVAILABLE이면") { + val seat = createSeatStub(status = SeatStatus.AVAILABLE) + + it("자리를 이용할 수 있다") { + shouldNotThrowAny { + seat.checkAvailable() + } + } + } + + context("자리 상태가 UNAVAILABLE이면") { + val seat = createSeatStub(status = SeatStatus.UNAVAILABLE) + + it("자리를 이용할 수 없다") { + shouldThrow { + seat.checkAvailable() + } + } + } + + context("자리 상태가 EMPTY이면") { + val seat = createSeatStub(status = SeatStatus.EMPTY) + + it("자리를 이용할 수 없다") { + shouldThrow { + seat.checkAvailable() + } + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/StudyRoomTest.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/StudyRoomTest.kt new file mode 100644 index 000000000..bac91b9a3 --- /dev/null +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/model/StudyRoomTest.kt @@ -0,0 +1,76 @@ +package team.aliens.dms.domain.studyroom.model + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.DescribeSpec +import team.aliens.dms.domain.student.model.Sex +import team.aliens.dms.domain.studyroom.exception.StudyRoomAvailableGradeMismatchException +import team.aliens.dms.domain.studyroom.exception.StudyRoomAvailableSexMismatchException +import team.aliens.dms.domain.studyroom.stub.createStudyRoomStub + +class StudyRoomTest : DescribeSpec({ + + describe("checkIsAvailableGradeAndSex") { + context("현재 학생의 학년, 성별과 자습실 이용 가능한 학년, 성별이 같으면") { + val studyRoom = createStudyRoomStub(availableGrade = 3, availableSex = Sex.MALE) + val grade = 3 + val sex = Sex.MALE + + it("자습실을 이용할 수 있다") { + shouldNotThrowAny { + studyRoom.checkIsAvailableGradeAndSex(grade, sex) + } + } + } + + context("자습실 이용 가능한 학년이 0이면") { + val studyRoom = createStudyRoomStub(availableGrade = 0, availableSex = Sex.MALE) + val sex = Sex.MALE + + it("모든 학년이 자습실을 이용할 수 있다") { + (1..3).forEach { grade -> + shouldNotThrowAny { + studyRoom.checkIsAvailableGradeAndSex(grade, sex) + } + } + } + } + + context("자습실 이용 가능한 성별이 ALL이면") { + val studyRoom = createStudyRoomStub(availableGrade = 3, availableSex = Sex.ALL) + val grade = 3 + + it("같은 학년의 모든 학생이 자습실을 이용할 수 있다") { + Sex.entries.forEach { sex -> + shouldNotThrowAny { + studyRoom.checkIsAvailableGradeAndSex(grade, sex) + } + } + } + } + + context("자습실 이용 가능한 학년이 다르면") { + val studyRoom = createStudyRoomStub(availableGrade = 3, availableSex = Sex.MALE) + val grade = 2 + val sex = Sex.MALE + + it("자습실을 이용할 수 없다") { + shouldThrow { + studyRoom.checkIsAvailableGradeAndSex(grade, sex) + } + } + } + + context("자습실 이용 가능한 성별이 다르면") { + val studyRoom = createStudyRoomStub(availableGrade = 3, availableSex = Sex.MALE) + val grade = 3 + val sex = Sex.FEMALE + + it("자습실을 이용할 수 없다") { + shouldThrow { + studyRoom.checkIsAvailableGradeAndSex(grade, sex) + } + } + } + } +}) diff --git a/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt index 2942c1600..1fc169052 100644 --- a/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt +++ b/dms-core/src/test/kotlin/team/aliens/dms/domain/studyroom/stub/StudyRoomStub.kt @@ -1,6 +1,7 @@ package team.aliens.dms.domain.studyroom.stub import team.aliens.dms.domain.student.model.Sex +import team.aliens.dms.domain.studyroom.model.AvailableTime import team.aliens.dms.domain.studyroom.model.Seat import team.aliens.dms.domain.studyroom.model.SeatApplication import team.aliens.dms.domain.studyroom.model.SeatStatus @@ -91,3 +92,13 @@ internal fun createSeatTypeStub( name = name, color = color ) + +internal fun createAvailableTime( + schoolId: UUID = UUID.randomUUID(), + startAt: LocalTime = LocalTime.now(), + endAt: LocalTime = LocalTime.now() +) = AvailableTime( + schoolId = schoolId, + startAt = startAt, + endAt = endAt +) diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/global/security/SecurityConfig.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/global/security/SecurityConfig.kt index 5a18aa536..316f03493 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/global/security/SecurityConfig.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/global/security/SecurityConfig.kt @@ -178,6 +178,7 @@ class SecurityConfig( .requestMatchers(HttpMethod.GET, "/outings/my").hasAuthority(STUDENT.name) .requestMatchers(HttpMethod.GET, "/outings/histories").hasAuthority(MANAGER.name) .requestMatchers(HttpMethod.GET, "/outings/available-time").hasAnyAuthority(STUDENT.name, MANAGER.name) + .requestMatchers(HttpMethod.GET, "/outings/history/{outing-application-id}").hasAuthority(MANAGER.name) .anyRequest().denyAll() } diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/scheduler/StudentTagScheduler.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/scheduler/StudentTagScheduler.kt new file mode 100644 index 000000000..6285fef82 --- /dev/null +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/scheduler/StudentTagScheduler.kt @@ -0,0 +1,17 @@ +package team.aliens.dms.scheduler + +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Component +import team.aliens.dms.domain.tag.usecase.UpdateStudentTagsUseCase + +@Component +class StudentTagScheduler( + private val updateStudentTagsUseCase: UpdateStudentTagsUseCase +) { + + /** + * 매일 밤 12시 마다 학생이 가진 벌점 태그 초기화 후 벌점에 따른 태그 자동 부여 + */ + @Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul") + fun updateStudentTags() = updateStudentTagsUseCase.execute() +} diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt index 575204d13..d207c460d 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/thirdparty/parser/ExcelAdapter.kt @@ -1,7 +1,6 @@ package team.aliens.dms.thirdparty.parser import org.apache.poi.hssf.usermodel.HSSFWorkbook -import org.apache.poi.ss.usermodel.BorderStyle import org.apache.poi.ss.usermodel.Cell import org.apache.poi.ss.usermodel.CellStyle import org.apache.poi.ss.usermodel.HorizontalAlignment @@ -12,7 +11,6 @@ import org.apache.poi.ss.usermodel.Sheet import org.apache.poi.ss.usermodel.VerticalAlignment import org.apache.poi.ss.usermodel.Workbook import org.apache.poi.ss.util.CellRangeAddress -import org.apache.poi.ss.util.RegionUtil import org.apache.poi.xssf.usermodel.XSSFWorkbook import org.springframework.stereotype.Component import team.aliens.dms.domain.file.FileExtension.XLS @@ -356,7 +354,7 @@ class ExcelAdapter : ParseFilePort, WriteFilePort { mutableListOf( outingApplication.studentName, outingApplication.studentGcn, - outingApplication.outAt.toString(), + outingApplication.outingDate.toString(), outingApplication.outingTime.toString(), outingApplication.arrivalTime.toString() ).apply { diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingApplicationPersistenceAdapter.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingApplicationPersistenceAdapter.kt index 466d5886e..9fd9d8a04 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingApplicationPersistenceAdapter.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingApplicationPersistenceAdapter.kt @@ -16,6 +16,7 @@ import team.aliens.dms.persistence.outing.entity.QOutingCompanionJpaEntity.outin import team.aliens.dms.persistence.outing.entity.QOutingTypeJpaEntity.outingTypeJpaEntity import team.aliens.dms.persistence.outing.mapper.OutingApplicationMapper import team.aliens.dms.persistence.outing.repository.OutingApplicationJpaRepository +import team.aliens.dms.persistence.outing.repository.OutingCompanionJpaRepository import team.aliens.dms.persistence.outing.repository.vo.QQueryCurrentOutingApplicationVO import team.aliens.dms.persistence.outing.repository.vo.QQueryOutingApplicationVO import team.aliens.dms.persistence.outing.repository.vo.QQueryOutingCompanionVO @@ -28,11 +29,12 @@ import java.util.UUID class OutingApplicationPersistenceAdapter( private val outingApplicationMapper: OutingApplicationMapper, private val outingApplicationRepository: OutingApplicationJpaRepository, + private val outingCompanionsRepository: OutingCompanionJpaRepository, private val queryFactory: JPAQueryFactory ) : OutingApplicationPort { - override fun existOutingApplicationByOutAtAndStudentId(outAt: LocalDate, studentId: UUID) = - outingApplicationRepository.existsByOutAtAndStudentId(outAt, studentId) + override fun existOutingApplicationByOutingDateAndStudentId(outingDate: LocalDate, studentId: UUID) = + outingApplicationRepository.existsByOutingDateAndStudentId(outingDate, studentId) override fun queryOutingApplicationById(outingApplicationId: UUID) = outingApplicationMapper.toDomain( @@ -52,8 +54,8 @@ class OutingApplicationPersistenceAdapter( .leftJoin(outingCompanionJpaEntity) .on(outingApplicationJpaEntity.id.eq(outingCompanionJpaEntity.outingApplication.id)) .leftJoin(outingCompanionJpaEntity.student, outingCompanionStudentJpaEntity) - .where(outingApplicationJpaEntity.outAt.between(start, end)) - .orderBy(outingApplicationJpaEntity.outAt.asc()) + .where(outingApplicationJpaEntity.outingDate.between(start, end)) + .orderBy(outingApplicationJpaEntity.outingDate.asc()) .transform( groupBy(outingApplicationJpaEntity.id) .list( @@ -62,7 +64,7 @@ class OutingApplicationPersistenceAdapter( studentJpaEntity.grade, studentJpaEntity.classRoom, studentJpaEntity.number, - outingApplicationJpaEntity.outAt, + outingApplicationJpaEntity.outingDate, outingApplicationJpaEntity.outingTime, outingApplicationJpaEntity.arrivalTime, list( @@ -97,13 +99,14 @@ class OutingApplicationPersistenceAdapter( groupBy(outingApplicationJpaEntity.id) .list( QQueryCurrentOutingApplicationVO( - outingApplicationJpaEntity.outAt, + outingApplicationJpaEntity.id, + outingApplicationJpaEntity.outingDate, outingTypeJpaEntity.id.title, outingApplicationJpaEntity.status, outingApplicationJpaEntity.outingTime, outingApplicationJpaEntity.arrivalTime, outingApplicationJpaEntity.reason, - list(outingCompanionStudentJpaEntity.name) + list(outingCompanionJpaEntity.student.name) ) ) ).firstOrNull() @@ -133,10 +136,10 @@ class OutingApplicationPersistenceAdapter( .leftJoin(outingCompanionJpaEntity.student, outingCompanionStudentJpaEntity) .where( studentName?.let { studentJpaEntity.name.eq(it) }, - outingApplicationJpaEntity.outAt.eq(date) + outingApplicationJpaEntity.outingDate.eq(date) ) .groupBy(outingApplicationJpaEntity.id) - .orderBy(outingApplicationJpaEntity.outAt.asc()) + .orderBy(outingApplicationJpaEntity.arrivalTime.asc()) .fetch() } @@ -148,6 +151,10 @@ class OutingApplicationPersistenceAdapter( )!! override fun deleteOutingApplication(outingApplication: OutingApplication) { + outingCompanionsRepository.deleteAllByOutingApplication( + outingApplicationMapper.toEntity(outingApplication) + ) + outingApplicationRepository.delete( outingApplicationMapper.toEntity(outingApplication) ) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingCompanionsPersistenceAdapter.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingCompanionsPersistenceAdapter.kt index 866b4dbf9..02a4e5ec7 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingCompanionsPersistenceAdapter.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/OutingCompanionsPersistenceAdapter.kt @@ -1,17 +1,44 @@ package team.aliens.dms.persistence.outing +import com.querydsl.jpa.impl.JPAQueryFactory import org.springframework.stereotype.Component import team.aliens.dms.domain.outing.model.OutingCompanion import team.aliens.dms.domain.outing.spi.OutingCompanionPort +import team.aliens.dms.domain.outing.spi.vo.OutingCompanionDetailsVO +import team.aliens.dms.persistence.outing.entity.QOutingCompanionJpaEntity.outingCompanionJpaEntity import team.aliens.dms.persistence.outing.mapper.OutingCompanionMapper import team.aliens.dms.persistence.outing.repository.OutingCompanionJpaRepository +import team.aliens.dms.persistence.outing.repository.vo.QQueryOutingCompanionDetailsVO +import team.aliens.dms.persistence.student.entity.QStudentJpaEntity.studentJpaEntity +import java.util.UUID @Component class OutingCompanionsPersistenceAdapter( private val outingCompanionRepository: OutingCompanionJpaRepository, - private val outingCompanionMapper: OutingCompanionMapper + private val outingCompanionMapper: OutingCompanionMapper, + private val queryFactory: JPAQueryFactory ) : OutingCompanionPort { + override fun queryOutingCompanionsById(outingApplicationId: UUID): List { + return queryFactory + .select( + QQueryOutingCompanionDetailsVO( + studentJpaEntity.id, + studentJpaEntity.name, + studentJpaEntity.grade, + studentJpaEntity.classRoom, + studentJpaEntity.number, + studentJpaEntity.room.number + ) + ) + .from(outingCompanionJpaEntity) + .join(outingCompanionJpaEntity.student, studentJpaEntity) + .where( + outingCompanionJpaEntity.outingApplication.id.eq(outingApplicationId) + ) + .fetch() + } + override fun saveAllOutingCompanions(outingCompanions: List) { outingCompanionRepository.saveAll( outingCompanions.map { diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/entity/OutingApplicationJpaEntity.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/entity/OutingApplicationJpaEntity.kt index 5965f3f32..9f678e12d 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/entity/OutingApplicationJpaEntity.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/entity/OutingApplicationJpaEntity.kt @@ -30,7 +30,7 @@ class OutingApplicationJpaEntity( override val createdAt: LocalDateTime, @Column(columnDefinition = "DATE", nullable = false) - val outAt: LocalDate, + val outingDate: LocalDate, @Column(columnDefinition = "TIME", nullable = false) val outingTime: LocalTime, diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/mapper/OutingApplicationMapper.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/mapper/OutingApplicationMapper.kt index fb16cd801..4eef0fe4a 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/mapper/OutingApplicationMapper.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/mapper/OutingApplicationMapper.kt @@ -21,7 +21,7 @@ class OutingApplicationMapper( id = it.id!!, studentId = it.student!!.id!!, createdAt = it.createdAt, - outAt = it.outAt, + outingDate = it.outingDate, outingTime = it.outingTime, arrivalTime = it.arrivalTime, status = it.status, @@ -44,7 +44,7 @@ class OutingApplicationMapper( id = domain.id, student = student, createdAt = domain.createdAt, - outAt = domain.outAt, + outingDate = domain.outingDate, outingTime = domain.outingTime, arrivalTime = domain.arrivalTime, status = domain.status, diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingApplicationJpaRepository.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingApplicationJpaRepository.kt index d4f91e6e2..4b13637a9 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingApplicationJpaRepository.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingApplicationJpaRepository.kt @@ -8,5 +8,5 @@ import java.util.UUID @Repository interface OutingApplicationJpaRepository : CrudRepository { - fun existsByOutAtAndStudentId(outAt: LocalDate, studentId: UUID): Boolean + fun existsByOutingDateAndStudentId(outingDate: LocalDate, studentId: UUID): Boolean } diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingCompanionJpaRepository.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingCompanionJpaRepository.kt index b13f407bc..a01f0395e 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingCompanionJpaRepository.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/OutingCompanionJpaRepository.kt @@ -2,8 +2,11 @@ package team.aliens.dms.persistence.outing.repository import org.springframework.data.repository.CrudRepository import org.springframework.stereotype.Repository +import team.aliens.dms.persistence.outing.entity.OutingApplicationJpaEntity import team.aliens.dms.persistence.outing.entity.OutingCompanionJpaEntity import team.aliens.dms.persistence.outing.entity.OutingCompanionJpaEntityId @Repository -interface OutingCompanionJpaRepository : CrudRepository +interface OutingCompanionJpaRepository : CrudRepository { + fun deleteAllByOutingApplication(outingApplication: OutingApplicationJpaEntity) +} diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryCurrentOutingApplicationVO.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryCurrentOutingApplicationVO.kt index cb6af2ab7..2395b08b4 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryCurrentOutingApplicationVO.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryCurrentOutingApplicationVO.kt @@ -1,25 +1,28 @@ -package team.aliens.dms.persistence.outing.repository.vo - -import com.querydsl.core.annotations.QueryProjection -import team.aliens.dms.domain.outing.model.OutingStatus -import team.aliens.dms.domain.outing.spi.vo.CurrentOutingApplicationVO -import java.time.LocalDate -import java.time.LocalTime - -class QueryCurrentOutingApplicationVO @QueryProjection constructor( - outAt: LocalDate, - outingTypeTitle: String, - status: OutingStatus, - outingTime: LocalTime, - arrivalTime: LocalTime, - reason: String?, - outingCompanions: List -) : CurrentOutingApplicationVO( - outAt = outAt, - outingTypeTitle = outingTypeTitle, - status = status, - outingTime = outingTime, - arrivalTime = arrivalTime, - reason = reason, - outingCompanions = outingCompanions -) +package team.aliens.dms.persistence.outing.repository.vo + +import com.querydsl.core.annotations.QueryProjection +import team.aliens.dms.domain.outing.model.OutingStatus +import team.aliens.dms.domain.outing.spi.vo.CurrentOutingApplicationVO +import java.time.LocalDate +import java.time.LocalTime +import java.util.UUID + +class QueryCurrentOutingApplicationVO @QueryProjection constructor( + id: UUID, + outingDate: LocalDate, + outingTypeTitle: String, + status: OutingStatus, + outingTime: LocalTime, + arrivalTime: LocalTime, + reason: String?, + outingCompanions: List +) : CurrentOutingApplicationVO( + id = id, + outingDate = outingDate, + outingTypeTitle = outingTypeTitle, + status = status, + outingTime = outingTime, + arrivalTime = arrivalTime, + reason = reason, + outingCompanions = outingCompanions +) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryOutingApplicationVO.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryOutingApplicationVO.kt index 5eee28d9b..1957a38a6 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryOutingApplicationVO.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryOutingApplicationVO.kt @@ -11,7 +11,7 @@ class QueryOutingApplicationVO @QueryProjection constructor( studentGrade: Int, studentClassRoom: Int, studentNumber: Int, - outAt: LocalDate, + outingDate: LocalDate, outingTime: LocalTime, arrivalTime: LocalTime, outingCompanionVOs: List @@ -20,7 +20,7 @@ class QueryOutingApplicationVO @QueryProjection constructor( studentGrade = studentGrade, studentClassRoom = studentClassRoom, studentNumber = studentNumber, - outAt = outAt, + outingDate = outingDate, outingTime = outingTime, arrivalTime = arrivalTime, outingCompanionVOs = outingCompanionVOs diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryOutingCompanionDetailsVO.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryOutingCompanionDetailsVO.kt new file mode 100644 index 000000000..a1fcee231 --- /dev/null +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/outing/repository/vo/QueryOutingCompanionDetailsVO.kt @@ -0,0 +1,21 @@ +package team.aliens.dms.persistence.outing.repository.vo + +import com.querydsl.core.annotations.QueryProjection +import team.aliens.dms.domain.outing.spi.vo.OutingCompanionDetailsVO +import java.util.UUID + +class QueryOutingCompanionDetailsVO @QueryProjection constructor( + id: UUID, + name: String, + grade: Int, + classRoom: Int, + number: Int, + roomNumber: String, +) : OutingCompanionDetailsVO( + id = id, + studentName = name, + studentGrade = grade, + studentClassRoom = classRoom, + studentNumber = number, + roomNumber = roomNumber +) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/PointHistoryPersistenceAdapter.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/PointHistoryPersistenceAdapter.kt index f1c52ff57..5c9cc710b 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/PointHistoryPersistenceAdapter.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/PointHistoryPersistenceAdapter.kt @@ -1,5 +1,7 @@ package team.aliens.dms.persistence.point +import com.querydsl.core.BooleanBuilder +import com.querydsl.jpa.JPAExpressions.select import com.querydsl.jpa.impl.JPAQueryFactory import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component @@ -9,11 +11,14 @@ import team.aliens.dms.domain.point.model.PointType import team.aliens.dms.domain.point.spi.PointHistoryPort import team.aliens.dms.domain.point.spi.vo.PointHistoryVO import team.aliens.dms.domain.point.spi.vo.StudentPointHistoryVO +import team.aliens.dms.domain.point.spi.vo.StudentTotalVO import team.aliens.dms.persistence.point.entity.QPointHistoryJpaEntity.pointHistoryJpaEntity import team.aliens.dms.persistence.point.mapper.PointHistoryMapper import team.aliens.dms.persistence.point.repository.PointHistoryJpaRepository import team.aliens.dms.persistence.point.repository.vo.QQueryAllPointHistoryVO import team.aliens.dms.persistence.point.repository.vo.QQueryPointHistoryVO +import team.aliens.dms.persistence.point.repository.vo.QQueryStudentTotalVO +import team.aliens.dms.persistence.student.entity.QStudentJpaEntity.studentJpaEntity import java.time.LocalDateTime import java.util.UUID @@ -154,4 +159,41 @@ class PointHistoryPersistenceAdapter( override fun queryPointHistoryByGcnIn(gcns: List) = pointHistoryRepository.findByStudentGcnIn(gcns) .map { pointHistoryMapper.toDomain(it)!! } + + override fun queryPointTotalsGroupByStudent(): List { + return queryFactory + .select( + QQueryStudentTotalVO( + studentJpaEntity.id, + pointHistoryJpaEntity.bonusTotal, + pointHistoryJpaEntity.minusTotal + ) + ) + .from(studentJpaEntity) + .innerJoin(pointHistoryJpaEntity).on( + pointHistoryJpaEntity.id.eq( + select(pointHistoryJpaEntity.id) + .from(studentJpaEntity) + .join(pointHistoryJpaEntity) + .on( + eqGcn(), pointHistoryJpaEntity.studentName.eq(studentJpaEntity.name) + + ) + .orderBy(pointHistoryJpaEntity.createdAt.desc()) + .fetchFirst() + ) + ) + .groupBy(studentJpaEntity.id) + .fetch() + } + + private fun eqGcn(): BooleanBuilder { + val condition = BooleanBuilder() + val gcn = pointHistoryJpaEntity.studentGcn + condition + .and(gcn.substring(0, 1).eq(studentJpaEntity.grade.stringValue())) + .and(gcn.substring(1, 2).endsWith(studentJpaEntity.classRoom.stringValue())) + .and(gcn.substring(2).endsWith(studentJpaEntity.number.stringValue())) + return condition + } } diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/repository/vo/QueryStudentTotalVO.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/repository/vo/QueryStudentTotalVO.kt new file mode 100644 index 000000000..5ac9bb346 --- /dev/null +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/repository/vo/QueryStudentTotalVO.kt @@ -0,0 +1,15 @@ +package team.aliens.dms.persistence.point.repository.vo + +import com.querydsl.core.annotations.QueryProjection +import team.aliens.dms.domain.point.spi.vo.StudentTotalVO +import java.util.UUID + +class QueryStudentTotalVO @QueryProjection constructor( + id: UUID, + bonusTotal: Int, + minusTotal: Int +) : StudentTotalVO( + studentId = id, + bonusTotal = bonusTotal, + minusTotal = minusTotal +) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/entity/AvailableFeatureJpaEntity.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/entity/AvailableFeatureJpaEntity.kt index 0f9431ed6..81e993f83 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/entity/AvailableFeatureJpaEntity.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/entity/AvailableFeatureJpaEntity.kt @@ -35,6 +35,9 @@ class AvailableFeatureJpaEntity( val studyRoomService: Boolean, @Column(columnDefinition = "TINYINT(1)", nullable = false) - val remainService: Boolean + val remainService: Boolean, + + @Column(columnDefinition = "TINYINT(1)", nullable = false) + val outingService: Boolean, ) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/mapper/AvailableFeatureMapper.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/mapper/AvailableFeatureMapper.kt index 520f2fb15..5a69f1439 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/mapper/AvailableFeatureMapper.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/school/mapper/AvailableFeatureMapper.kt @@ -20,7 +20,8 @@ class AvailableFeatureMapper( noticeService = entity.noticeService, pointService = entity.pointService, studyRoomService = entity.studyRoomService, - remainService = entity.remainService + remainService = entity.remainService, + outingService = entity.outingService ) } } @@ -35,7 +36,8 @@ class AvailableFeatureMapper( noticeService = domain.noticeService, pointService = domain.pointService, studyRoomService = domain.studyRoomService, - remainService = domain.remainService + remainService = domain.remainService, + outingService = domain.outingService ) } } diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt index 275953a86..ba0c2a21e 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt @@ -185,6 +185,8 @@ class StudentPersistenceAdapter( roomJpaEntity.number, studentJpaEntity.profileImageUrl, studentJpaEntity.sex, + pointHistoryJpaEntity.bonusTotal, + pointHistoryJpaEntity.minusTotal, list(tagJpaEntity) ) ) @@ -199,6 +201,8 @@ class StudentPersistenceAdapter( roomNumber = it.roomNumber, profileImageUrl = it.profileImageUrl, sex = it.sex, + bonusPoint = it.bonusPoint, + minusPoint = it.minusPoint, tags = it.tags .map { tag -> tagMapper.toDomain(tag)!! diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/repository/vo/QueryStudentsWithTagVO.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/repository/vo/QueryStudentsWithTagVO.kt index ee7e8b0a6..e55c71f71 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/repository/vo/QueryStudentsWithTagVO.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/repository/vo/QueryStudentsWithTagVO.kt @@ -14,5 +14,7 @@ data class QueryStudentsWithTagVO @QueryProjection constructor( val roomNumber: String, val profileImageUrl: String, val sex: Sex, + val bonusPoint: Int, + val minusPoint: Int, val tags: List ) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/StudentTagPersistenceAdapter.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/StudentTagPersistenceAdapter.kt index a98c13e3a..2025f2e5d 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/StudentTagPersistenceAdapter.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/StudentTagPersistenceAdapter.kt @@ -4,6 +4,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory import org.springframework.stereotype.Component import team.aliens.dms.domain.tag.model.StudentTag import team.aliens.dms.domain.tag.spi.StudentTagPort +import team.aliens.dms.persistence.tag.entity.QStudentTagJpaEntity.studentTagJpaEntity import team.aliens.dms.persistence.tag.entity.StudentTagId import team.aliens.dms.persistence.tag.mapper.StudentTagMapper import team.aliens.dms.persistence.tag.repository.StudentTagJpaRepository @@ -16,6 +17,18 @@ class StudentTagPersistenceAdapter( private val queryFactory: JPAQueryFactory ) : StudentTagPort { + override fun queryStudentTagsByStudentId(studentId: UUID): List { + return studentTagRepository.findAllByStudentId(studentId) + .map { studentTagMapper.toDomain(it)!! } + } + + override fun deleteAllStudentTagsByTagIdIn(tagIds: List) { + queryFactory.delete(studentTagJpaEntity) + .where( + studentTagJpaEntity.tag.id.`in`(tagIds) + ).execute() + } + override fun deleteStudentTagById(studentId: UUID, tagId: UUID) { val id = StudentTagId( studentId = studentId, @@ -29,6 +42,12 @@ class StudentTagPersistenceAdapter( studentTagRepository.deleteByTagId(tagId) } + override fun saveStudentTag(studentTag: StudentTag) = studentTagMapper.toDomain( + studentTagRepository.save( + studentTagMapper.toEntity(studentTag) + ) + )!! + override fun saveAllStudentTags(studentTags: List) { studentTagRepository.saveAll( studentTags.map { diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/TagPersistenceAdapter.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/TagPersistenceAdapter.kt index 90b84e5c2..ebc975294 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/TagPersistenceAdapter.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/TagPersistenceAdapter.kt @@ -18,6 +18,16 @@ class TagPersistenceAdapter( private val queryFactory: JPAQueryFactory ) : TagPort { + override fun queryAllWarningTags(names: List): List { + return queryFactory.selectFrom(tagJpaEntity) + .where( + tagJpaEntity.name.`in`(names) + ).fetch() + .map { + tagMapper.toDomain(it)!! + } + } + override fun queryTagsBySchoolId(schoolId: UUID): List { return tagRepository.findBySchoolId(schoolId) .map { @@ -31,6 +41,12 @@ class TagPersistenceAdapter( ) } + override fun queryTagByName(name: String): Tag? { + return tagMapper.toDomain( + tagRepository.findByName(name) + ) + } + override fun deleteTagById(tagId: UUID) { tagRepository.deleteById(tagId) } diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/StudentTagJpaRepository.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/StudentTagJpaRepository.kt index d47c64853..70ee9a24d 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/StudentTagJpaRepository.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/StudentTagJpaRepository.kt @@ -7,4 +7,6 @@ import java.util.UUID interface StudentTagJpaRepository : CrudRepository { fun deleteByTagId(tagId: UUID) + + fun findAllByStudentId(studentId: UUID): List } diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/TagJpaRepository.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/TagJpaRepository.kt index a4f481cfc..c0a4e93ac 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/TagJpaRepository.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/tag/repository/TagJpaRepository.kt @@ -7,5 +7,7 @@ import java.util.UUID interface TagJpaRepository : CrudRepository { fun findBySchoolId(schoolId: UUID): List + fun findByName(name: String): TagJpaEntity? + fun existsByNameAndSchoolId(name: String, schoolId: UUID): Boolean } diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/common/WebMvcConfig.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/common/config/WebMvcConfig.kt similarity index 95% rename from dms-presentation/src/main/kotlin/team/aliens/dms/common/WebMvcConfig.kt rename to dms-presentation/src/main/kotlin/team/aliens/dms/common/config/WebMvcConfig.kt index ab081933b..befc456fe 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/common/WebMvcConfig.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/common/config/WebMvcConfig.kt @@ -1,4 +1,4 @@ -package team.aliens.dms.common +package team.aliens.dms.common.config import org.springframework.context.annotation.Configuration import org.springframework.http.HttpHeaders diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/OutingWebAdapter.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/OutingWebAdapter.kt index cef31f6d6..a83592d57 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/OutingWebAdapter.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/OutingWebAdapter.kt @@ -24,6 +24,7 @@ import team.aliens.dms.domain.outing.dto.GetAllOutingTypeTitlesResponse import team.aliens.dms.domain.outing.dto.GetCurrentOutingApplicationResponse import team.aliens.dms.domain.outing.dto.OutingApplicationHistoriesResponse import team.aliens.dms.domain.outing.dto.OutingAvailableTimesResponse +import team.aliens.dms.domain.outing.dto.OutingHistoryDetailsResponse import team.aliens.dms.domain.outing.dto.request.ApplyOutingWebRequest import team.aliens.dms.domain.outing.dto.request.CreateOutingTypeWebRequest import team.aliens.dms.domain.outing.model.OutingStatus @@ -34,6 +35,7 @@ import team.aliens.dms.domain.outing.usecase.GetAllOutingTypeTitlesUseCase import team.aliens.dms.domain.outing.usecase.GetCurrentOutingApplicationUseCase import team.aliens.dms.domain.outing.usecase.GetOutingApplicationHistoriesUseCase import team.aliens.dms.domain.outing.usecase.GetOutingAvailableTimesUseCase +import team.aliens.dms.domain.outing.usecase.GetOutingHistoryDetailsUseCase import team.aliens.dms.domain.outing.usecase.RemoveOutingTypeUseCase import team.aliens.dms.domain.outing.usecase.UnApplyOutingUseCase import team.aliens.dms.domain.outing.usecase.UpdateOutingStatusUseCase @@ -53,8 +55,9 @@ class OutingWebAdapter( private val updateOutingStatusUseCase: UpdateOutingStatusUseCase, private val exportAllOutingApplicationsUseCase: ExportAllOutingApplicationsUseCase, private val getCurrentOutingApplicationUseCase: GetCurrentOutingApplicationUseCase, - private val getOutingApplicationHistoryUseCase: GetOutingApplicationHistoriesUseCase, - private val getOutingAvailableTimesUseCase: GetOutingAvailableTimesUseCase + private val getOutingApplicationHistoriesUseCase: GetOutingApplicationHistoriesUseCase, + private val getOutingAvailableTimesUseCase: GetOutingAvailableTimesUseCase, + private val getOutingHistoryDetailsUseCase: GetOutingHistoryDetailsUseCase ) { @ResponseStatus(HttpStatus.CREATED) @@ -62,7 +65,7 @@ class OutingWebAdapter( fun applyOuting(@RequestBody @Valid webRequest: ApplyOutingWebRequest): ApplyOutingResponse { return applyOutingUseCase.execute( ApplyOutingRequest( - outAt = webRequest.outAt, + outingDate = webRequest.outingDate, outingTime = webRequest.outingTime, arrivalTime = webRequest.arrivalTime, outingTypeTitle = webRequest.outingTypeTitle, @@ -127,7 +130,7 @@ class OutingWebAdapter( @RequestParam(name = "student_name", required = false) studentName: String?, @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) date: LocalDate, ): OutingApplicationHistoriesResponse { - return getOutingApplicationHistoryUseCase.execute( + return getOutingApplicationHistoriesUseCase.execute( studentName = studentName, date = date ) @@ -139,4 +142,11 @@ class OutingWebAdapter( ): OutingAvailableTimesResponse { return getOutingAvailableTimesUseCase.execute(dayOfWeek) } + + @GetMapping("/history/{outing-application-id}") + fun getOutingHistoryDetails( + @PathVariable("outing-application-id") @NotNull outingApplicationId: UUID + ): OutingHistoryDetailsResponse { + return getOutingHistoryDetailsUseCase.execute(outingApplicationId) + } } diff --git a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/dto/request/ApplyOutingWebRequest.kt b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/dto/request/ApplyOutingWebRequest.kt index 7b5e18a96..92028e013 100644 --- a/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/dto/request/ApplyOutingWebRequest.kt +++ b/dms-presentation/src/main/kotlin/team/aliens/dms/domain/outing/dto/request/ApplyOutingWebRequest.kt @@ -1,30 +1,30 @@ -package team.aliens.dms.domain.outing.dto.request - -import jakarta.validation.constraints.NotBlank -import jakarta.validation.constraints.NotNull -import jakarta.validation.constraints.Size -import team.aliens.dms.common.validator.NotNullElements -import java.time.LocalDate -import java.time.LocalTime -import java.util.UUID - -data class ApplyOutingWebRequest( - @field:NotNull - val outAt: LocalDate, - - @field:NotNull - val outingTime: LocalTime, - - @field:NotNull - val arrivalTime: LocalTime, - - @field:Size(max = 20) - @field:NotBlank - val outingTypeTitle: String, - - @field:Size(max = 100) - val reason: String?, - - @field:NotNullElements - val companionIds: List? -) +package team.aliens.dms.domain.outing.dto.request + +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size +import team.aliens.dms.common.validator.NotNullElements +import java.time.LocalDate +import java.time.LocalTime +import java.util.UUID + +data class ApplyOutingWebRequest( + @field:NotNull + val outingDate: LocalDate, + + @field:NotNull + val outingTime: LocalTime, + + @field:NotNull + val arrivalTime: LocalTime, + + @field:Size(max = 20) + @field:NotBlank + val outingTypeTitle: String, + + @field:Size(max = 100) + val reason: String?, + + @field:NotNullElements + val companionIds: List? +)