diff --git a/raisedragon-api/build.gradle.kts b/raisedragon-api/build.gradle.kts index d260304..fb3db71 100644 --- a/raisedragon-api/build.gradle.kts +++ b/raisedragon-api/build.gradle.kts @@ -9,6 +9,7 @@ tasks.jar { val swaggerVersion: String by project.extra dependencies { + implementation(project(":raisedragon-common")) implementation(project(":raisedragon-core")) implementation(project(":raisedragon-external")) api("org.springframework.boot:spring-boot-starter-data-jpa:3.0.4") diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/betting/BettingApplicationService.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/betting/BettingApplicationService.kt index 139d715..adc8526 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/betting/BettingApplicationService.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/betting/BettingApplicationService.kt @@ -81,7 +81,7 @@ class BettingApplicationService( private fun Betting.validateStartDate() { val now = LocalDateTime.now() - val goalStartDate = goalService.loadById(goalId).startDate + val goalStartDate = goalService.findById(goalId).startDate if (now.toLocalDate() >= goalStartDate.toLocalDate()) { throw BaseException.of(ExceptionCode.E400_BAD_REQUEST, "이미 시작한 내기 입니다.") } diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goal/GoalApplicationService.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goal/GoalApplicationService.kt index 201d750..3071225 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goal/GoalApplicationService.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goal/GoalApplicationService.kt @@ -9,7 +9,6 @@ import com.whatever.raisedragon.domain.goal.* import com.whatever.raisedragon.domain.goalgifticon.GoalGifticonService import com.whatever.raisedragon.domain.goalproof.GoalProofService import com.whatever.raisedragon.domain.user.UserService -import com.whatever.raisedragon.domain.user.fromDto import com.whatever.raisedragon.domain.winner.WinnerService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -33,7 +32,7 @@ class GoalApplicationService( exceptionCode = ExceptionCode.E409_CONFLICT, executionMessage = "다짐을 생성하는 중, 생성할 수 있는 다짐 갯수를 초과하였습니다." ) - if (goalService.existsByUserIdAndAnyResult(request.userId, GoalResult.PROCEEDING)) throw BaseException.of( + if (goalService.existsByUserIdAndAnyGoalResult(request.userId, GoalResult.PROCEEDING)) throw BaseException.of( exceptionCode = ExceptionCode.E409_CONFLICT, executionMessage = "다짐을 생성하는 중, 이미 생성한 다짐이 있어 생성이 불가합니다." ) @@ -58,13 +57,13 @@ class GoalApplicationService( } fun retrieveGoal(goalId: Long): GoalResponse { - val goal = goalService.loadById(goalId) + val goal = goalService.findById(goalId) val hostUser = userService.loadById(goal.userId) return GoalResponse.of(goal, hostUser.nickname.value) } fun retrieveGoalDetail(goalId: Long, userId: Long): GoalWithBettingResponse { - val goal = goalService.loadById(goalId) + val goal = goalService.findById(goalId) val hostUser = userService.loadById(goal.userId) val betting = bettingService.loadUserAndGoal(userId, goalId) val goalProofs = goalProofService.findAllByGoalIdAndUserId(goalId, userId) @@ -80,7 +79,7 @@ class GoalApplicationService( } fun retrieveAllByUserId(userId: Long): List { - val goals = goalService.loadAllByUserId(userId) + val goals = goalService.findAllByUserId(userId) val users = userService.findAllByIdInIds(goals.map { it.userId }.toSet()) return goals.map { goal -> @@ -95,9 +94,9 @@ class GoalApplicationService( fun retrieveGoalBettingParticipant( goalId: Long ): GoalRetrieveParticipantResponse { - val goal = goalService.loadById(goalId) + val goal = goalService.findById(goalId) val hostUser = userService.loadById(goal.userId) - val bettingList = bettingService.loadAllByGoalId(goalId) + val bettingList = bettingService.findAllByGoalId(goalId) val hostDto = GoalBettingHostResponse( id = hostUser.id!!, @@ -125,9 +124,9 @@ class GoalApplicationService( fun retrieveGoalBettingParticipantNoAuth( goalId: Long ): GoalRetrieveParticipantResponse { - val goal = goalService.loadById(goalId) + val goal = goalService.findById(goalId) val goalHostUser = userService.loadById(goal.userId) - val bettingList = bettingService.loadAllByGoalId(goalId) + val bettingList = bettingService.findAllByGoalId(goalId) val hostDto = GoalBettingHostResponse( id = goalHostUser.id!!, @@ -178,13 +177,12 @@ class GoalApplicationService( @Transactional fun modifyGoal(request: GoalModifyServiceRequest): GoalResponse { - val goal = goalService.loadById(request.goalId) + val goal = goalService.findById(request.goalId) isNotUsersGoal(goal, request.userId) isAlreadyStarted(goal) - val modifiedGoal = goalService.modify( - goal = goal, - userEntity = userService.loadById(request.userId).fromDto(), + val modifiedGoal = goalService.updateContent( + goalId = goal.id, content = request.content ) @@ -194,14 +192,11 @@ class GoalApplicationService( @Transactional fun deleteGoal(request: GoalDeleteServiceRequest) { - val goal = goalService.loadById(request.goalId) + val goal = goalService.findById(request.goalId) isNotUsersGoal(goal, request.userId) isAlreadyStarted(goal) - goalService.softDelete( - goal = goal, - userEntity = userService.loadById(request.userId).fromDto(), - ) + goalService.softDelete(goal.id) } private fun isNotUsersGoal(goal: Goal, userId: Long) { @@ -223,6 +218,6 @@ class GoalApplicationService( } private fun isNumberOfGoalUnderOneHundred(userId: Long): Boolean { - return goalService.loadAllByUserId(userId).size > 99 + return goalService.findAllByUserId(userId).size > 99 } } \ No newline at end of file diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt index a918e76..2c7a3e3 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt @@ -29,7 +29,7 @@ class GoalGifticonApplicationService( @Transactional fun createAndUploadGifticon(request: GoalGifticonCreateServiceRequest): GoalGifticonResponse { - val goal = goalService.loadById(request.goalId) + val goal = goalService.findById(request.goalId) if (isNotBettingTypeBilling(goal.type)) throw BaseException.of( exceptionCode = ExceptionCode.E400_BAD_REQUEST, executionMessage = "기프티콘을 업르도하는 중, 무료 다짐에는 기프티콘을 업로드할 수 없습니다." @@ -65,7 +65,7 @@ class GoalGifticonApplicationService( userId: Long ): GifticonResponse { val user = userService.loadById(userId) - val goal = goalService.loadById(goalId) + val goal = goalService.findById(goalId) isBrokenTiming(goal) val goalGifticon = if (userId != goal.userId) { @@ -93,7 +93,7 @@ class GoalGifticonApplicationService( @Transactional fun updateGifticonURLByGoalId(request: GoalGifticonUpdateServiceRequest): GoalGifticonResponse { val userEntity = userService.loadById(request.userId).fromDto() - val goal = goalService.loadById(request.goalId).fromDto(userEntity).toDto() + val goal = goalService.findById(request.goalId).fromDto(userEntity).toDto() val goalGifticon = goalGifticonService.loadByGoalAndUserEntity( goal = goal, userEntity = userEntity diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalproof/GoalProofApplicationService.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalproof/GoalProofApplicationService.kt index ee18d4e..cac6bca 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalproof/GoalProofApplicationService.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalproof/GoalProofApplicationService.kt @@ -10,12 +10,10 @@ import com.whatever.raisedragon.domain.goalproof.Comment import com.whatever.raisedragon.domain.goalproof.GoalProof import com.whatever.raisedragon.domain.goalproof.GoalProofService import com.whatever.raisedragon.domain.user.UserService -import com.whatever.raisedragon.domain.user.fromDto import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime import java.time.temporal.ChronoUnit -import kotlin.math.abs @Service @Transactional(readOnly = true) @@ -27,7 +25,7 @@ class GoalProofApplicationService( @Transactional fun create(request: GoalProofCreateServiceRequest): GoalProofCreateUpdateResponse { - val goal = goalService.loadById(request.goalId) + val goal = goalService.findById(request.goalId) val user = userService.loadById(request.userId) isGoalProofAlreadyExists(request.goalId) @@ -39,7 +37,7 @@ class GoalProofApplicationService( url = URL(request.url), comment = request.comment ) - goalService.increaseThreshold(goal, user.fromDto()) + goalService.increaseThreshold(goal.id) return GoalProofCreateUpdateResponse(GoalProofRetrieveResponse.of(goalProof)) } @@ -63,7 +61,7 @@ class GoalProofApplicationService( fun retrieveAll(goalId: Long, userId: Long): GoalProofListRetrieveResponse { val goalProofs = goalProofService.findAllByGoalIdAndUserId(goalId, userId) - val goalStartDateTime = goalService.loadById(goalId).startDate + val goalStartDateTime = goalService.findById(goalId).startDate val progressDays = goalProofs.map { it.createdAt!!.dayOfMonth.minus(goalStartDateTime.dayOfMonth) + 1 @@ -126,7 +124,7 @@ class GoalProofApplicationService( } private fun GoalProof.validateEndDate() { - if (goalService.loadById(goalId).endDate > LocalDateTime.now()) { + if (goalService.findById(goalId).endDate > LocalDateTime.now()) { throw BaseException.of(ExceptionCode.E400_BAD_REQUEST, "이미 끝난 내기입니다") } } diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/test/TestApplicationService.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/test/TestApplicationService.kt index f722c13..deb7c21 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/test/TestApplicationService.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/test/TestApplicationService.kt @@ -24,13 +24,13 @@ class TestApplicationService( @Transactional fun confirmGoalResult(goalId: Long) { - val goal = goalService.loadById(goalId) + val goal = goalService.findById(goalId) val goalProofCount = goalProofService.countAllByGoalId(goal.id) // TODO: using 7 instead of goal's threshold. must be changed to goal's threshold after confirming business requirements val goalResult = if (goalProofCount >= 7) GoalResult.SUCCESS else GoalResult.FAIL goalService.updateResult(goal.id, goalResult) - val bettingList = bettingService.findAllByGoalIdAndNotDeleted(goal.id) + val bettingList = bettingService.findAllByGoalId(goal.id) val failedBettingList = mutableListOf() val succeedBettingList = mutableListOf() bettingList.forEach { betting -> diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/user/UserApplicationService.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/user/UserApplicationService.kt index a92b8f6..795fd65 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/user/UserApplicationService.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/user/UserApplicationService.kt @@ -47,8 +47,7 @@ class UserApplicationService( @Transactional fun delete(id: Long) { - val user = userService.loadById(id) - if (goalService.findProceedingGoalIsExistsByUser(user)) { + if (goalService.existsByUserAndEndDateIsAfterThanNow(id)) { throw BaseException.of( exceptionCode = ExceptionCode.E400_BAD_REQUEST, executionMessage = "아직 진행중인 다짐이 있어 회원탈퇴에 실패했습니다." diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/ApiExceptionHandler.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/ApiExceptionHandler.kt index 7ef96f4..7d3faca 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/ApiExceptionHandler.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/ApiExceptionHandler.kt @@ -11,7 +11,6 @@ import org.springframework.web.bind.MissingServletRequestParameterException import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestControllerAdvice -import org.springframework.web.context.request.WebRequest import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException @RestControllerAdvice diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/scheduler/GoalResultScheduler.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/scheduler/GoalResultScheduler.kt index 71c4a1d..6d04f8c 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/scheduler/GoalResultScheduler.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/scheduler/GoalResultScheduler.kt @@ -34,7 +34,7 @@ class GoalResultScheduler( val now = LocalDateTime.now() logger.info("Start adjusting result of goals at {}", now) val endDate = LocalDateTime.of(now.year, now.month, now.dayOfMonth, 23, 59, 59, 59) - val betGoalList = goalService.findAllByEndDateLessThanEqualAndResultIsProceeding(endDate) + val betGoalList = goalService.findAllByEndDateLessThanEqualAndGoalResultIsProceeding(endDate) betGoalList.forEach(::confirmGoalResult) logger.info("Done adjusting result for {} goals, at {}", betGoalList.size, LocalDateTime.now()) } @@ -45,7 +45,7 @@ class GoalResultScheduler( val goalResult = if (goalProofCount >= 7) GoalResult.SUCCESS else GoalResult.FAIL goalService.updateResult(goal.id, goalResult) - val bettingList = bettingService.findAllByGoalIdAndNotDeleted(goal.id) + val bettingList = bettingService.findAllByGoalId(goal.id) val failedBettingList = mutableListOf() val succeedBettingList = mutableListOf() bettingList.forEach { betting -> diff --git a/raisedragon-common/build.gradle.kts b/raisedragon-common/build.gradle.kts new file mode 100644 index 0000000..571b417 --- /dev/null +++ b/raisedragon-common/build.gradle.kts @@ -0,0 +1,2 @@ +dependencies { +} \ No newline at end of file diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/exception/BaseException.kt b/raisedragon-common/src/main/kotlin/com/whatever/raisedragon/common/exception/BaseException.kt similarity index 100% rename from raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/exception/BaseException.kt rename to raisedragon-common/src/main/kotlin/com/whatever/raisedragon/common/exception/BaseException.kt diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/exception/ExceptionCode.kt b/raisedragon-common/src/main/kotlin/com/whatever/raisedragon/common/exception/ExceptionCode.kt similarity index 89% rename from raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/exception/ExceptionCode.kt rename to raisedragon-common/src/main/kotlin/com/whatever/raisedragon/common/exception/ExceptionCode.kt index 63302f8..be82755 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/common/exception/ExceptionCode.kt +++ b/raisedragon-common/src/main/kotlin/com/whatever/raisedragon/common/exception/ExceptionCode.kt @@ -1,6 +1,5 @@ package com.whatever.raisedragon.common.exception -import com.whatever.raisedragon.common.ErrorResponse import org.springframework.http.HttpStatus enum class ExceptionCode( @@ -38,11 +37,4 @@ fun ExceptionCode.throwAsException() { exceptionCode = this, executionMessage = message ) -} - -fun ExceptionCode.toErrorResponse(): ErrorResponse { - return ErrorResponse( - code = code, - detailMessage = message - ) } \ No newline at end of file diff --git a/raisedragon-core/build.gradle.kts b/raisedragon-core/build.gradle.kts index 4dda0f1..dc65551 100644 --- a/raisedragon-core/build.gradle.kts +++ b/raisedragon-core/build.gradle.kts @@ -1,4 +1,5 @@ dependencies { + implementation(project(":raisedragon-common")) implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.0.4") runtimeOnly("com.mysql:mysql-connector-j:8.0.32") diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/common/config/ExceptionSuppliers.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/common/config/ExceptionSuppliers.kt new file mode 100644 index 0000000..c61d6d2 --- /dev/null +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/common/config/ExceptionSuppliers.kt @@ -0,0 +1,24 @@ +package com.whatever.raisedragon.common.config + +import com.whatever.raisedragon.common.exception.BaseException +import com.whatever.raisedragon.common.exception.ExceptionCode +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import java.util.function.Supplier + +@Configuration +class ExceptionSuppliers { + + @Bean + @Qualifier("notFoundExceptionSupplier") + fun notFoundExceptionSupplier(): Supplier { + return Supplier { BaseException.of(ExceptionCode.E404_NOT_FOUND) } + } + + @Bean + @Qualifier("InternalExceptionSupplier") + fun internalExceptionSupplier(): Supplier { + return Supplier { BaseException.of(ExceptionCode.E500_INTERNAL_SERVER_ERROR) } + } +} \ No newline at end of file diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/betting/BettingService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/betting/BettingService.kt index 33401a6..df10a10 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/betting/BettingService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/betting/BettingService.kt @@ -1,15 +1,19 @@ package com.whatever.raisedragon.domain.betting +import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.domain.goal.GoalRepository import com.whatever.raisedragon.domain.user.UserRepository +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime +import java.util.function.Supplier @Service @Transactional(readOnly = true) class BettingService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, private val bettingRepository: BettingRepository, private val userRepository: UserRepository, private val goalRepository: GoalRepository, @@ -22,8 +26,10 @@ class BettingService( ): Betting { val betting = bettingRepository.save( BettingEntity( - userEntity = userRepository.findById(userId).get(), - goalEntity = goalRepository.findById(goalId).get(), + userEntity = userRepository.findById(userId) + .orElseThrow(notFoundExceptionSupplier), + goalEntity = goalRepository.findById(goalId) + .orElseThrow(notFoundExceptionSupplier), bettingPredictionType = bettingPredictionType, bettingResult = BettingResult.PROCEEDING ) @@ -36,23 +42,17 @@ class BettingService( goalId: Long ): Betting? { return bettingRepository.findByUserEntityAndGoalEntity( - userEntity = userRepository.findById(userId).get(), - goalEntity = goalRepository.findById(goalId).get() + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier), + goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) )?.toDto() } - fun findAllByGoalIdAndNotDeleted(goalId: Long): List { - return bettingRepository.findAllByGoalEntity( - goalEntity = goalRepository.findByIdOrNull(goalId) - ?: throw IllegalStateException("cannot find goal $goalId") - ).map { it.toDto() } - } - - fun loadAllByGoalId( + fun findAllByGoalId( goalId: Long ): List { return bettingRepository.findAllByGoalEntity( - goalEntity = goalRepository.findById(goalId).get() + goalEntity = goalRepository.findById(goalId) + .orElseThrow(notFoundExceptionSupplier) ).map { it.toDto() } } @@ -61,14 +61,12 @@ class BettingService( } fun findAllByUserId(userId: Long): List { - val userEntity = - userRepository.findByIdOrNull(userId) ?: throw IllegalStateException("cannot find user $userId") + val userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) return bettingRepository.findAllByUserEntity(userEntity).map { it.toDto() } } fun existsBettingParticipantUser(userId: Long): Boolean { - val userEntity = - userRepository.findByIdOrNull(userId) ?: throw IllegalStateException("cannot find user $userId") + val userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) val bettings = bettingRepository.findAllByUserEntity(userEntity) for (betting in bettings) { @@ -79,8 +77,7 @@ class BettingService( @Transactional fun update(bettingId: Long, bettingPredictionType: BettingPredictionType): Betting { - val betting = bettingRepository.findByIdOrNull(bettingId) - ?: throw IllegalStateException("Cannot find betting $bettingId") + val betting = bettingRepository.findById(bettingId).orElseThrow(notFoundExceptionSupplier) if (betting.bettingPredictionType != bettingPredictionType) { betting.bettingPredictionType = bettingPredictionType } @@ -89,8 +86,7 @@ class BettingService( @Transactional fun updateResult(bettingId: Long, bettingResult: BettingResult): Betting { - val betting = bettingRepository.findByIdOrNull(bettingId) - ?: throw IllegalStateException("Cannot find betting $bettingId") + val betting = bettingRepository.findById(bettingId).orElseThrow(notFoundExceptionSupplier) if (betting.bettingResult != bettingResult) { betting.bettingResult = bettingResult } @@ -104,23 +100,21 @@ class BettingService( @Transactional fun softDelete(bettingId: Long) { - val betting = bettingRepository.findByIdOrNull(bettingId) - ?: throw IllegalStateException("Cannot find betting $bettingId") + val betting = bettingRepository.findById(bettingId).orElseThrow(notFoundExceptionSupplier) betting.deletedAt = LocalDateTime.now() } @Transactional fun hardDelete(bettingId: Long) { - val betting = bettingRepository.findByIdOrNull(bettingId) - ?: throw IllegalStateException("Cannot find betting $bettingId") + val betting = bettingRepository.findById(bettingId).orElseThrow(notFoundExceptionSupplier) bettingRepository.delete(betting) } @Transactional fun hardDeleteByUserId(userId: Long) { - val bettings = bettingRepository.findAllByUserEntity( - userEntity = userRepository.findByIdOrNull(userId) ?: throw IllegalArgumentException("Cannot find user $userId") + val bettingEntities = bettingRepository.findAllByUserEntity( + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) ) - bettingRepository.deleteAll(bettings) + bettingRepository.deleteAll(bettingEntities) } } \ No newline at end of file diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonService.kt index 914f34a..b0be530 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonService.kt @@ -1,13 +1,16 @@ package com.whatever.raisedragon.domain.gifticon +import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.domain.user.UserRepository -import org.springframework.data.repository.findByIdOrNull +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.function.Supplier @Transactional(readOnly = true) @Service class GifticonService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, private val gifticonRepository: GifticonRepository, private val userRepository: UserRepository ) { @@ -19,7 +22,7 @@ class GifticonService( ): Gifticon { val gifticon = gifticonRepository.save( GifticonEntity( - userEntity = userRepository.findById(userId).get(), + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier), url = URL(url) ) ) @@ -27,14 +30,14 @@ class GifticonService( } fun loadById(gifticonId: Long): Gifticon { - return gifticonRepository.findById(gifticonId).get().toDto() + return gifticonRepository.findById(gifticonId).orElseThrow(notFoundExceptionSupplier).toDto() } @Transactional fun hardDeleteByUserId(userId: Long) { - val gifticons = gifticonRepository.findAllByUserEntity( - userEntity = userRepository.findByIdOrNull(userId) ?: throw IllegalArgumentException("Cannot find user $userId") + val gifticonEntities = gifticonRepository.findAllByUserEntity( + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) ) - gifticonRepository.deleteAll(gifticons) + gifticonRepository.deleteAll(gifticonEntities) } } \ No newline at end of file diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goal/GoalService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goal/GoalService.kt index 3ba508f..544dbbd 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goal/GoalService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goal/GoalService.kt @@ -1,17 +1,17 @@ package com.whatever.raisedragon.domain.goal -import com.whatever.raisedragon.domain.user.User -import com.whatever.raisedragon.domain.user.UserEntity +import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.domain.user.UserRepository -import com.whatever.raisedragon.domain.user.fromDto -import org.springframework.data.repository.findByIdOrNull +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime +import java.util.function.Supplier @Transactional(readOnly = true) @Service class GoalService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, private val goalRepository: GoalRepository, private val userRepository: UserRepository ) { @@ -27,7 +27,7 @@ class GoalService( ): Goal { val goal = goalRepository.save( GoalEntity( - userEntity = userRepository.findById(userId).get(), + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier), goalType = goalType, content = content, threshold = threshold, @@ -39,20 +39,13 @@ class GoalService( return goal.toDto() } - fun loadById(id: Long): Goal { - return goalRepository.findByIdOrNull(id)?.toDto() - ?: throw IllegalArgumentException("다짐을 조회하는 중, 잘못된 내용을 요청하셨습니다.") + fun findById(id: Long): Goal { + return goalRepository.findById(id).orElseThrow(notFoundExceptionSupplier).toDto() } - fun existsByUserIdAndAnyResult(userId: Long, goalResult: GoalResult): Boolean { - val userEntity = userRepository.findByIdOrNull(userId) - ?: throw IllegalArgumentException("cannot find user $userId") - return goalRepository.findAllByUserEntityAndGoalResult(userEntity, goalResult).isNotEmpty() - } - - fun loadAllByUserId(userId: Long): List { + fun findAllByUserId(userId: Long): List { return goalRepository.findAllByUserEntity( - userRepository.findById(userId).get() + userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) ).map { it.toDto() } } @@ -60,69 +53,55 @@ class GoalService( return goalRepository.findAllById(goalIds).map { it.toDto() } } - fun findAllByEndDateLessThanEqualAndResultIsProceeding(endDate: LocalDateTime): List { - return goalRepository.findAllByEndDateLessThanEqualAndGoalResultIs(endDate, GoalResult.PROCEEDING).map { it.toDto() } + fun findAllByEndDateLessThanEqualAndGoalResultIsProceeding(endDate: LocalDateTime): List { + return goalRepository.findAllByEndDateLessThanEqualAndGoalResultIs(endDate, GoalResult.PROCEEDING) + .map { it.toDto() } + } + + fun existsByUserIdAndAnyGoalResult(userId: Long, goalResult: GoalResult): Boolean { + val userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) + return goalRepository.findAllByUserEntityAndGoalResult(userEntity, goalResult).isNotEmpty() + } + + fun existsByUserAndEndDateIsAfterThanNow(userId: Long): Boolean { + return goalRepository.existsByUserEntityAndEndDateIsAfter( + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier), + now = LocalDateTime.now() + ) } @Transactional fun updateResult(goalId: Long, goalResult: GoalResult): Goal { - val goalEntity = - goalRepository.findByIdOrNull(goalId) ?: throw IllegalStateException("cannot find goal $goalId") + val goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) goalEntity.goalResult = goalResult return goalEntity.toDto() } @Transactional - fun modify( - goal: Goal, - userEntity: UserEntity, - content: Content, - ): Goal { - val goalEntity = goal.fromDto(userEntity) + fun updateContent(goalId: Long, content: Content): Goal { + val goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) goalEntity.content = content - return goalEntity.toDto() } @Transactional - fun softDelete( - goal: Goal, - userEntity: UserEntity, - ): Goal { - val goalEntity = goal.fromDto(userEntity) - goalEntity.deletedAt = LocalDateTime.now() - - return goalEntity.toDto() + fun increaseThreshold(id: Long) { + val goalEntity = goalRepository.findById(id).orElseThrow(notFoundExceptionSupplier) + goalEntity.threshold = Threshold(goalEntity.threshold.value + 1) } @Transactional - fun hardDelete( - goal: Goal, - userEntity: UserEntity, - ) { - val goalEntity = goal.fromDto(userEntity) - goalRepository.delete(goalEntity) + fun softDelete(id: Long): Goal { + val goalEntity = goalRepository.findById(id).orElseThrow(notFoundExceptionSupplier) + goalEntity.deletedAt = LocalDateTime.now() + return goalEntity.toDto() } @Transactional fun hardDeleteByUserId(userId: Long) { val goals = goalRepository.findAllByUserEntity( - userEntity = userRepository.findByIdOrNull(userId) ?: throw IllegalArgumentException("Cannot find user $userId") + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) ) goalRepository.deleteAll(goals) } - - @Transactional - fun increaseThreshold(goal: Goal, userEntity: UserEntity) { - val goalEntity = goal.fromDto(userEntity) - goalEntity.threshold = Threshold(goalEntity.threshold.value + 1) - } - - fun findProceedingGoalIsExistsByUser(user: User): Boolean { - val existsByUserEntityAndEndDateIsAfter = goalRepository.existsByUserEntityAndEndDateIsAfter( - userEntity = user.fromDto(), - now = LocalDateTime.now() - ) - return existsByUserEntityAndEndDateIsAfter - } } \ No newline at end of file diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalgifticon/GoalGifticonService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalgifticon/GoalGifticonService.kt index 10e805a..6ef6380 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalgifticon/GoalGifticonService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalgifticon/GoalGifticonService.kt @@ -1,17 +1,20 @@ package com.whatever.raisedragon.domain.goalgifticon +import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.domain.gifticon.GifticonRepository import com.whatever.raisedragon.domain.goal.Goal import com.whatever.raisedragon.domain.goal.GoalRepository import com.whatever.raisedragon.domain.goal.fromDto import com.whatever.raisedragon.domain.user.UserEntity -import org.springframework.data.repository.findByIdOrNull +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.function.Supplier @Transactional(readOnly = true) @Service class GoalGifticonService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, private val goalGifticonRepository: GoalGifticonRepository, private val goalRepository: GoalRepository, private val gifticonRepository: GifticonRepository @@ -25,15 +28,15 @@ class GoalGifticonService( ): GoalGifticon { val goalGifticon = goalGifticonRepository.save( GoalGifticonEntity( - goalEntity = goalRepository.findById(goalId).get(), - gifticonEntity = gifticonRepository.findById(gifticonId).get() + goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier), + gifticonEntity = gifticonRepository.findById(gifticonId).orElseThrow(notFoundExceptionSupplier) ) ) return goalGifticon.toDto() } fun loadById(id: Long): GoalGifticon { - return goalGifticonRepository.findById(id).get().toDto() + return goalGifticonRepository.findById(id).orElseThrow(notFoundExceptionSupplier).toDto() } fun loadByGoalAndUserEntity( @@ -41,11 +44,11 @@ class GoalGifticonService( userEntity: UserEntity ): GoalGifticon? { return goalGifticonRepository.findByGoalEntity(goal.fromDto(userEntity))?.toDto() + ?: throw notFoundExceptionSupplier.get() } fun findByGoalId(goalId: Long): GoalGifticon? { - val goalEntity = - goalRepository.findByIdOrNull(goalId) ?: throw IllegalStateException("cannot find goal $goalId") + val goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) return goalGifticonRepository.findByGoalEntity(goalEntity)?.toDto() } } \ No newline at end of file diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofService.kt index 374b0af..223a12a 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofService.kt @@ -1,5 +1,6 @@ package com.whatever.raisedragon.domain.goalproof +import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.domain.gifticon.URL import com.whatever.raisedragon.domain.goal.Goal import com.whatever.raisedragon.domain.goal.GoalRepository @@ -7,14 +8,16 @@ import com.whatever.raisedragon.domain.goal.fromDto import com.whatever.raisedragon.domain.user.User import com.whatever.raisedragon.domain.user.UserRepository import com.whatever.raisedragon.domain.user.fromDto -import org.springframework.data.repository.findByIdOrNull +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime +import java.util.function.Supplier @Service @Transactional(readOnly = true) class GoalProofService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, private val goalRepository: GoalRepository, private val userRepository: UserRepository, private val goalProofRepository: GoalProofRepository @@ -56,36 +59,31 @@ class GoalProofService( 59 ) return goalProofRepository.existsByGoalEntityAndCreatedAtBetween( - goalEntity = goalRepository.findByIdOrNull(goalId) - ?: throw throw IllegalArgumentException("cannot find goal $goalId"), + goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier), todayStartDateTime = todayStartDateTime, todayEndDateTime = todayEndDateTime ) } fun findById(goalProofId: Long): GoalProof? { - return goalProofRepository.findByIdOrNull(goalProofId)?.toDto() + return goalProofRepository.findById(goalProofId).orElseThrow(notFoundExceptionSupplier).toDto() } fun countAllByGoalId(goalId: Long): Int { - val goalEntity = - goalRepository.findByIdOrNull(goalId) ?: throw IllegalArgumentException("cannot find goal $goalId") + val goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) return goalProofRepository.countAllByGoalEntity(goalEntity) } fun findAllByGoalIdAndUserId(goalId: Long, userId: Long): List { - val goalEntity = - goalRepository.findByIdOrNull(goalId) ?: throw IllegalArgumentException("cannot find goal $goalId") - val userEntity = - userRepository.findByIdOrNull(userId) ?: throw IllegalArgumentException("cannot find user $userId") + val goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) + val userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) return goalProofRepository.findAllByUserEntityAndGoalEntity(goalEntity = goalEntity, userEntity = userEntity) .map { it.toDto() } } @Transactional fun update(goalProofId: Long, url: URL? = null, comment: Comment? = null): GoalProof { - val goalProof = goalProofRepository.findByIdOrNull(goalProofId) - ?: throw IllegalArgumentException("cannot find goalProof $goalProofId") + val goalProof = goalProofRepository.findById(goalProofId).orElseThrow(notFoundExceptionSupplier) url?.let { goalProof.url = it } comment?.let { goalProof.comment = it } return goalProof.toDto() @@ -94,8 +92,7 @@ class GoalProofService( @Transactional fun hardDeleteByUserId(userId: Long) { val goalProofs = goalProofRepository.findAllByUserEntity( - userEntity = userRepository.findByIdOrNull(userId) - ?: throw IllegalArgumentException("Cannot find user $userId") + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) ) goalProofRepository.deleteAll(goalProofs) } diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/refreshtoken/RefreshTokenService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/refreshtoken/RefreshTokenService.kt index c538523..e042c4f 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/refreshtoken/RefreshTokenService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/refreshtoken/RefreshTokenService.kt @@ -1,16 +1,20 @@ package com.whatever.raisedragon.domain.refreshtoken +import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.domain.user.User import com.whatever.raisedragon.domain.user.UserEntity import com.whatever.raisedragon.domain.user.UserRepository import com.whatever.raisedragon.domain.user.fromDto -import org.springframework.data.repository.findByIdOrNull +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.function.Supplier @Service @Transactional(readOnly = true) class RefreshTokenService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, + @Qualifier("internalExceptionSupplier") private val internalExceptionSupplier: Supplier, private val refreshTokenRepository: RefreshTokenRepository, private val userRepository: UserRepository ) { @@ -36,8 +40,8 @@ class RefreshTokenService( @Transactional fun hardDeleteByUserId(userId: Long) { val refreshTokenEntity = refreshTokenRepository.findByUserEntity( - userEntity = userRepository.findByIdOrNull(userId) ?: throw IllegalArgumentException("Cannot find user $userId") - )!! + userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) + ) ?: throw internalExceptionSupplier.get() refreshTokenRepository.delete(refreshTokenEntity) } } \ No newline at end of file diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/user/UserService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/user/UserService.kt index 8123df1..97e90fb 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/user/UserService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/user/UserService.kt @@ -1,12 +1,15 @@ package com.whatever.raisedragon.domain.user -import org.springframework.data.repository.findByIdOrNull +import com.whatever.raisedragon.common.exception.BaseException +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.function.Supplier @Service @Transactional(readOnly = true) class UserService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, private val userRepository: UserRepository, ) { @@ -15,7 +18,7 @@ class UserService( } fun loadById(id: Long): User { - return userRepository.findByIdOrNull(id)?.toDto() ?: throw IllegalArgumentException("유저를 불러오는 중, 잘못된 값을 요청하셨습니다.") + return userRepository.findById(id).orElseThrow(notFoundExceptionSupplier).toDto() } fun findAllByIdInIds(ids: Set): List { @@ -33,7 +36,7 @@ class UserService( @Transactional fun updateNickname(id: Long, nickname: String): User { - val userEntity = userRepository.findByIdOrNull(id) ?: throw IllegalArgumentException("유저를 불러오는 중, 잘못된 값을 요청하셨습니다.") + val userEntity = userRepository.findById(id).orElseThrow(notFoundExceptionSupplier) userEntity.nickname = Nickname(nickname) return userEntity.toDto() } diff --git a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/winner/WinnerService.kt b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/winner/WinnerService.kt index 1063583..269c44a 100644 --- a/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/winner/WinnerService.kt +++ b/raisedragon-core/src/main/kotlin/com/whatever/raisedragon/domain/winner/WinnerService.kt @@ -1,16 +1,19 @@ package com.whatever.raisedragon.domain.winner +import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.domain.gifticon.GifticonRepository import com.whatever.raisedragon.domain.goal.GoalRepository import com.whatever.raisedragon.domain.user.Nickname import com.whatever.raisedragon.domain.user.UserRepository -import org.springframework.data.repository.findByIdOrNull +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.function.Supplier @Service @Transactional(readOnly = true) class WinnerService( + @Qualifier("notFoundExceptionSupplier") private val notFoundExceptionSupplier: Supplier, private val winnerRepository: WinnerRepository, private val goalRepository: GoalRepository, private val userRepository: UserRepository, @@ -20,28 +23,24 @@ class WinnerService( @Transactional fun create(goalId: Long, userId: Long, gifticonId: Long): Winner { val goalEntity = - goalRepository.findByIdOrNull(goalId) ?: throw IllegalStateException("cannot find goal $goalId") + goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) val userEntity = - userRepository.findByIdOrNull(userId) ?: throw IllegalStateException("cannot find user $userId") - val gifticonEntity = gifticonRepository.findByIdOrNull(gifticonId) - ?: throw IllegalStateException("cannot find gifticon $gifticonId") + userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) + val gifticonEntity = gifticonRepository.findById(gifticonId).orElseThrow(notFoundExceptionSupplier) val winnerEntity = WinnerEntity(goalEntity, userEntity, gifticonEntity) winnerRepository.save(winnerEntity) return winnerEntity.toDto() } fun findByGoalIdAndUserId(goalId: Long, userId: Long): Winner? { - val goalEntity = - goalRepository.findByIdOrNull(goalId) ?: throw IllegalStateException("cannot find goal $goalId") - val userEntity = - userRepository.findByIdOrNull(userId) ?: throw IllegalStateException("cannot find user $userId") + val goalEntity = goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier) + val userEntity = userRepository.findById(userId).orElseThrow(notFoundExceptionSupplier) return winnerRepository.findByGoalEntityAndUserEntity(goalEntity, userEntity)?.toDto() } fun findWinnerNicknameByGoalId(goalId: Long): Nickname? { return winnerRepository - .findByGoalEntity(goalRepository.findByIdOrNull(goalId) - ?: throw IllegalStateException("cannot find goal $goalId")) + .findByGoalEntity(goalRepository.findById(goalId).orElseThrow(notFoundExceptionSupplier)) ?.userEntity?.nickname } } \ No newline at end of file diff --git a/raisedragon-core/src/main/resources/ddl/V1_DDL.sql b/raisedragon-core/src/main/resources/ddl/V1_DDL.sql index 31f1e02..438bcbb 100644 --- a/raisedragon-core/src/main/resources/ddl/V1_DDL.sql +++ b/raisedragon-core/src/main/resources/ddl/V1_DDL.sql @@ -44,7 +44,7 @@ create table if not exists refresh_token updated_at datetime(6) not null ); -create table if not exists user +create table if not exists users ( id bigint auto_increment primary key, nickname varchar(255) not null, diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/RepositoryTestSupport.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/IntegrationTestSupport.kt similarity index 50% rename from raisedragon-core/src/test/kotlin/com/whatever/raisedragon/RepositoryTestSupport.kt rename to raisedragon-core/src/test/kotlin/com/whatever/raisedragon/IntegrationTestSupport.kt index cef5207..f66a92c 100644 --- a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/RepositoryTestSupport.kt +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/IntegrationTestSupport.kt @@ -1,8 +1,8 @@ package com.whatever.raisedragon -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles @ActiveProfiles("test") -@DataJpaTest -class RepositoryTestSupport \ No newline at end of file +@SpringBootTest +interface IntegrationTestSupport \ No newline at end of file diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/RaiseDragonApplicationTests.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/RaiseDragonApplicationTests.kt index 1cdf1fb..e198d8e 100644 --- a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/RaiseDragonApplicationTests.kt +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/RaiseDragonApplicationTests.kt @@ -1,8 +1,6 @@ package com.whatever.raisedragon import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.data.jpa.repository.config.EnableJpaAuditing @SpringBootApplication -@EnableJpaAuditing class RaiseDragonApplicationTests \ No newline at end of file diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/betting/BettingRepositoryTest.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/betting/BettingRepositoryTest.kt index fef5739..2370214 100644 --- a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/betting/BettingRepositoryTest.kt +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/betting/BettingRepositoryTest.kt @@ -1,6 +1,6 @@ package com.whatever.raisedragon.domain.betting -import com.whatever.raisedragon.RepositoryTestSupport +import com.whatever.raisedragon.IntegrationTestSupport import com.whatever.raisedragon.domain.betting.BettingPredictionType.FAIL import com.whatever.raisedragon.domain.betting.BettingPredictionType.SUCCESS import com.whatever.raisedragon.domain.betting.BettingResult.* @@ -8,6 +8,7 @@ import com.whatever.raisedragon.domain.goal.* import com.whatever.raisedragon.domain.user.Nickname import com.whatever.raisedragon.domain.user.UserEntity import com.whatever.raisedragon.domain.user.UserRepository +import jakarta.transaction.Transactional import org.assertj.core.api.Assertions.assertThat import org.assertj.core.groups.Tuple.tuple import org.junit.jupiter.api.DisplayName @@ -15,7 +16,8 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import java.time.LocalDateTime -class BettingRepositoryTest : RepositoryTestSupport() { +@Transactional +class BettingRepositoryTest : IntegrationTestSupport { @Autowired private lateinit var bettingRepository: BettingRepository diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonRepositoryTest.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonRepositoryTest.kt index 4cb0273..c07d75c 100644 --- a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonRepositoryTest.kt +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/gifticon/GifticonRepositoryTest.kt @@ -1,16 +1,18 @@ package com.whatever.raisedragon.domain.gifticon -import com.whatever.raisedragon.RepositoryTestSupport +import com.whatever.raisedragon.IntegrationTestSupport import com.whatever.raisedragon.domain.user.Nickname import com.whatever.raisedragon.domain.user.UserEntity import com.whatever.raisedragon.domain.user.UserRepository +import jakarta.transaction.Transactional import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.tuple import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired -class GifticonRepositoryTest : RepositoryTestSupport() { +@Transactional +class GifticonRepositoryTest : IntegrationTestSupport { @Autowired private lateinit var gifticonRepository: GifticonRepository diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goal/GoalRepositoryTest.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goal/GoalRepositoryTest.kt index 9cb3b03..7419740 100644 --- a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goal/GoalRepositoryTest.kt +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goal/GoalRepositoryTest.kt @@ -1,12 +1,13 @@ package com.whatever.raisedragon.domain.goal -import com.whatever.raisedragon.RepositoryTestSupport +import com.whatever.raisedragon.IntegrationTestSupport import com.whatever.raisedragon.domain.goal.GoalResult.* import com.whatever.raisedragon.domain.goal.GoalType.BILLING import com.whatever.raisedragon.domain.goal.GoalType.FREE import com.whatever.raisedragon.domain.user.Nickname import com.whatever.raisedragon.domain.user.UserEntity import com.whatever.raisedragon.domain.user.UserRepository +import jakarta.transaction.Transactional import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.tuple import org.junit.jupiter.api.DisplayName @@ -14,7 +15,8 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import java.time.LocalDateTime -class GoalRepositoryTest : RepositoryTestSupport() { +@Transactional +class GoalRepositoryTest : IntegrationTestSupport { @Autowired private lateinit var goalRepository: GoalRepository diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goal/GoalServiceTest.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goal/GoalServiceTest.kt new file mode 100644 index 0000000..a3d90e2 --- /dev/null +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goal/GoalServiceTest.kt @@ -0,0 +1,631 @@ +package com.whatever.raisedragon.domain.goal + +import com.whatever.raisedragon.IntegrationTestSupport +import com.whatever.raisedragon.common.exception.BaseException +import com.whatever.raisedragon.common.exception.ExceptionCode +import com.whatever.raisedragon.domain.goal.GoalResult.* +import com.whatever.raisedragon.domain.goal.GoalType.* +import com.whatever.raisedragon.domain.user.Nickname +import com.whatever.raisedragon.domain.user.UserEntity +import com.whatever.raisedragon.domain.user.UserRepository +import jakarta.transaction.Transactional +import org.assertj.core.api.Assertions.* +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import java.time.LocalDateTime + +@Transactional +class GoalServiceTest : IntegrationTestSupport { + + @Autowired + private lateinit var goalService: GoalService + + @Autowired + private lateinit var goalRepository: GoalRepository + + @Autowired + private lateinit var userRepository: UserRepository + + @DisplayName("기본적인 Goal를 생성한다.") + @Test + fun create1() { + // given + val userEntity = UserEntity(nickname = Nickname("User")) + userRepository.save(userEntity) + + val content = Content("Sample content") + val goalType = FREE + val threshold = Threshold(5) + val startDate = LocalDateTime.now() + val endDate = startDate.plusDays(7) + + // when + val goal = goalService.create( + userId = userEntity.id, + content = content, + goalType = goalType, + threshold = threshold, + startDate = startDate, + endDate = endDate + ) + + // then + assertThat(goal) + .isInstanceOf(Goal::class.java) + .isEqualTo( + Goal( + id = goal.id, + userId = userEntity.id, + type = goalType, + content = content, + threshold = threshold, + goalResult = PROCEEDING, + startDate = startDate, + endDate = endDate, + createdAt = goal.createdAt, + updatedAt = goal.updatedAt, + deletedAt = goal.deletedAt + ) + ) + } + + @DisplayName("잘못된 userId를 가지고 요청한 경우 예외가 발생한다.") + @Test + fun create2() { + // given + val userEntity = UserEntity(nickname = Nickname("User")) + userRepository.save(userEntity) + + val content = Content("Sample content") + val goalType = FREE + val threshold = Threshold(5) + val startDate = LocalDateTime.now() + val endDate = startDate.plusDays(7) + + // when // then + assertThatThrownBy { + goalService.create( + userId = -1, + content = content, + goalType = goalType, + threshold = threshold, + startDate = startDate, + endDate = endDate + ) + } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("id에 해당하는 Goal를 조회한다.") + @Test + fun loadById1() { + // given + val userEntity = UserEntity(nickname = Nickname("User")) + userRepository.save(userEntity) + + val goalEntity = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity) + + // when + val foundGoal = goalService.findById(goalEntity.id) + + // then + assertThat(foundGoal) + .isInstanceOf(Goal::class.java) + .isEqualTo( + Goal( + id = goalEntity.id, + userId = userEntity.id, + type = goalEntity.goalType, + content = goalEntity.content, + threshold = goalEntity.threshold, + goalResult = goalEntity.goalResult, + startDate = goalEntity.startDate, + endDate = goalEntity.endDate, + createdAt = goalEntity.createdAt, + updatedAt = goalEntity.updatedAt, + deletedAt = goalEntity.deletedAt + ) + ) + } + + @DisplayName("잘못된 goalId를 가지고 요청한 경우 예외가 발생한다.") + @Test + fun loadById2() { + // given + val userEntity = UserEntity(nickname = Nickname("User")) + userRepository.save(userEntity) + + val goalEntity = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity) + + // when // then + assertThatThrownBy { goalService.findById(-1L) }.isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("userId와 GoalResult가 같은 Goal이 있으면 true를 반환한다.") + @Test + fun existsByUserIdAndAnyGoalResult1() { + // given + val userEntity = UserEntity(nickname = Nickname("User")) + userRepository.save(userEntity) + + val goalEntity1 = createGoalEntity(userEntity, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + val isExist = goalService.existsByUserIdAndAnyGoalResult(userEntity.id, PROCEEDING) + + // then + assertThat(isExist).isTrue() + } + + @DisplayName("userId와 GoalResult가 같은 Goal가 없으면 false를 반환한다.") + @Test + fun existsByUserIdAndAnyGoalResult2() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val goalEntity1 = createGoalEntity(userEntity1, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity2, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity2, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + val isExist = goalService.existsByUserIdAndAnyGoalResult(userEntity2.id, PROCEEDING) + + // then + assertThat(isExist).isFalse() + } + + @DisplayName("userId와 GoalResult가 같은 Goal이 있는지 확인할 때 요청된 id로 저장된 유저를 찾을 수 없는 경우 예외가 발생한다.") + @Test + fun existsByUserIdAndAnyGoalResult3() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val goalEntity1 = createGoalEntity(userEntity1, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity2, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity2, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when // then + assertThatThrownBy { + goalService.existsByUserIdAndAnyGoalResult(-1L, PROCEEDING) + }.isInstanceOf(BaseException::class.java).hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("userId가 같은 Goal를 모두 조회한다.") + @Test + fun loadAllByUserId1() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val goalEntity1 = createGoalEntity(userEntity1, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity1, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity2, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + val goalList = goalService.findAllByUserId(userEntity1.id) + + // then + assertThat(goalList).hasSize(2) + .extracting("userId", "type", "goalResult") + .containsExactlyInAnyOrder( + tuple(userEntity1.id, FREE, PROCEEDING), + tuple(userEntity1.id, BILLING, FAIL), + ) + } + + @DisplayName("userId가 같은 Goal를 모두 찾는 중 해당하는 유저가 없는 경우 예외가 발생한다.") + @Test + fun loadAllByUserId2() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val goalEntity1 = createGoalEntity(userEntity1, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity1, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity2, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when // then + assertThatThrownBy { goalService.findAllByUserId(-1L) } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("ids에 포함되는 id를 갖는 모든 Goal를 모두 조회한다.") + @Test + fun findAllByIds() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val goalEntity1 = createGoalEntity(userEntity1, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity1, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity2, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + val goals = goalService.findAllByIds(setOf(goalEntity1.id, goalEntity3.id)) + + // then + assertThat(goals).hasSize(2) + .extracting("id", "userId", "type", "goalResult") + .containsExactlyInAnyOrder( + tuple(goalEntity1.id, userEntity1.id, FREE, PROCEEDING), + tuple(goalEntity3.id, userEntity2.id, FREE, SUCCESS), + ) + } + + @DisplayName("endDate가 요청한 endDate보다 적거나 같으며 GoalResult가 PROCEEDING인 모든 Goal를 조회한다.") + @Test + fun findAllByEndDateLessThanEqualAndGoalResultIsProceeding() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val specificEndDate = LocalDateTime.now() + val goalEntity1 = createGoalEntity( + userEntity = userEntity1, + goalType = FREE, + goalResult = PROCEEDING, + endDateTime = specificEndDate.minusSeconds(1) + ) + val goalEntity2 = createGoalEntity( + userEntity = userEntity1, + goalType = BILLING, + goalResult = FAIL, + endDateTime = specificEndDate.minusSeconds(1) + ) + val goalEntity3 = createGoalEntity( + userEntity = userEntity2, + goalType = FREE, + goalResult = PROCEEDING, + endDateTime = specificEndDate.plusSeconds(1) + ) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + val foundGoal = goalService.findAllByEndDateLessThanEqualAndGoalResultIsProceeding(specificEndDate) + + // then + assertThat(foundGoal).hasSize(1) + .first() + .isEqualTo(goalEntity1.toDto()) + } + + @DisplayName("요청된 id의 Goal의 GoalResult를 수정한다.") + @Test + fun updateResult1() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val goalEntity1 = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity1) + + // when + val foundGoal = goalService.updateResult(goalEntity1.id, FAIL) + + // then + assertThat(foundGoal).isInstanceOf(Goal::class.java) + assertThat(foundGoal.goalResult).isEqualTo(FAIL) + } + + @DisplayName("요청된 id의 Goal의 GoalResult를 수정할 때 해당하는 Goal이 없는 경우 예외가 발생한다.") + @Test + fun updateResult2() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val goalEntity1 = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity1) + + // when // then + assertThatThrownBy { goalService.updateResult(-1L, FAIL) } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("요청한 id의 Goal의 content를 변경한다") + @Test + fun updateContent1() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val goalEntity = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity) + + // when + val foundGoal = goalService.updateContent(goalEntity.id, Content("Modified")) + + // then + assertThat(foundGoal).isInstanceOf(Goal::class.java) + assertThat(foundGoal.content).isEqualTo(Content("Modified")) + } + + @DisplayName("요청한 id의 Goal의 content를 변경할 때 id에 해당하는 Goal이 없는 경우 예외가 발생한다.") + @Test + fun updateContent2() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val goalEntity = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity) + + // when // then + assertThatThrownBy { goalService.updateContent(-1L, Content("Modified")) } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("요청한 id의 Goal를 soft-delete 한다.") + @Test + fun softDelete1() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val goalEntity = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity) + + // when + val foundGoal = goalService.softDelete(goalEntity.id) + + // then + assertThat(foundGoal).isInstanceOf(Goal::class.java) + assertThat(foundGoal.deletedAt).isNotNull() + } + + @DisplayName("요청한 id의 Goal를 soft-delete 할 때 요청한 id의 Goal이 없는 경우 예외가 발생한다.") + @Test + fun softDelete2() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val goalEntity = createGoalEntity(userEntity, FREE, PROCEEDING) + goalRepository.save(goalEntity) + + // when // then + assertThatThrownBy { goalService.softDelete(-1L) } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("userId를 갖는 모든 Goal를 hard-delete 한다.") + @Test + fun hardDeleteByUserId1() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val goalEntity1 = createGoalEntity(userEntity1, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity1, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity2, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + goalService.hardDeleteByUserId(userEntity1.id) + + // then + assertThat( + goalRepository.findAllById(listOf(goalEntity1.id, goalEntity2.id)) + ).isEmpty() + } + + @DisplayName("userId를 갖는 모든 Goal를 hard-delete 할 때 userId에 해당하는 User가 없으면 예외가 발생한다.") + @Test + fun hardDeleteByUserId2() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val goalEntity1 = createGoalEntity(userEntity1, FREE, PROCEEDING) + val goalEntity2 = createGoalEntity(userEntity1, BILLING, FAIL) + val goalEntity3 = createGoalEntity(userEntity2, FREE, SUCCESS) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when // then + assertThatThrownBy { goalService.hardDeleteByUserId(-1L) } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("id에 해당하는 Goal의 Threshold = 1 증가시킨다.") + @Test + fun increaseThreshold1() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val threshold = Threshold(7) + val goalEntity = GoalEntity( + userEntity = userEntity, + goalType = FREE, + content = Content("sampleContent"), + threshold = threshold, + goalResult = PROCEEDING, + startDate = LocalDateTime.now(), + endDate = LocalDateTime.now() + ) + goalRepository.save(goalEntity) + + // when + goalService.increaseThreshold(goalEntity.id) + + // then + assertThat(goalRepository.findById(goalEntity.id).get().threshold).isEqualTo(Threshold(8)) + } + + @DisplayName("id에 해당하는 Goal의 Threshold = 1 증가시킬 때 id에 해당하는 Goal이 없을 때 예외가 발생한다.") + @Test + fun increaseThreshold2() { + // given + val userEntity = UserEntity(nickname = Nickname("User1")) + userRepository.save(userEntity) + + val threshold = Threshold(7) + val goalEntity = GoalEntity( + userEntity = userEntity, + goalType = FREE, + content = Content("sampleContent"), + threshold = threshold, + goalResult = PROCEEDING, + startDate = LocalDateTime.now(), + endDate = LocalDateTime.now() + ) + goalRepository.save(goalEntity) + + // when // then + assertThatThrownBy { goalService.increaseThreshold(-1L) } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + @DisplayName("요청한 User가 생성한 Goal 중 endDate가 현재 시간 이후인 Goal이 있으면 true를 반환합니다.") + @Test + fun existsByUserAndEndDateIsAfterThanNow1() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val now = LocalDateTime.now() + val goalEntity1 = createGoalEntity( + userEntity = userEntity1, + goalType = FREE, + goalResult = PROCEEDING, + endDateTime = now.plusSeconds(1) + ) + val goalEntity2 = createGoalEntity( + userEntity = userEntity1, + goalType = BILLING, + goalResult = FAIL, + endDateTime = now.minusSeconds(1) + ) + val goalEntity3 = createGoalEntity( + userEntity = userEntity2, + goalType = FREE, + goalResult = SUCCESS, + endDateTime = now.plusSeconds(1) + ) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + val result = goalService.existsByUserAndEndDateIsAfterThanNow(userEntity1.id) + + // then + assertThat(result).isTrue() + } + + @DisplayName("요청한 User가 생성한 Goal 중 endDate가 현재 시간 이후인 Goal이 없으면 false를 반환합니다.") + @Test + fun existsByUserAndEndDateIsAfterThanNow2() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val now = LocalDateTime.now() + val goalEntity1 = createGoalEntity( + userEntity = userEntity1, + goalType = FREE, + goalResult = PROCEEDING, + endDateTime = now.minusSeconds(1) + ) + val goalEntity2 = createGoalEntity( + userEntity = userEntity1, + goalType = BILLING, + goalResult = FAIL, + endDateTime = now.minusSeconds(1) + ) + val goalEntity3 = createGoalEntity( + userEntity = userEntity2, + goalType = FREE, + goalResult = SUCCESS, + endDateTime = now.plusSeconds(1) + ) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + val result = goalService.existsByUserAndEndDateIsAfterThanNow(userEntity1.id) + + // then + assertThat(result).isFalse() + } + + @DisplayName("요청한 User가 생성한 Goal 중 endDate가 현재 시간 이후인 Goal이 있는지 확인할 때 userId에 해당하는 User가 없으면 예외가 발생한다.") + @Test + fun existsByUserAndEndDateIsAfterThanNow3() { + // given + val userEntity1 = UserEntity(nickname = Nickname("User1")) + val userEntity2 = UserEntity(nickname = Nickname("User2")) + userRepository.saveAll(listOf(userEntity1, userEntity2)) + + val now = LocalDateTime.now() + val goalEntity1 = createGoalEntity( + userEntity = userEntity1, + goalType = FREE, + goalResult = PROCEEDING, + endDateTime = now.minusSeconds(1) + ) + val goalEntity2 = createGoalEntity( + userEntity = userEntity1, + goalType = BILLING, + goalResult = FAIL, + endDateTime = now.minusSeconds(1) + ) + val goalEntity3 = createGoalEntity( + userEntity = userEntity2, + goalType = FREE, + goalResult = SUCCESS, + endDateTime = now.plusSeconds(1) + ) + goalRepository.saveAll(listOf(goalEntity1, goalEntity2, goalEntity3)) + + // when + assertThatThrownBy { goalService.existsByUserAndEndDateIsAfterThanNow(-1L) } + .isInstanceOf(BaseException::class.java) + .hasMessage(ExceptionCode.E404_NOT_FOUND.message) + } + + private fun createGoalEntity( + userEntity: UserEntity, + goalType: GoalType, + goalResult: GoalResult, + startDateTime: LocalDateTime = LocalDateTime.now(), + endDateTime: LocalDateTime = startDateTime.plusDays(7) + ): GoalEntity { + return GoalEntity( + userEntity = userEntity, + goalType = goalType, + content = Content("sampleContent"), + goalResult = goalResult, + startDate = startDateTime, + endDate = endDateTime + ) + } +} \ No newline at end of file diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofRepositoryTest.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofRepositoryTest.kt index f925785..daddeba 100644 --- a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofRepositoryTest.kt +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/goalproof/GoalProofRepositoryTest.kt @@ -1,6 +1,6 @@ package com.whatever.raisedragon.domain.goalproof -import com.whatever.raisedragon.RepositoryTestSupport +import com.whatever.raisedragon.IntegrationTestSupport import com.whatever.raisedragon.domain.gifticon.URL import com.whatever.raisedragon.domain.goal.* import com.whatever.raisedragon.domain.goal.GoalResult.PROCEEDING @@ -10,6 +10,7 @@ import com.whatever.raisedragon.domain.goal.GoalType.FREE import com.whatever.raisedragon.domain.user.Nickname import com.whatever.raisedragon.domain.user.UserEntity import com.whatever.raisedragon.domain.user.UserRepository +import jakarta.transaction.Transactional import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.DisplayName @@ -17,7 +18,8 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import java.time.LocalDateTime -class GoalProofRepositoryTest : RepositoryTestSupport() { +@Transactional +class GoalProofRepositoryTest : IntegrationTestSupport { @Autowired private lateinit var goalProofRepository: GoalProofRepository diff --git a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/user/UserRepositoryTest.kt b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/user/UserRepositoryTest.kt index f8810cb..a9303e0 100644 --- a/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/user/UserRepositoryTest.kt +++ b/raisedragon-core/src/test/kotlin/com/whatever/raisedragon/domain/user/UserRepositoryTest.kt @@ -1,12 +1,14 @@ package com.whatever.raisedragon.domain.user -import com.whatever.raisedragon.RepositoryTestSupport +import com.whatever.raisedragon.IntegrationTestSupport +import jakarta.transaction.Transactional import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired -class UserRepositoryTest : RepositoryTestSupport() { +@Transactional +class UserRepositoryTest : IntegrationTestSupport { @Autowired private lateinit var userRepository: UserRepository diff --git a/settings.gradle.kts b/settings.gradle.kts index 1c74772..b486fa7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,3 +2,4 @@ rootProject.name = "raisedragon" include("raisedragon-core") include("raisedragon-api") include("raisedragon-external") +include("raisedragon-common")