diff --git a/src/main/kotlin/com/didit/application/achievement/MissionQueryService.kt b/src/main/kotlin/com/didit/application/achievement/MissionQueryService.kt index 8556caf4..93670291 100644 --- a/src/main/kotlin/com/didit/application/achievement/MissionQueryService.kt +++ b/src/main/kotlin/com/didit/application/achievement/MissionQueryService.kt @@ -5,7 +5,6 @@ import com.didit.application.achievement.dto.MissionInfo import com.didit.application.achievement.dto.PopupStatus import com.didit.application.achievement.dto.WeeklyStatus import com.didit.application.achievement.exception.CurrentMissionNotFoundException -import com.didit.application.achievement.exception.MissionDefinitionNotFoundException import com.didit.application.achievement.exception.UserLevelNotFoundException import com.didit.application.achievement.provided.MissionFinder import com.didit.application.achievement.required.MissionRepository @@ -34,11 +33,21 @@ class MissionQueryService( ) : MissionFinder { override fun getCurrentMission(userId: UUID): CurrentMissionResponse { val userLevel = userLevelRepository.findByUserId(userId) ?: throw UserLevelNotFoundException(userId) + val missionLevel = userLevel.currentLevel + 1 + val mission = missionRepository.findByLevel(missionLevel) + + if (mission == null) { + val lastMission = userMissionRepository.findByUserId(userId).firstOrNull() + return CurrentMissionResponse( + currentLevel = userLevel.currentLevel, + mission = null, + weeklyStatus = buildWeeklyStatusForUser(userId), + popup = lastMission?.let { getPopupStatus(it) } ?: PopupStatus(exists = false, type = null), + ) + } + val userMission = userMissionRepository.findCurrentMissionByUserId(userId) ?: throw CurrentMissionNotFoundException(userId) - val missionLevel = userLevel.currentLevel + 1 - val mission = - missionRepository.findByLevel(missionLevel) ?: throw MissionDefinitionNotFoundException(missionLevel) val missionInfo = MissionInfo( @@ -86,7 +95,10 @@ class MissionQueryService( if (mission.missionType != MissionType.CONSECUTIVE_WEEK) { return null } + return buildWeeklyStatusForUser(userId) + } + private fun buildWeeklyStatusForUser(userId: UUID): WeeklyStatus { val weekStartDate = getWeekStartDate(ServiceTime.today()) val from = ServiceTime.startOfDayUtc(weekStartDate) val to = ServiceTime.startOfDayUtc(weekStartDate.plusWeeks(1)) diff --git a/src/main/kotlin/com/didit/application/achievement/UserMissionService.kt b/src/main/kotlin/com/didit/application/achievement/UserMissionService.kt index a5b433f8..bfdf919d 100644 --- a/src/main/kotlin/com/didit/application/achievement/UserMissionService.kt +++ b/src/main/kotlin/com/didit/application/achievement/UserMissionService.kt @@ -35,6 +35,7 @@ class UserMissionService( override fun confirmLevelUp(userId: UUID) { val userMission = userMissionRepository.findCurrentMissionByUserId(userId) + ?: userMissionRepository.findByUserId(userId).firstOrNull() ?: throw CurrentMissionNotFoundException(userId) userMission.levelUpPopupShown = true diff --git a/src/main/kotlin/com/didit/application/achievement/dto/CurrentMissionResponse.kt b/src/main/kotlin/com/didit/application/achievement/dto/CurrentMissionResponse.kt index d2e2b0d6..2a8ddbcd 100644 --- a/src/main/kotlin/com/didit/application/achievement/dto/CurrentMissionResponse.kt +++ b/src/main/kotlin/com/didit/application/achievement/dto/CurrentMissionResponse.kt @@ -2,7 +2,7 @@ package com.didit.application.achievement.dto data class CurrentMissionResponse( val currentLevel: Int, - val mission: MissionInfo, + val mission: MissionInfo?, val weeklyStatus: WeeklyStatus?, val popup: PopupStatus, ) diff --git a/src/test/kotlin/com/didit/application/achievement/MissionQueryServiceTest.kt b/src/test/kotlin/com/didit/application/achievement/MissionQueryServiceTest.kt index 2866ede5..97bd509b 100644 --- a/src/test/kotlin/com/didit/application/achievement/MissionQueryServiceTest.kt +++ b/src/test/kotlin/com/didit/application/achievement/MissionQueryServiceTest.kt @@ -1,7 +1,6 @@ package com.didit.application.achievement import com.didit.application.achievement.exception.CurrentMissionNotFoundException -import com.didit.application.achievement.exception.MissionDefinitionNotFoundException import com.didit.application.achievement.exception.UserLevelNotFoundException import com.didit.application.achievement.required.MissionRepository import com.didit.application.achievement.required.UserLevelRepository @@ -74,10 +73,10 @@ class MissionQueryServiceTest { val result = missionQueryService.getCurrentMission(userId) assertThat(result.currentLevel).isEqualTo(0) - assertThat(result.mission.type).isEqualTo("FIRST_RETRO") - assertThat(result.mission.progress).isEqualTo(0) - assertThat(result.mission.target).isEqualTo(1) - assertThat(result.mission.remainingDays).isNull() + assertThat(result.mission!!.type).isEqualTo("FIRST_RETRO") + assertThat(result.mission!!.progress).isEqualTo(0) + assertThat(result.mission!!.target).isEqualTo(1) + assertThat(result.mission!!.remainingDays).isNull() assertThat(result.weeklyStatus).isNull() assertThat(result.popup.exists).isFalse() } @@ -103,8 +102,8 @@ class MissionQueryServiceTest { val result = missionQueryService.getCurrentMission(userId) assertThat(result.currentLevel).isEqualTo(1) - assertThat(result.mission.type).isEqualTo("TIME_LIMITED") - assertThat(result.mission.remainingDays).isEqualTo(5) + assertThat(result.mission!!.type).isEqualTo("TIME_LIMITED") + assertThat(result.mission!!.remainingDays).isEqualTo(5) assertThat(result.weeklyStatus).isNull() } @@ -130,7 +129,7 @@ class MissionQueryServiceTest { val result = missionQueryService.getCurrentMission(userId) assertThat(result.currentLevel).isEqualTo(2) - assertThat(result.mission.type).isEqualTo("CONSECUTIVE_WEEK") + assertThat(result.mission!!.type).isEqualTo("CONSECUTIVE_WEEK") assertThat(result.weeklyStatus).isNotNull() assertThat(result.weeklyStatus!!.days).hasSize(7) } @@ -147,6 +146,7 @@ class MissionQueryServiceTest { fun `현재 미션이 없으면 CurrentMissionNotFoundException을 발생시킨다`() { val userLevel = UserLevel(userId = userId, currentLevel = 1) whenever(userLevelRepository.findByUserId(userId)).thenReturn(userLevel) + whenever(missionRepository.findByLevel(2)).thenReturn(Mission.timeLimited()) whenever(userMissionRepository.findCurrentMissionByUserId(userId)).thenReturn(null) assertThatThrownBy { missionQueryService.getCurrentMission(userId) } @@ -154,16 +154,23 @@ class MissionQueryServiceTest { } @Test - fun `미션 정의가 없으면 MissionDefinitionNotFoundException을 발생시킨다`() { - val userLevel = UserLevel(userId = userId, currentLevel = 0) - val userMission = UserMission(userId = userId, missionId = UUID.randomUUID()) + fun `최고 레벨(미션 정의 없음)이면 mission이 null이고 주간 현황을 반환한다`() { + val userLevel = UserLevel(userId = userId, currentLevel = 10) whenever(userLevelRepository.findByUserId(userId)).thenReturn(userLevel) - whenever(userMissionRepository.findCurrentMissionByUserId(userId)).thenReturn(userMission) - whenever(missionRepository.findByLevel(1)).thenReturn(null) + whenever(missionRepository.findByLevel(11)).thenReturn(null) + whenever(userMissionRepository.findByUserId(userId)).thenReturn(emptyList()) + whenever(retrospectiveRepository.findCompletedByUserIdAndPeriod(eq(userId), any(), any())).thenReturn( + emptyList(), + ) - assertThatThrownBy { missionQueryService.getCurrentMission(userId) } - .isInstanceOf(MissionDefinitionNotFoundException::class.java) + val result = missionQueryService.getCurrentMission(userId) + + assertThat(result.currentLevel).isEqualTo(10) + assertThat(result.mission).isNull() + assertThat(result.weeklyStatus).isNotNull() + assertThat(result.weeklyStatus!!.days).hasSize(7) + assertThat(result.popup.exists).isFalse() } @Test