Skip to content

Commit f41a210

Browse files
authored
Merge pull request #59 from EntryDSM/feature/58-pass-api
Feature/58 pass api
2 parents aafa9f7 + b881f72 commit f41a210

15 files changed

Lines changed: 257 additions & 1 deletion

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package hs.kr.entrydsm.domain.application.interfaces
2+
3+
import hs.kr.entrydsm.domain.application.aggregates.Application
4+
import java.util.UUID
5+
6+
interface ApplicationCaseQueryApplicationContract {
7+
fun queryApplicationByUserId(userId: UUID): Application?
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package hs.kr.entrydsm.domain.application.interfaces
2+
3+
import hs.kr.entrydsm.domain.schedule.aggregates.Schedule
4+
import hs.kr.entrydsm.domain.schedule.values.ScheduleType
5+
6+
interface ApplicationQueryScheduleContract {
7+
suspend fun queryByScheduleType(scheduleType: ScheduleType): Schedule?
8+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package hs.kr.entrydsm.domain.schedule.aggregates
2+
3+
import hs.kr.entrydsm.domain.schedule.values.ScheduleType
4+
import hs.kr.entrydsm.global.annotation.aggregates.Aggregate
5+
import java.time.LocalDateTime
6+
7+
@Aggregate(context = "schedule")
8+
data class Schedule(
9+
val scheduleType: ScheduleType,
10+
val date: LocalDateTime
11+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package hs.kr.entrydsm.domain.schedule.exception
2+
3+
import hs.kr.entrydsm.global.exception.BusinessException
4+
5+
sealed class ScheduleExceptions(
6+
override val status: Int,
7+
override val message: String,
8+
) : BusinessException(status, message) {
9+
10+
class ScoreNotFoundException(message: String = SCORE_NOT_FOUND_EXCEPTION):
11+
ScheduleExceptions(404, message)
12+
13+
class AdmissionUnavailableException(message: String = ADMISSION_UNAVAILABLE):
14+
ScheduleExceptions(404, message)
15+
16+
companion object {
17+
private const val SCORE_NOT_FOUND_EXCEPTION = "점수가 존재하지 않습니다"
18+
private const val ADMISSION_UNAVAILABLE = "합격여부를 확인할 수 없습니다"
19+
}
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package hs.kr.entrydsm.domain.schedule.values
2+
3+
enum class ScheduleType {
4+
START_DATE,
5+
FIRST_ANNOUNCEMENT,
6+
INTERVIEW,
7+
SECOND_ANNOUNCEMENT,
8+
END_DATE
9+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package hs.kr.entrydsm.domain.status.exception
2+
3+
import hs.kr.entrydsm.global.exception.BusinessException
4+
5+
sealed class StatusExceptions(
6+
override val status: Int,
7+
override val message: String,
8+
) : BusinessException(status, message) {
9+
class StatusNotFoundException(message: String = STATUS_NOT_FOUND) :
10+
StatusExceptions(404, message)
11+
12+
class AlreadySubmittedException(message: String = ALREADY_SUBMITTED) :
13+
StatusExceptions(409, message)
14+
15+
companion object {
16+
private const val STATUS_NOT_FOUND = "상태가 존재하지 않습니다"
17+
private const val ALREADY_SUBMITTED = "이미 최종제출이 되어있습니다."
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package hs.kr.entrydsm.application.domain.application.usecase
2+
3+
import hs.kr.entrydsm.application.domain.application.exception.ApplicationNotFoundException
4+
import hs.kr.entrydsm.application.domain.pass.presentation.dto.response.QueryIsFirstRoundPassResponse
5+
import hs.kr.entrydsm.application.global.annotation.usecase.ReadOnlyUseCase
6+
import hs.kr.entrydsm.application.global.security.SecurityAdapter
7+
import hs.kr.entrydsm.domain.application.interfaces.ApplicationContract
8+
import hs.kr.entrydsm.domain.application.interfaces.ApplicationQueryScheduleContract
9+
import hs.kr.entrydsm.domain.schedule.exception.ScheduleExceptions
10+
import hs.kr.entrydsm.domain.schedule.values.ScheduleType
11+
import hs.kr.entrydsm.domain.status.exception.StatusExceptions
12+
import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract
13+
import java.time.LocalDateTime
14+
15+
@ReadOnlyUseCase
16+
class QueryIsFirstRoundPassUseCase(
17+
private val securityAdapter: SecurityAdapter,
18+
private val queryApplicationContract: ApplicationContract,
19+
private val applicationQueryScheduleContract: ApplicationQueryScheduleContract,
20+
private val applicationQueryStatusContract: ApplicationQueryStatusContract
21+
) {
22+
suspend fun execute(): QueryIsFirstRoundPassResponse {
23+
24+
val userId = securityAdapter.getCurrentUserId()
25+
val application = queryApplicationContract.getApplicationByUserId(userId)
26+
?: throw ApplicationNotFoundException()
27+
28+
val firstAnnounce = applicationQueryScheduleContract.queryByScheduleType(ScheduleType.FIRST_ANNOUNCEMENT)
29+
?: throw ScheduleExceptions.ScoreNotFoundException()
30+
31+
if (LocalDateTime.now().isBefore(firstAnnounce.date))
32+
throw ScheduleExceptions.AdmissionUnavailableException()
33+
34+
val status = applicationQueryStatusContract.queryStatusByReceiptCode(application.receiptCode)
35+
?: throw StatusExceptions.StatusNotFoundException()
36+
37+
return QueryIsFirstRoundPassResponse(status.isFirstRoundPass)
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package hs.kr.entrydsm.application.domain.application.usecase
2+
3+
import hs.kr.entrydsm.application.domain.application.exception.ApplicationNotFoundException
4+
import hs.kr.entrydsm.application.domain.pass.presentation.dto.response.QueryIsSecondRoundPassResponse
5+
import hs.kr.entrydsm.application.global.annotation.usecase.ReadOnlyUseCase
6+
import hs.kr.entrydsm.application.global.security.SecurityAdapter
7+
import hs.kr.entrydsm.domain.application.interfaces.ApplicationContract
8+
import hs.kr.entrydsm.domain.application.interfaces.ApplicationQueryScheduleContract
9+
import hs.kr.entrydsm.domain.schedule.exception.ScheduleExceptions
10+
import hs.kr.entrydsm.domain.schedule.values.ScheduleType
11+
import hs.kr.entrydsm.domain.status.exception.StatusExceptions
12+
import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract
13+
import java.time.LocalDateTime
14+
15+
@ReadOnlyUseCase
16+
class QueryIsSecondRoundPassUseCase (
17+
private val securityAdapter: SecurityAdapter,
18+
private val queryApplicationContract: ApplicationContract,
19+
private val applicationQueryScheduleContract: ApplicationQueryScheduleContract,
20+
private val applicationQueryStatusContract: ApplicationQueryStatusContract
21+
) {
22+
suspend fun execute(): QueryIsSecondRoundPassResponse {
23+
val userId = securityAdapter.getCurrentUserId()
24+
val application = queryApplicationContract.getApplicationByUserId(userId)
25+
?: throw ApplicationNotFoundException()
26+
27+
val secondAnnounce = applicationQueryScheduleContract.queryByScheduleType(ScheduleType.SECOND_ANNOUNCEMENT)
28+
?: throw ScheduleExceptions.ScoreNotFoundException()
29+
30+
if (LocalDateTime.now().isBefore(secondAnnounce.date))
31+
throw ScheduleExceptions.AdmissionUnavailableException()
32+
33+
val status = applicationQueryStatusContract.queryStatusByReceiptCode(application.receiptCode)
34+
?: throw StatusExceptions.StatusNotFoundException()
35+
36+
return QueryIsSecondRoundPassResponse(status.isSecondRoundPass)
37+
}
38+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package hs.kr.entrydsm.application.domain.pass.presentation
2+
3+
import hs.kr.entrydsm.application.domain.application.usecase.QueryIsFirstRoundPassUseCase
4+
import hs.kr.entrydsm.application.domain.application.usecase.QueryIsSecondRoundPassUseCase
5+
import hs.kr.entrydsm.application.domain.pass.presentation.dto.response.QueryIsFirstRoundPassResponse
6+
import hs.kr.entrydsm.application.domain.pass.presentation.dto.response.QueryIsSecondRoundPassResponse
7+
import hs.kr.entrydsm.application.global.document.pass.PassApiDocument
8+
import org.springframework.web.bind.annotation.GetMapping
9+
import org.springframework.web.bind.annotation.RequestMapping
10+
import org.springframework.web.bind.annotation.RestController
11+
12+
@RestController
13+
@RequestMapping("/pass")
14+
class WebPassAdapter(
15+
private val queryIsFirstRoundPassUseCase: QueryIsFirstRoundPassUseCase,
16+
private val queryIsSecondRoundPassUseCase: QueryIsSecondRoundPassUseCase
17+
) : PassApiDocument {
18+
@GetMapping("/first-round")
19+
override suspend fun queryIsFirstRound(): QueryIsFirstRoundPassResponse =
20+
queryIsFirstRoundPassUseCase.execute()
21+
22+
@GetMapping("/second-round")
23+
override suspend fun queryIsSecondRound(): QueryIsSecondRoundPassResponse =
24+
queryIsSecondRoundPassUseCase.execute()
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package hs.kr.entrydsm.application.domain.pass.presentation.dto.response
2+
3+
data class QueryIsFirstRoundPassResponse(
4+
val isFirstRoundPass: Boolean
5+
)

0 commit comments

Comments
 (0)