Coverage Summary for Class: GetTransactionsByCategoryUseCase (com.georgeci.moneysurfer.domain.usecase)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| GetTransactionsByCategoryUseCase |
100%
(4/4)
|
50%
(1/2)
|
100%
(11/11)
|
100%
(19/19)
|
| GetTransactionsByCategoryUseCase$Companion |
|
| GetTransactionsByCategoryUseCase$invoke$1$1 |
100%
(1/1)
|
|
100%
(5/5)
|
100%
(23/23)
|
| GetTransactionsByCategoryUseCase$invoke$1$1$1 |
100%
(1/1)
|
50%
(1/2)
|
100%
(1/1)
|
84.6%
(11/13)
|
| GetTransactionsByCategoryUseCase$invoke-ayLZWDE$$inlined$flatMapLatest$1 |
0%
(0/1)
|
|
| Total |
85.7%
(6/7)
|
50%
(2/4)
|
100%
(17/17)
|
96.4%
(53/55)
|
package com.georgeci.moneysurfer.domain.usecase
import com.georgeci.moneysurfer.domain.auth.SessionPointers
import com.georgeci.moneysurfer.domain.model.CategoryTree
import com.georgeci.moneysurfer.domain.model.Transaction
import com.georgeci.moneysurfer.domain.primitives.CategoryId
import com.georgeci.moneysurfer.domain.repositories.CategoryRepository
import com.georgeci.moneysurfer.domain.repositories.TransactionRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import org.koin.core.annotation.Single
/**
* Newest-first transactions booked to [categoryId] **or anything below it**, capped at [limit].
*
* Including the subtree matches how the rest of the app treats a parent: the detail screen's
* headline number already rolls children up, so a recent list that showed only the parent's own
* transactions would contradict the total sitting directly above it.
*
* Filtering happens in memory over the workspace list rather than in SQL. That list is already
* indexed and sorted for exactly this ordering, and it is the same read the dashboard and the
* transactions list make — so this shares their cached flow instead of adding a third query
* shape over the same table.
*/
@Single
@OptIn(ExperimentalCoroutinesApi::class)
class GetTransactionsByCategoryUseCase(
private val transactionRepository: TransactionRepository,
private val categoryRepository: CategoryRepository,
private val session: SessionPointers,
) {
operator fun invoke(
categoryId: CategoryId,
limit: Int = DEFAULT_LIMIT,
): Flow<List<Transaction>> =
session.currentWorkspaceId.flatMapLatest { workspaceId ->
workspaceId ?: return@flatMapLatest flowOf(emptyList())
combine(
transactionRepository.getByWorkspaceId(workspaceId),
categoryRepository.getByWorkspaceId(workspaceId),
) { transactions, categories ->
val subtree = CategoryTree.descendantsOf(categories, categoryId) + categoryId
transactions.asSequence()
.filter { it.categoryId in subtree }
.take(limit)
.toList()
}
}
companion object {
/** Enough to fill the detail screen's "Recent" block without becoming a second list screen. */
const val DEFAULT_LIMIT = 10
}
}