Skip to content

Commit

Permalink
feat: 오프라인 출석 코드 refresh 기능 추가 (#121)
Browse files Browse the repository at this point in the history
* feat: 세션 수정 API에 누락된 code response 추가

* feat: 오프라인 출석 코드 refresh 기능 추가

* test: 오프라인 출석 코드 refresh 기능 테스트 코드 작성
  • Loading branch information
ddingmin authored Jul 20, 2024
1 parent 3393ab5 commit b6b4a12
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/main/kotlin/com/depromeet/makers/domain/model/Session.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ data class Session(
startTime: LocalDateTime = this.startTime,
sessionType: SessionType = this.sessionType,
place: Place = this.place,
code: String? = this.code,
): Session {
return copy(
generation = generation,
Expand All @@ -43,6 +44,7 @@ data class Session(
startTime = startTime,
sessionType = sessionType,
place = place,
code = code,
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.depromeet.makers.domain.usecase

import com.depromeet.makers.domain.gateway.SessionGateway
import com.depromeet.makers.domain.model.Session

class RefreshSessionCode(
val sessionGateway: SessionGateway,
) : UseCase<String, Session> {
override fun execute(sessionId: String): Session {
val session = sessionGateway.getById(sessionId)

return sessionGateway.save(
session.update(
code = Session.generateCode(),
),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class SessionController(
private val updateSessionPlace: UpdateSessionPlace,
private val deleteSession: DeleteSession,
private val getInfoSession: GetInfoSession,
private val refreshSessionCode: RefreshSessionCode,
) {
@Operation(summary = "새로운 세션 생성", description = "새로운 세션을 생성합니다.")
@PreAuthorize("hasRole('ORGANIZER')")
Expand Down Expand Up @@ -130,6 +131,19 @@ class SessionController(
return UpdateSessionPlaceResponse.fromDomain(updatedSession)
}

@Operation(summary = "세션 코드 갱신", description = "세션의 코드를 갱신합니다.")
@PreAuthorize("hasRole('ORGANIZER')")
@PatchMapping("/{sessionId}/code")
fun refreshSessionCode(
@PathVariable sessionId: String,
): UpdateSessionResponse {
val updatedSession =
refreshSessionCode.execute(
sessionId = sessionId,
)
return UpdateSessionResponse.fromDomain(updatedSession)
}

@Operation(summary = "세션 삭제", description = "세션을 삭제합니다.")
@PreAuthorize("hasRole('ORGANIZER')")
@DeleteMapping("/{sessionId}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ data class UpdateSessionPlaceResponse(

@Schema(description = "장소", example = "온라인")
val place: PlaceResponse,

@Schema(description = "세션 코드", example = "1234")
val code: String?,
) {
companion object {
fun fromDomain(session: Session): UpdateSessionPlaceResponse {
Expand All @@ -42,6 +45,7 @@ data class UpdateSessionPlaceResponse(
startTime = startTime.toString(),
sessionType = sessionType.name,
place = place.let(PlaceResponse::fromDomain),
code = code,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class UpdateSessionResponse(

@Schema(description = "장소", example = "온라인")
val place: PlaceResponse,

@Schema(description = "세션 코드", example = "1234")
val code: String?,
) {
companion object {
fun fromDomain(session: Session): UpdateSessionResponse {
Expand All @@ -42,6 +45,7 @@ class UpdateSessionResponse(
startTime = startTime.toString(),
sessionType = sessionType.name,
place = place.let { PlaceResponse.fromDomain(it) },
code = code,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.depromeet.makers.domain.usecase

import com.depromeet.makers.domain.gateway.SessionGateway
import com.depromeet.makers.domain.model.Place
import com.depromeet.makers.domain.model.Session
import com.depromeet.makers.domain.model.SessionType
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldBeInteger
import io.mockk.every
import io.mockk.mockk
import java.time.LocalDateTime

class RefreshSessionCodeTest :
BehaviorSpec({
Given("세션 코드를 갱신할 때") {
val sessionGateway = mockk<SessionGateway>()
val refreshSessionCode = RefreshSessionCode(sessionGateway = sessionGateway)

val previousCode = "previousCode"
val mockSession =
Session(
sessionId = "123e4567-e89b-12d3-a456-426614174000",
generation = 15,
week = 1,
title = "세션 제목",
description = "세션 설명",
startTime = LocalDateTime.of(2030, 10, 1, 10, 0),
sessionType = SessionType.OFFLINE,
place =
Place.newPlace(
name = "테스트 장소",
address = "전북 익산시 부송동 100",
longitude = 35.9418,
latitude = 126.9544,
),
code = previousCode,
)

every { sessionGateway.getById(any()) } returns mockSession
every { sessionGateway.save(any()) } returns mockSession.update(code = Session.generateCode())

When("execute가 실행되면") {
val result =
refreshSessionCode.execute(
sessionId = mockSession.sessionId,
)

Then("세션 코드가 갱신된 세션이 반환된다") {
result.code shouldNotBe previousCode
result.code shouldNotBe null
result.code.shouldBeInteger()
result.code!!.length shouldBe 4
}
}
}
})

0 comments on commit b6b4a12

Please sign in to comment.