diff --git a/dms-application/src/main/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCase.kt b/dms-application/src/main/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCase.kt index 8bee6d74f..5564d5164 100644 --- a/dms-application/src/main/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCase.kt +++ b/dms-application/src/main/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCase.kt @@ -8,6 +8,7 @@ import team.aliens.dms.domain.manager.spi.ManagerQueryUserPort import team.aliens.dms.domain.manager.spi.ManagerSecurityPort import team.aliens.dms.domain.school.validateSameSchool import team.aliens.dms.domain.student.exception.StudentNotFoundException +import team.aliens.dms.domain.student.spi.CommandStudentPort import team.aliens.dms.domain.student.spi.StudentCommandRemainStatusPort import team.aliens.dms.domain.student.spi.StudentCommandStudyRoomPort import team.aliens.dms.domain.student.spi.StudentQueryStudyRoomPort @@ -24,6 +25,7 @@ class RemoveStudentUseCase( private val commandRemainStatusPort: StudentCommandRemainStatusPort, private val queryStudyRoomPort: StudentQueryStudyRoomPort, private val commandStudyRoomPort: StudentCommandStudyRoomPort, + private val commandStudentPort: CommandStudentPort, private val commandUserPort: ManagerCommandUserPort ) { @@ -50,6 +52,10 @@ class RemoveStudentUseCase( ) } + commandStudentPort.saveStudent( + student.copy(deletedAt = LocalDateTime.now()) + ) + commandUserPort.saveUser( studentUser.copy(deletedAt = LocalDateTime.now()) ) diff --git a/dms-application/src/main/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCase.kt b/dms-application/src/main/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCase.kt index 748d87e11..c5b086e2b 100644 --- a/dms-application/src/main/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCase.kt +++ b/dms-application/src/main/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCase.kt @@ -1,6 +1,9 @@ package team.aliens.dms.domain.student.usecase import team.aliens.dms.common.annotation.UseCase +import team.aliens.dms.domain.student.exception.StudentNotFoundException +import team.aliens.dms.domain.student.spi.CommandStudentPort +import team.aliens.dms.domain.student.spi.QueryStudentPort import team.aliens.dms.domain.student.spi.StudentCommandRemainStatusPort import team.aliens.dms.domain.student.spi.StudentCommandStudyRoomPort import team.aliens.dms.domain.student.spi.StudentCommandUserPort @@ -14,15 +17,18 @@ import java.time.LocalDateTime @UseCase class StudentWithdrawalUseCase( private val securityPort: StudentSecurityPort, + private val queryStudentPort: QueryStudentPort, private val queryUserPort: StudentQueryUserPort, private val commandRemainStatusPort: StudentCommandRemainStatusPort, private val queryStudyRoomPort: StudentQueryStudyRoomPort, private val commandStudyRoomPort: StudentCommandStudyRoomPort, + private val commandStudentPort: CommandStudentPort, private val commandUserPort: StudentCommandUserPort ) { fun execute() { val currentStudentId = securityPort.getCurrentUserId() + val student = queryStudentPort.queryStudentById(currentStudentId) ?: throw StudentNotFoundException val studentUser = queryUserPort.queryUserById(currentStudentId) ?: throw UserNotFoundException // 잔류 내역 삭제 @@ -39,6 +45,10 @@ class StudentWithdrawalUseCase( ) } + commandStudentPort.saveStudent( + student.copy(deletedAt = LocalDateTime.now()) + ) + commandUserPort.saveUser( studentUser.copy(deletedAt = LocalDateTime.now()) ) diff --git a/dms-application/src/test/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCaseTests.kt b/dms-application/src/test/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCaseTests.kt index 34a99d34d..1d0c87c31 100644 --- a/dms-application/src/test/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCaseTests.kt +++ b/dms-application/src/test/kotlin/team/aliens/dms/domain/manager/usecase/RemoveStudentUseCaseTests.kt @@ -18,6 +18,7 @@ import team.aliens.dms.domain.school.exception.SchoolMismatchException import team.aliens.dms.domain.student.exception.StudentNotFoundException import team.aliens.dms.domain.student.model.Sex import team.aliens.dms.domain.student.model.Student +import team.aliens.dms.domain.student.spi.CommandStudentPort import team.aliens.dms.domain.student.spi.StudentCommandRemainStatusPort import team.aliens.dms.domain.student.spi.StudentCommandStudyRoomPort import team.aliens.dms.domain.student.spi.StudentQueryStudyRoomPort @@ -50,6 +51,9 @@ class RemoveStudentUseCaseTests { @MockBean private lateinit var commandStudyRoomPort: StudentCommandStudyRoomPort + @MockBean + private lateinit var commandStudentPort: CommandStudentPort + @MockBean private lateinit var commandUserPort: ManagerCommandUserPort @@ -59,7 +63,7 @@ class RemoveStudentUseCaseTests { fun setUp() { removeStudentUseCase = RemoveStudentUseCase( securityPort, queryUserPort, queryStudentPort, commandRemainStatusPort, - queryStudyRoomPort, commandStudyRoomPort, commandUserPort + queryStudyRoomPort, commandStudyRoomPort, commandStudentPort, commandUserPort ) } diff --git a/dms-application/src/test/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCaseTests.kt b/dms-application/src/test/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCaseTests.kt index b9305bfba..7f16fec2a 100644 --- a/dms-application/src/test/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCaseTests.kt +++ b/dms-application/src/test/kotlin/team/aliens/dms/domain/student/usecase/StudentWithdrawalUseCaseTests.kt @@ -8,6 +8,11 @@ import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ExtendWith import org.springframework.test.context.junit.jupiter.SpringExtension import team.aliens.dms.domain.auth.model.Authority +import team.aliens.dms.domain.student.exception.StudentNotFoundException +import team.aliens.dms.domain.student.model.Sex +import team.aliens.dms.domain.student.model.Student +import team.aliens.dms.domain.student.spi.CommandStudentPort +import team.aliens.dms.domain.student.spi.QueryStudentPort import team.aliens.dms.domain.student.spi.StudentCommandRemainStatusPort import team.aliens.dms.domain.student.spi.StudentCommandStudyRoomPort import team.aliens.dms.domain.student.spi.StudentCommandUserPort @@ -25,14 +30,17 @@ import java.util.UUID class StudentWithdrawalUseCaseTests { private val securityPort: StudentSecurityPort = mockk(relaxed = true) + private val queryStudentPort: QueryStudentPort = mockk(relaxed = true) private val queryUserPort: StudentQueryUserPort = mockk(relaxed = true) private val commandRemainStatusPort: StudentCommandRemainStatusPort = mockk(relaxed = true) private val queryStudyRoomPort: StudentQueryStudyRoomPort = mockk(relaxed = true) private val commandStudyRoomPort: StudentCommandStudyRoomPort = mockk(relaxed = true) + private val commandStudentPort: CommandStudentPort = mockk(relaxed = true) private val commandUserPort: StudentCommandUserPort = mockk(relaxed = true) private val studentWithdrawalUseCase = StudentWithdrawalUseCase( - securityPort, queryUserPort, commandRemainStatusPort, queryStudyRoomPort, commandStudyRoomPort, commandUserPort + securityPort, queryStudentPort, queryUserPort, commandRemainStatusPort, queryStudyRoomPort, + commandStudyRoomPort, commandStudentPort, commandUserPort ) private val currentStudentId = UUID.randomUUID() @@ -50,6 +58,22 @@ class StudentWithdrawalUseCaseTests { ) } + private val studentStub by lazy { + Student( + id = currentStudentId, + roomId = UUID.randomUUID(), + roomNumber = "216", + roomLocation = "A", + schoolId = UUID.randomUUID(), + grade = 2, + classRoom = 1, + number = 20, + name = "김범진", + profileImageUrl = "profile image url", + sex = Sex.FEMALE + ) + } + private val studyRoomId = UUID.randomUUID() private val seatStub by lazy { @@ -72,6 +96,8 @@ class StudentWithdrawalUseCaseTests { every { queryUserPort.queryUserById(currentStudentId) } returns userStub + every { queryStudentPort.queryStudentById(currentStudentId) } returns studentStub + every { queryStudyRoomPort.querySeatByStudentId(currentStudentId) } returns null // when & then @@ -93,11 +119,28 @@ class StudentWithdrawalUseCaseTests { } } + @Test + fun `학생이 존재하지 않음`() { + // given + every { securityPort.getCurrentUserId() } returns currentStudentId + + every { queryUserPort.queryUserById(currentStudentId) } returns userStub + + every { queryStudentPort.queryStudentById(currentStudentId) } returns null + + // when & then + assertThrows { + studentWithdrawalUseCase.execute() + } + } + @Test fun `자습실이 존재하지 않음`() { // given every { securityPort.getCurrentUserId() } returns currentStudentId + every { queryStudentPort.queryStudentById(currentStudentId) } returns studentStub + every { queryUserPort.queryUserById(currentStudentId) } returns userStub every { queryStudyRoomPort.querySeatByStudentId(currentStudentId) } returns seatStub diff --git a/dms-domain/src/main/kotlin/team/aliens/dms/domain/student/model/Student.kt b/dms-domain/src/main/kotlin/team/aliens/dms/domain/student/model/Student.kt index ae4cdb685..58c70a956 100644 --- a/dms-domain/src/main/kotlin/team/aliens/dms/domain/student/model/Student.kt +++ b/dms-domain/src/main/kotlin/team/aliens/dms/domain/student/model/Student.kt @@ -1,6 +1,7 @@ package team.aliens.dms.domain.student.model import team.aliens.dms.common.annotation.Aggregate +import java.time.LocalDateTime import java.util.UUID @Aggregate @@ -26,8 +27,9 @@ data class Student( val profileImageUrl: String? = PROFILE_IMAGE, - val sex: Sex + val sex: Sex, + val deletedAt: LocalDateTime? = null ) { val gcn: String = processGcn(this.grade, this.classRoom, this.number) diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt index 64757be54..64edf2f1c 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt @@ -77,6 +77,7 @@ class StudentPersistenceAdapter( return queryFactory .selectFrom(studentJpaEntity) .join(studentJpaEntity.user, userJpaEntity).fetchJoin() + .join(studentJpaEntity.room, roomJpaEntity).fetchJoin() .join(userJpaEntity.school, schoolJpaEntity) .leftJoin(pointHistoryJpaEntity) .on(eqStudentRecentPointHistory()) diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt index 41e6963fa..a87190ccc 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt @@ -1,8 +1,10 @@ package team.aliens.dms.persistence.student.entity +import org.hibernate.annotations.Where import team.aliens.dms.domain.student.model.Sex import team.aliens.dms.persistence.room.entity.RoomJpaEntity import team.aliens.dms.persistence.user.entity.UserJpaEntity +import java.time.LocalDateTime import java.util.UUID import javax.persistence.CascadeType import javax.persistence.Column @@ -25,6 +27,7 @@ import javax.persistence.UniqueConstraint UniqueConstraint(columnNames = arrayOf("grade", "class_room", "number")) ] ) +@Where(clause = "deleted_at is null") class StudentJpaEntity( @Id @@ -60,6 +63,8 @@ class StudentJpaEntity( @Column(columnDefinition = "VARCHAR(6)", nullable = false) @Enumerated(EnumType.STRING) - val sex: Sex + val sex: Sex, + @Column(columnDefinition = "DATETIME") + val deletedAt: LocalDateTime? ) diff --git a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt index 5670f927d..59152485a 100644 --- a/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt +++ b/dms-infrastructure/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt @@ -27,7 +27,8 @@ class StudentMapper( number = it.number, name = it.name, profileImageUrl = it.profileImageUrl, - sex = it.sex + sex = it.sex, + deletedAt = it.deletedAt ) } } @@ -46,7 +47,8 @@ class StudentMapper( number = domain.number, name = domain.name, profileImageUrl = domain.profileImageUrl!!, - sex = domain.sex + sex = domain.sex, + deletedAt = domain.deletedAt ) } }