Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/main/kotlin/com/didit/adapter/webapi/home/HomeApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.didit.adapter.webapi.home.dto.HomeResponse
import com.didit.adapter.webapi.home.dto.HomeV2Response
import com.didit.adapter.webapi.response.SuccessResponse
import com.didit.adapter.webapi.retrospect.dto.RetrospectiveListItemV2Response
import com.didit.application.achievement.provided.MissionFinder
import com.didit.application.achievement.provided.UserMissionRegister
import com.didit.application.auth.provided.UserFinder
import com.didit.application.notification.provided.NotificationHistoryFinder
import com.didit.application.retrospect.provided.RetrospectiveFinder
Expand All @@ -19,6 +21,8 @@ class HomeApi(
private val userFinder: UserFinder,
private val retrospectiveFinder: RetrospectiveFinder,
private val notificationHistoryFinder: NotificationHistoryFinder,
private val missionFinder: MissionFinder,
private val userMissionRegister: UserMissionRegister,
) {
@Deprecated("Use v2 endpoint", replaceWith = ReplaceWith("getHomeV2"))
@RequireAuth
Expand Down Expand Up @@ -47,6 +51,8 @@ class HomeApi(
fun getHomeV2(
@CurrentUserId userId: UUID,
): SuccessResponse<HomeV2Response> {
userMissionRegister.ensureInitialized(userId)

val user = userFinder.findByIdOrThrow(userId)
val recentRetros = retrospectiveFinder.findRecentWithProjectAndTagsByUserId(userId, limit = 5)
val todayCount = retrospectiveFinder.countByUserIdAndDate(userId, ServiceTime.today())
Expand All @@ -56,6 +62,7 @@ class HomeApi(
nickname = user.nickname ?: "",
todayRetrospectiveCount = todayCount,
hasUnreadNotification = notificationHistoryFinder.hasUnread(userId),
mission = missionFinder.getCurrentMission(userId),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle users with no current mission on home

When a user finishes the level-10 mission, MissionProgressService.awardNextLevel returns without creating another UserMission, while findCurrentMissionByUserId only returns IN_PROGRESS/WAIT_CONFIRM missions, so this new unguarded call throws CURRENT_MISSION_NOT_FOUND and turns /api/v2/home into a 500 for users who complete the mission ladder. Consider returning a terminal/null mission state for home instead of letting the aggregation fail.

Useful? React with 👍 / 👎.

recentRetrospectives =
recentRetros.map {
RetrospectiveListItemV2Response.from(it)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.didit.adapter.webapi.home.dto

import com.didit.adapter.webapi.retrospect.dto.RetrospectiveListItemV2Response
import com.didit.application.achievement.dto.CurrentMissionResponse

data class HomeV2Response(
val nickname: String,
val todayRetrospectiveCount: Int,
val hasUnreadNotification: Boolean,
val mission: CurrentMissionResponse,
val recentRetrospectives: List<RetrospectiveListItemV2Response>,
)
29 changes: 28 additions & 1 deletion src/test/kotlin/com/didit/adapter/webapi/home/HomeApiTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.didit.adapter.webapi.home

import com.didit.application.achievement.dto.CurrentMissionResponse
import com.didit.application.achievement.dto.MissionInfo
import com.didit.application.achievement.dto.PopupStatus
import com.didit.application.achievement.provided.MissionFinder
import com.didit.application.achievement.provided.UserMissionRegister
import com.didit.application.auth.provided.UserFinder
import com.didit.application.notification.provided.NotificationHistoryFinder
import com.didit.application.retrospect.dto.RetrospectiveDetailResult
Expand All @@ -19,15 +24,35 @@ import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get
import org.springframework.restdocs.payload.JsonFieldType
import org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath
import org.springframework.restdocs.payload.PayloadDocumentation.responseFields
import org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import java.util.UUID

class HomeApiTest : AuthenticatedRestDocsSupport() {
private val userFinder: UserFinder = mock(UserFinder::class.java)
private val retrospectiveFinder: RetrospectiveFinder = mock(RetrospectiveFinder::class.java)
private val notificationHistoryFinder: NotificationHistoryFinder = mock(NotificationHistoryFinder::class.java)
private val missionFinder: MissionFinder = mock(MissionFinder::class.java)
private val userMissionRegister: UserMissionRegister = mock(UserMissionRegister::class.java)

override fun initController() = HomeApi(userFinder, retrospectiveFinder, notificationHistoryFinder)
override fun initController() = HomeApi(userFinder, retrospectiveFinder, notificationHistoryFinder, missionFinder, userMissionRegister)

private fun currentMission() =
CurrentMissionResponse(
currentLevel = 0,
mission =
MissionInfo(
type = "FIRST_RETRO",
title = "첫 회고 작성하기",
description = "첫 회고를 작성해보세요",
progress = 0,
target = 1,
remainingDays = null,
cta = "회고 시작하기",
),
weeklyStatus = null,
popup = PopupStatus(exists = false, type = null),
)

@Test
fun `홈 조회`() {
Expand Down Expand Up @@ -74,6 +99,7 @@ class HomeApiTest : AuthenticatedRestDocsSupport() {
whenever(retrospectiveFinder.findRecentWithProjectAndTagsByUserId(userId, 5)).thenReturn(listOf(result))
whenever(retrospectiveFinder.countByUserIdAndDate(userId, ServiceTime.today())).thenReturn(1)
whenever(notificationHistoryFinder.hasUnread(userId)).thenReturn(true)
whenever(missionFinder.getCurrentMission(userId)).thenReturn(currentMission())

mockMvc
.perform(get("/api/v2/home"))
Expand All @@ -87,6 +113,7 @@ class HomeApiTest : AuthenticatedRestDocsSupport() {
fieldWithPath("data.nickname").type(JsonFieldType.STRING).description("닉네임"),
fieldWithPath("data.todayRetrospectiveCount").type(JsonFieldType.NUMBER).description("오늘 회고 횟수"),
fieldWithPath("data.hasUnreadNotification").type(JsonFieldType.BOOLEAN).description("안 읽은 알림 존재 여부"),
subsectionWithPath("data.mission").description("현재 미션/레벨 정보 (GET /api/v1/missions/current와 동일 구조)"),
fieldWithPath("data.recentRetrospectives").type(JsonFieldType.ARRAY).description("최근 회고 목록"),
fieldWithPath("data.recentRetrospectives[].id").type(JsonFieldType.STRING).description("회고 ID"),
fieldWithPath("data.recentRetrospectives[].title").type(JsonFieldType.STRING).description("회고 제목").optional(),
Expand Down
Loading