Coverage Summary for Class: SetGoalStatusUseCase (com.georgeci.moneysurfer.domain.usecase)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| SetGoalStatusUseCase |
100%
(2/2)
|
87.5%
(7/8)
|
100%
(13/13)
|
98.9%
(184/186)
|
| SetGoalStatusUseCase$invoke$1 |
|
| Total |
100%
(2/2)
|
87.5%
(7/8)
|
100%
(13/13)
|
98.9%
(184/186)
|
package com.georgeci.moneysurfer.domain.usecase
import arrow.core.Either
import arrow.core.raise.either
import arrow.core.raise.ensure
import com.georgeci.moneysurfer.domain.model.GoalStatus
import com.georgeci.moneysurfer.domain.primitives.GoalId
import com.georgeci.moneysurfer.domain.repositories.GoalContributionRepository
import com.georgeci.moneysurfer.domain.repositories.SavingsGoalRepository
import org.koin.core.annotation.Single
/**
* Pause, resume and archive. COMPLETED is not settable — it is derived from progress,
* so resuming a goal that is already past its target lands on COMPLETED instead of
* ACTIVE.
*/
@Single
class SetGoalStatusUseCase(
private val goalRepository: SavingsGoalRepository,
private val contributionRepository: GoalContributionRepository,
) {
suspend operator fun invoke(
id: GoalId,
status: GoalStatus,
): Either<GoalActionError, GoalStatus> = either {
ensure(status != GoalStatus.COMPLETED) { GoalActionError.StatusNotSettable }
val goal = goalRepository.getById(id) ?: raise(GoalActionError.GoalNotFound)
val saved = contributionRepository.savedAmount(id)
val resolved = status.afterProgressChange(saved >= goal.target)
if (resolved == goal.status) return@either resolved
Either.catch { goalRepository.update(goal.copy(status = resolved)) }
.mapLeft { GoalActionError.LocalWriteFailed(it) }
.bind()
resolved
}
}