diff --git a/domain/src/main/java/com/comit/domain/exception/ThrowUnknownException.kt b/domain/src/main/java/com/comit/domain/exception/ThrowUnknownException.kt index 869dc1a7..3a710d48 100644 --- a/domain/src/main/java/com/comit/domain/exception/ThrowUnknownException.kt +++ b/domain/src/main/java/com/comit/domain/exception/ThrowUnknownException.kt @@ -8,7 +8,6 @@ import com.google.firebase.ktx.Firebase * * NoInterNetException, NoConnectivityException 등 모든 경우에 사용되는 Exception은 별도로 처리 * Exception이 발생할 경우 Firebase Crashlytics에 제보합니다. - * */ fun throwUnknownException( e: Throwable, @@ -27,3 +26,28 @@ fun throwUnknownException( } } } + +/** + * 심통에서 예상 밖에 예외를 toast 방식으로 처리할 때 사용하는 함수 + * + * NoInterNetException, NoConnectivityException 등 모든 경우에 사용되는 Exception은 별도로 처리 + * Exception이 발생할 경우 Firebase Crashlytics에 제보합니다. + */ +fun throwUnknownExceptionForToast( + e: Throwable, + throwErrorMessage: (String) -> Unit, +) { + // TODO(limsaehyun): 인터넷 에러가 UnknwonException으로 감지됨 해결 필요 + // TODO(limsaehyun): 임시로 message text 로 구분 + if (e.message?.contains("NoInternetException") == true) throw NoInternetException() + if (e.message?.contains("NoConnectivityException") == true) throw NoInternetException() + + when (e) { + is NoInternetException -> throw NoInternetException() + is NoConnectivityException -> throw NoInternetException() + else -> { + Firebase.crashlytics.recordException(e) + throwErrorMessage(e.message ?: "알 수 없는 에러가 발생했습니다!") + } + } +} diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/calendar/SimTongCalendar.kt b/feature/feature-home/src/main/java/com/comit/feature_home/calendar/SimTongCalendar.kt index d9fdfbf0..815e9b56 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/calendar/SimTongCalendar.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/calendar/SimTongCalendar.kt @@ -80,6 +80,7 @@ enum class SimTongCalendarStatus( ), } +private val CalendarLoadingHeight: Dp = 255.dp private const val Week: Int = 7 @Stable @@ -216,7 +217,8 @@ fun SimTongCalendar( CircularProgressIndicator( color = SimTongColor.MainColor, modifier = Modifier - .fillMaxSize() + .fillMaxWidth() + .height(CalendarLoadingHeight) .wrapContentSize(Alignment.Center), ) } else { @@ -224,6 +226,7 @@ fun SimTongCalendar( list = calendarList, onItemClicked = onItemClicked ) + Spacer(modifier = Modifier.height(40.dp)) } } } @@ -327,9 +330,7 @@ fun SimTongCalendarList( list: List, onItemClicked: (Int, String) -> Unit = { _, _ -> }, ) { - Column( - modifier = Modifier.fillMaxSize() - ) { + Column { repeat(list.size / Week) { size -> val rowList = list.subList(size * Week, size * Week + Week) diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/mvi/CloseDayContract.kt b/feature/feature-home/src/main/java/com/comit/feature_home/mvi/CloseDayContract.kt index eda6fbf4..87feae15 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/mvi/CloseDayContract.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/mvi/CloseDayContract.kt @@ -15,9 +15,15 @@ sealed class CloseDaySideEffect { object TokenException : CloseDaySideEffect() - object DayOffExcess : CloseDaySideEffect() + object AlreadyHoliday : CloseDaySideEffect() - object AnnualDayChangeFail : CloseDaySideEffect() + object TooManyHoliday : CloseDaySideEffect() + + object TooManyAnnualDay : CloseDaySideEffect() + + object AlreadyAnnualDay : CloseDaySideEffect() object AlreadyWork : CloseDaySideEffect() + + object CannotChangeWorkState : CloseDaySideEffect() } diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/mvi/FetchScheduleContract.kt b/feature/feature-home/src/main/java/com/comit/feature_home/mvi/FetchScheduleContract.kt index 32cd2526..7d7a18c8 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/mvi/FetchScheduleContract.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/mvi/FetchScheduleContract.kt @@ -28,9 +28,11 @@ fun ScheduleList.Schedule.toStateSchedule() = FetchScheduleState.Schedule( sealed class FetchScheduleSideEffect { - object FetchScheduleFail : FetchScheduleSideEffect() + object DeleteScheduleDateError : FetchScheduleSideEffect() + + object DeleteScheduleCannotFound : FetchScheduleSideEffect() object DeleteScheduleSuccess : FetchScheduleSideEffect() - object DeleteScheduleFail : FetchScheduleSideEffect() + object TokenError : FetchScheduleSideEffect() } diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/navigation/HomeNavigation.kt b/feature/feature-home/src/main/java/com/comit/feature_home/navigation/HomeNavigation.kt index 35b42aa9..f69de2bb 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/navigation/HomeNavigation.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/navigation/HomeNavigation.kt @@ -10,10 +10,10 @@ import androidx.navigation.navArgument import androidx.navigation.navigation import com.comit.feature_home.screen.HomeScreen import com.comit.feature_home.screen.SalaryWebViewScreen +import com.comit.feature_home.screen.WriteClosedDayScreen import com.comit.feature_home.screen.alarm.AlarmScreen import com.comit.feature_home.screen.schedule.ShowScheduleScreen import com.comit.feature_home.screen.schedule.WriteScheduleScreen -import com.comit.feature_home.vm.WriteClosedDayScreen import com.comit.navigator.SimTongScreen fun NavGraphBuilder.homeNavigation( diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/screen/HomeScreen.kt b/feature/feature-home/src/main/java/com/comit/feature_home/screen/HomeScreen.kt index 43dc7249..1ba46137 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/screen/HomeScreen.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/screen/HomeScreen.kt @@ -1,4 +1,4 @@ -@file:OptIn(ExperimentalMaterialApi::class, InternalCoroutinesApi::class,) +@file:OptIn(ExperimentalMaterialApi::class, InternalCoroutinesApi::class) package com.comit.feature_home.screen @@ -28,6 +28,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -35,6 +36,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import com.comit.common.rememberToast +import com.comit.common.utils.string import com.comit.core.observeWithLifecycle import com.comit.core_design_system.color.SimTongColor import com.comit.core_design_system.component.Header @@ -57,8 +59,6 @@ private val HomeScreenPadding = PaddingValues( horizontal = 25.dp, ) -private val HomeCalendarHeight: Dp = 343.dp - private const val StartDateAdd = -3 private const val EndDateAdd = 3 @@ -84,23 +84,35 @@ fun HomeScreen( today.get(Calendar.MONTH), today.get(Calendar.DATE) + StartDateAdd ) - val startYear = startAt.get(Calendar.YEAR).toString() - val startMonth = (startAt.get(Calendar.MONTH) + 1).toString() - val startDay = startAt.get(Calendar.DATE).toString() + val startYear = startAt.get(Calendar.YEAR) + val startMonth = (startAt.get(Calendar.MONTH) + 1) + val startDay = startAt.get(Calendar.DATE) val endAt = GregorianCalendar( today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DATE) + EndDateAdd ) - val endYear = endAt.get(Calendar.YEAR).toString() - val endMonth = (endAt.get(Calendar.MONTH) + 1).toString() - val endDay = endAt.get(Calendar.DATE).toString() + val endYear = endAt.get(Calendar.YEAR) + val endMonth = (endAt.get(Calendar.MONTH) + 1) + val endDay = endAt.get(Calendar.DATE) LaunchedEffect(key1 = homeViewModel) { homeViewModel.fetchMenu( - startAt = "$startYear-$startMonth-$startDay", - endAt = "$endYear-$endMonth-$endDay", + startAt = buildAnnotatedString { + append(startYear.toString()) + append("-") + append(string.format("%02d", startMonth)) + append("-") + append(string.format("%02d", startDay)) + }.toString(), + endAt = buildAnnotatedString { + append(endYear.toString()) + append("-") + append(string.format("%02d", endMonth)) + append("-") + append(string.format("%02d", endDay)) + }.toString() ) } @@ -163,7 +175,6 @@ fun HomeScreen( SimTongCalendar( modifier = Modifier .fillMaxWidth() - .height(HomeCalendarHeight) .simClickable( rippleEnabled = false, ) { diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/vm/WriteClosedDayScreen.kt b/feature/feature-home/src/main/java/com/comit/feature_home/screen/WriteClosedDayScreen.kt similarity index 92% rename from feature/feature-home/src/main/java/com/comit/feature_home/vm/WriteClosedDayScreen.kt rename to feature/feature-home/src/main/java/com/comit/feature_home/screen/WriteClosedDayScreen.kt index eb435904..3337c447 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/vm/WriteClosedDayScreen.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/screen/WriteClosedDayScreen.kt @@ -4,7 +4,7 @@ ) @file:Suppress("OPT_IN_IS_NOT_ENABLED") -package com.comit.feature_home.vm +package com.comit.feature_home.screen import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -62,6 +62,7 @@ import com.comit.feature_home.calendar.SimTongCalendar import com.comit.feature_home.calendar.SimTongCalendarStatus import com.comit.feature_home.mvi.CloseDaySideEffect import com.comit.feature_home.string +import com.comit.feature_home.vm.CloseDayViewModel import com.example.feature_home.R import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.launch @@ -78,8 +79,12 @@ private val CalendarPadding = PaddingValues( private const val DateInputWrongMessage = "잘못된 날짜 입력입니다" private const val TokenExceptionMessage = "토큰 만료. 다시 로그인해주세요" -private const val DayOffExcessMessage = "일주일에 휴무일은 최대 2회입니다" +private const val AlreadyHoliday = "이미 휴무일입니다" +private const val TooManyHoliday = "휴무일은 일주일에 2번만 가능합니다" +private const val AlreadyAnnualDay = "이미 연차입니다" +private const val TooManyAnnualDay = "연차 개수가 부족합니다" private const val AlreadyWorkMessage = "이미 근무일입니다" +private const val CannotChangeWorkState = "더 이상 변경할 수 없는 일정입니다" @Composable fun WriteClosedDayScreen( @@ -122,15 +127,24 @@ fun WriteClosedDayScreen( CloseDaySideEffect.TokenException -> { toast(message = TokenExceptionMessage) } - CloseDaySideEffect.DayOffExcess -> { - toast(message = DayOffExcessMessage) + CloseDaySideEffect.AlreadyHoliday -> { + toast(message = AlreadyHoliday) } - CloseDaySideEffect.AnnualDayChangeFail -> { - toast(message = "서비스 준비중입니다") + CloseDaySideEffect.TooManyHoliday -> { + toast(message = TooManyHoliday) + } + CloseDaySideEffect.AlreadyAnnualDay -> { + toast(message = AlreadyAnnualDay) + } + CloseDaySideEffect.TooManyAnnualDay -> { + toast(message = TooManyAnnualDay) } CloseDaySideEffect.AlreadyWork -> { toast(message = AlreadyWorkMessage) } + CloseDaySideEffect.CannotChangeWorkState -> { + toast(message = CannotChangeWorkState) + } } } diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/screen/schedule/ShowScheduleScreen.kt b/feature/feature-home/src/main/java/com/comit/feature_home/screen/schedule/ShowScheduleScreen.kt index 75a3fc82..8b2a49fb 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/screen/schedule/ShowScheduleScreen.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/screen/schedule/ShowScheduleScreen.kt @@ -36,7 +36,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController @@ -69,16 +68,12 @@ import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.launch import java.time.LocalDate import java.time.format.DateTimeFormatter -import java.util.Calendar -import java.util.GregorianCalendar import java.util.UUID private val HorizontalPadding = PaddingValues( horizontal = 30.dp, ) -private val HomeCalendarHeight: Dp = 343.dp - private val CalendarPadding = PaddingValues( horizontal = 20.dp, ) @@ -95,25 +90,8 @@ fun ShowScheduleScreen( val showScheduleState = showScheduleContainer.stateFlow.collectAsState().value val showScheduleSideEffect = showScheduleContainer.sideEffectFlow - val today = GregorianCalendar() - val calendar = GregorianCalendar( - today.get(Calendar.YEAR), - today.get(Calendar.MONTH), - today.get(Calendar.DATE) - ) var checkMonth by remember { mutableStateOf(0) } -// var date by remember { -// mutableStateOf( -// Date.valueOf( -// string.format("%02d", calendar.get(Calendar.YEAR)) + -// "-" + -// string.format("%02d", calendar.get(Calendar.MONTH) + 1) + -// "-01" -// ) -// ) -// } - LaunchedEffect(showScheduleViewModel) { showScheduleViewModel.showSchedule( startAt = getStartAt(checkMonth), @@ -133,9 +111,6 @@ fun ShowScheduleScreen( showScheduleSideEffect.observeWithLifecycle() { when (it) { - FetchScheduleSideEffect.FetchScheduleFail -> { - toast(message = "일정을 불러오는데 실패했습니다.") - } FetchScheduleSideEffect.DeleteScheduleSuccess -> { coroutineScope.launch { bottomSheetState.hide() @@ -145,8 +120,14 @@ fun ShowScheduleScreen( endAt = getEndAt(checkMonth) ) } - FetchScheduleSideEffect.DeleteScheduleFail -> { - toast(message = "일정 삭제를 실패했습니다.") + FetchScheduleSideEffect.DeleteScheduleDateError -> { + toast(message = "삭제할 일정을 찾지 못했습니다") + } + FetchScheduleSideEffect.DeleteScheduleCannotFound -> { + toast(message = "일정이 존재하지 않습니다") + } + FetchScheduleSideEffect.TokenError -> { + toast(message = "토큰 만료. 다시 로그인해주세요") } } } @@ -259,6 +240,9 @@ fun ShowScheduleScreen( Spacer(modifier = Modifier.height(20.dp)) SimTongCalendar( + modifier = Modifier + .fillMaxWidth() + .padding(CalendarPadding), onBeforeClicked = { _, _checkMonth -> checkMonth = _checkMonth showScheduleViewModel.showSchedule( @@ -273,10 +257,6 @@ fun ShowScheduleScreen( endAt = getEndAt(checkMonth) ) }, - modifier = Modifier - .fillMaxWidth() - .height(HomeCalendarHeight) - .padding(CalendarPadding), ) Spacer(modifier = Modifier.height(7.dp)) diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/vm/CloseDayViewModel.kt b/feature/feature-home/src/main/java/com/comit/feature_home/vm/CloseDayViewModel.kt index ef0765ce..20307b5b 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/vm/CloseDayViewModel.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/vm/CloseDayViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.comit.domain.exception.BadRequestException import com.comit.domain.exception.ConflictException import com.comit.domain.exception.NotFoundException +import com.comit.domain.exception.TooManyRequestsException import com.comit.domain.exception.UnAuthorizedException import com.comit.domain.exception.throwUnknownException import com.comit.domain.usecase.holiday.CheckLeftHolidayUseCase @@ -43,7 +44,8 @@ class CloseDayViewModel @Inject constructor( when (it) { is BadRequestException -> postSideEffect(CloseDaySideEffect.DateInputWrong) is UnAuthorizedException -> postSideEffect(CloseDaySideEffect.TokenException) - is ConflictException -> postSideEffect(CloseDaySideEffect.DayOffExcess) + is ConflictException -> postSideEffect(CloseDaySideEffect.AlreadyHoliday) + is TooManyRequestsException -> postSideEffect(CloseDaySideEffect.TooManyHoliday) else -> throwUnknownException(it) } } @@ -57,7 +59,13 @@ class CloseDayViewModel @Inject constructor( ).onSuccess { postSideEffect(CloseDaySideEffect.CloseDayChangeSuccess) }.onFailure { - postSideEffect(CloseDaySideEffect.AnnualDayChangeFail) + when (it) { + is BadRequestException -> postSideEffect(CloseDaySideEffect.DateInputWrong) + is UnAuthorizedException -> postSideEffect(CloseDaySideEffect.TokenException) + is ConflictException -> postSideEffect(CloseDaySideEffect.AlreadyAnnualDay) + is TooManyRequestsException -> postSideEffect(CloseDaySideEffect.TooManyAnnualDay) + else -> throwUnknownException(it) + } } } } @@ -73,6 +81,7 @@ class CloseDayViewModel @Inject constructor( is BadRequestException -> postSideEffect(CloseDaySideEffect.DateInputWrong) is UnAuthorizedException -> postSideEffect(CloseDaySideEffect.TokenException) is NotFoundException -> postSideEffect(CloseDaySideEffect.AlreadyWork) + is ConflictException -> postSideEffect(CloseDaySideEffect.CannotChangeWorkState) else -> throwUnknownException(it) } } @@ -87,6 +96,11 @@ class CloseDayViewModel @Inject constructor( reduce { state.copy(leftHoliday = it.result) } + }.onFailure { + when (it) { + is UnAuthorizedException -> postSideEffect(CloseDaySideEffect.TokenException) + else -> throwUnknownException(it) + } } } } diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetHolidayViewModel.kt b/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetHolidayViewModel.kt index caefaa4e..f78c4332 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetHolidayViewModel.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetHolidayViewModel.kt @@ -4,6 +4,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.comit.domain.exception.BadRequestException +import com.comit.domain.exception.UnAuthorizedException +import com.comit.domain.exception.throwUnknownException import com.comit.domain.usecase.holiday.FetchHolidaysUseCase import com.comit.feature_home.mvi.FetchHolidayState import com.comit.feature_home.mvi.toState @@ -32,7 +35,11 @@ class GetHolidayViewModel @Inject constructor( ).onSuccess { _holidayList.value = it.toState().holidayList }.onFailure { - _holidayList.value = listOf() + when (it) { + is BadRequestException -> _holidayList.value = listOf() + is UnAuthorizedException -> _holidayList.value = listOf() + else -> throwUnknownException(it) + } } } } diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetWorkCountViewModel.kt b/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetWorkCountViewModel.kt index 77f485b8..eb1aef87 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetWorkCountViewModel.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/vm/GetWorkCountViewModel.kt @@ -4,6 +4,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.comit.domain.exception.BadRequestException +import com.comit.domain.exception.UnAuthorizedException +import com.comit.domain.exception.throwUnknownException import com.comit.domain.usecase.schedule.FetchPersonalScheduleUseCase import com.comit.feature_home.mvi.FetchScheduleState import com.comit.feature_home.mvi.toState @@ -30,7 +33,11 @@ class GetWorkCountViewModel @Inject constructor( ).onSuccess { _workCountList.value = it.toState().scheduleList }.onFailure { - _workCountList.value = listOf() + when (it) { + is BadRequestException -> _workCountList.value = listOf() + is UnAuthorizedException -> _workCountList.value = listOf() + else -> throwUnknownException(it) + } } } } diff --git a/feature/feature-home/src/main/java/com/comit/feature_home/vm/ShowScheduleViewModel.kt b/feature/feature-home/src/main/java/com/comit/feature_home/vm/ShowScheduleViewModel.kt index acca6c7b..321b01f9 100644 --- a/feature/feature-home/src/main/java/com/comit/feature_home/vm/ShowScheduleViewModel.kt +++ b/feature/feature-home/src/main/java/com/comit/feature_home/vm/ShowScheduleViewModel.kt @@ -2,6 +2,10 @@ package com.comit.feature_home.vm import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.comit.domain.exception.BadRequestException +import com.comit.domain.exception.NotFoundException +import com.comit.domain.exception.UnAuthorizedException +import com.comit.domain.exception.throwUnknownException import com.comit.domain.usecase.schedule.DeletePersonalScheduleUseCase import com.comit.domain.usecase.schedule.FetchPersonalScheduleUseCase import com.comit.feature_home.mvi.FetchScheduleSideEffect @@ -25,7 +29,6 @@ class ShowScheduleViewModel @Inject constructor( override val container = container(FetchScheduleState()) - // TODO(limsaehyun): 예상치 못한 예외 시 throwUnknownException 반환 필요 fun showSchedule( startAt: String, endAt: String, @@ -41,12 +44,14 @@ class ShowScheduleViewModel @Inject constructor( ) } }.onFailure { - postSideEffect(FetchScheduleSideEffect.FetchScheduleFail) + when (it) { + is UnAuthorizedException -> postSideEffect(FetchScheduleSideEffect.TokenError) + else -> throwUnknownException(it) + } } } } - // TODO(limsaehyun): 예상치 못한 예외 시 throwUnknownException 반환 필요 fun deleteSchedule( id: UUID ) = intent { @@ -56,7 +61,12 @@ class ShowScheduleViewModel @Inject constructor( ).onSuccess { postSideEffect(FetchScheduleSideEffect.DeleteScheduleSuccess) }.onFailure { - postSideEffect(FetchScheduleSideEffect.DeleteScheduleFail) + when (it) { + is BadRequestException -> postSideEffect(FetchScheduleSideEffect.DeleteScheduleDateError) + is UnAuthorizedException -> postSideEffect(FetchScheduleSideEffect.TokenError) + is NotFoundException -> postSideEffect(FetchScheduleSideEffect.DeleteScheduleCannotFound) + else -> throwUnknownException(it) + } } } }