103 lines
3.9 KiB
Kotlin

package roomescape.user.business
import com.github.f4b6a3.tsid.TsidFactory
import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import roomescape.common.config.next
import roomescape.common.dto.CurrentUserContext
import roomescape.common.dto.UserLoginCredentials
import roomescape.common.dto.toCredentials
import roomescape.user.exception.UserErrorCode
import roomescape.user.exception.UserException
import roomescape.user.infrastructure.persistence.*
import roomescape.user.web.UserContactResponse
import roomescape.user.web.UserCreateRequest
import roomescape.user.web.UserCreateResponse
import roomescape.user.web.toEntity
private val log: KLogger = KotlinLogging.logger {}
const val SIGNUP: String = "최초 가입"
@Service
class UserService(
private val userRepository: UserRepository,
private val userStatusHistoryRepository: UserStatusHistoryRepository,
private val userValidator: UserValidator,
private val tsidFactory: TsidFactory
) {
@Transactional(readOnly = true)
fun findContextById(id: Long): CurrentUserContext {
log.info { "[UserService.findContextById] 현재 로그인된 회원 조회 시작: id=${id}" }
val user: UserEntity = findOrThrow(id)
return CurrentUserContext(user.id, user.name)
.also {
log.info { "[UserService.findContextById] 현재 로그인된 회원 조회 완료: id=${id}" }
}
}
@Transactional(readOnly = true)
fun findCredentialsByAccount(email: String): UserLoginCredentials {
log.info { "[UserService.findCredentialsByAccount] 회원 조회 시작: email=${email}" }
return userRepository.findByEmail(email)
?.let {
log.info { "[UserService.findCredentialsByAccount] 회원 조회 완료: id=${it.id}" }
it.toCredentials()
}
?: run {
log.info { "[UserService.findCredentialsByAccount] 회원 조회 실패" }
throw UserException(UserErrorCode.USER_NOT_FOUND)
}
}
@Transactional(readOnly = true)
fun findContactById(id: Long) : UserContactResponse {
log.info { "[UserService.findContactById] 회원 연락 정보 조회 시작: id=${id}" }
val user = findOrThrow(id)
return UserContactResponse(user.id, user.name, user.phone)
.also {
log.info { "[UserService.findContactById] 회원 연락 정보 조회 완료: id=${id}, name=${it.name}" }
}
}
@Transactional
fun signup(request: UserCreateRequest): UserCreateResponse {
log.info { "[UserService.signup] 회원가입 시작: request:$request" }
userValidator.validateCanSignup(request.email, request.phone)
val user: UserEntity = userRepository.save(
request.toEntity(id = tsidFactory.next(), status = UserStatus.ACTIVE)
).also {
log.info { "[UserService.signup] 회원 저장 완료: id:${it.id}" }
}.also {
createHistory(user = it, reason = SIGNUP)
}
return UserCreateResponse(user.id, user.name)
.also {
log.info { "[UserService.signup] 회원가입 완료: id:${it.id}" }
}
}
private fun findOrThrow(id: Long): UserEntity {
return userRepository.findByIdOrNull(id)
?: throw UserException(UserErrorCode.USER_NOT_FOUND)
}
private fun createHistory(user: UserEntity, reason: String): UserStatusHistoryEntity {
return userStatusHistoryRepository.save(
UserStatusHistoryEntity(id = tsidFactory.next(), userId = user.id, reason = reason, status = user.status)
).also {
log.info { "[UserService.signup] 회원 상태 이력 저장 완료: userStatusHistoryId:${it.id}" }
}
}
}