diff --git a/_endpoint_test/coin.http b/_endpoint_test/coin.http new file mode 100644 index 00000000..ced6abae --- /dev/null +++ b/_endpoint_test/coin.http @@ -0,0 +1,2 @@ +### 현재 유저 코인 정보 조회 +GET {{host}}/coin diff --git a/api/src/main/kotlin/com/mashup/dojo/CoinController.kt b/api/src/main/kotlin/com/mashup/dojo/CoinController.kt new file mode 100644 index 00000000..96ee6e75 --- /dev/null +++ b/api/src/main/kotlin/com/mashup/dojo/CoinController.kt @@ -0,0 +1,40 @@ +package com.mashup.dojo + +import com.mashup.dojo.common.DojoApiResponse +import com.mashup.dojo.domain.MemberId +import com.mashup.dojo.dto.CurrentCoinResponse +import com.mashup.dojo.usecase.CoinUseCase +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@Tag(name = "Coin", description = "코인 API") +@RestController +@RequestMapping("/coin") +class CoinController( + private val coinUseCase: CoinUseCase, +) { + @GetMapping + @Operation( + summary = "본인의 현재 코인을 조회합니다.", + description = "유저의 현재 남은 코인 정보를 조회합니다", + responses = [ + ApiResponse(responseCode = "200", description = "코인 정보 조회") + ] + ) + fun getCurrentCoin(): DojoApiResponse { // TODO : param UserInfo + val currentCoin = coinUseCase.getCurrentCoin(CoinUseCase.GetCurrentCoinCommand(MemberId("1"))) + + return DojoApiResponse.success( + CurrentCoinResponse( + coinId = currentCoin.id, + memberId = currentCoin.memberId, + amount = currentCoin.amount, + lastUpdatedAt = currentCoin.lastUpdatedAt + ) + ) + } +} diff --git a/api/src/main/kotlin/com/mashup/dojo/dto/CurrentCoinResponse.kt b/api/src/main/kotlin/com/mashup/dojo/dto/CurrentCoinResponse.kt new file mode 100644 index 00000000..84326ead --- /dev/null +++ b/api/src/main/kotlin/com/mashup/dojo/dto/CurrentCoinResponse.kt @@ -0,0 +1,21 @@ +package com.mashup.dojo.dto + +import com.mashup.dojo.domain.CoinId +import com.mashup.dojo.domain.MemberId +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import java.time.LocalDateTime + +@Schema(description = "현재 코인 정보 조회") +data class CurrentCoinResponse( + @Schema(description = "유저 id") + @field:NotBlank + val memberId: MemberId, + @Schema(description = "유저의 코인 id") + @field:NotBlank + val coinId: CoinId, + @Schema(description = "현재 유저의 보유 코인", example = "200L") + val amount: Long, + @Schema(description = "마지막으로 코인 정보가 변경된 시각") + val lastUpdatedAt: LocalDateTime, +) diff --git a/service/src/main/kotlin/com/mashup/dojo/domain/Coin.kt b/service/src/main/kotlin/com/mashup/dojo/domain/Coin.kt new file mode 100644 index 00000000..81116ece --- /dev/null +++ b/service/src/main/kotlin/com/mashup/dojo/domain/Coin.kt @@ -0,0 +1,29 @@ +package com.mashup.dojo.domain + +import java.time.LocalDateTime + +@JvmInline +value class CoinId(val value: String) + +data class Coin( + val id: CoinId, + val memberId: MemberId, + val amount: Long, + val lastUpdatedAt: LocalDateTime, +) + +@JvmInline +value class CoinUseDetailId(val value: String) + +data class CoinUseDetail( + val id: CoinUseDetailId, + val coinId: CoinId, + val useType: CoinUseType, + val reason: String, + val createdAt: LocalDateTime, +) + +enum class CoinUseType { + USED, + EARNED, +} diff --git a/service/src/main/kotlin/com/mashup/dojo/service/CoinService.kt b/service/src/main/kotlin/com/mashup/dojo/service/CoinService.kt new file mode 100644 index 00000000..b2845070 --- /dev/null +++ b/service/src/main/kotlin/com/mashup/dojo/service/CoinService.kt @@ -0,0 +1,31 @@ +package com.mashup.dojo.service + +import com.mashup.dojo.domain.Coin +import com.mashup.dojo.domain.CoinId +import com.mashup.dojo.domain.MemberId +import org.springframework.stereotype.Service +import java.time.LocalDateTime + +interface CoinService { + fun getCoin(memberId: MemberId): Coin +} + +@Service +class DefaultCoinService( + // TODO : private val coinRepository: CoinRepository +) : CoinService { + override fun getCoin(memberId: MemberId): Coin { + // return coinRepository.findByMemberId(memberId) + return DEFAULT_COIN_INFO + } + + companion object { + val DEFAULT_COIN_INFO = + Coin( + id = CoinId("1"), + memberId = MemberId("1"), + amount = 200L, + lastUpdatedAt = LocalDateTime.now() + ) + } +} diff --git a/service/src/main/kotlin/com/mashup/dojo/usecase/CoinUseCase.kt b/service/src/main/kotlin/com/mashup/dojo/usecase/CoinUseCase.kt new file mode 100644 index 00000000..ceca5463 --- /dev/null +++ b/service/src/main/kotlin/com/mashup/dojo/usecase/CoinUseCase.kt @@ -0,0 +1,21 @@ +package com.mashup.dojo.usecase + +import com.mashup.dojo.domain.Coin +import com.mashup.dojo.domain.MemberId +import com.mashup.dojo.service.CoinService +import org.springframework.stereotype.Component + +interface CoinUseCase { + data class GetCurrentCoinCommand(val memberId: MemberId) + + fun getCurrentCoin(command: GetCurrentCoinCommand): Coin +} + +@Component +class DefaultCoinUseCase( + private val coinService: CoinService, +) : CoinUseCase { + override fun getCurrentCoin(command: CoinUseCase.GetCurrentCoinCommand): Coin { + return coinService.getCoin(command.memberId) + } +}