Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Commit

Permalink
Data layer bugfixes (#3111)
Browse files Browse the repository at this point in the history
* WIP: Property-based testing utils

* WIP: Property-based Arb setup

* Add support for arb income

* Add args for transaction

* WIP: Fix the `TransactionMapper`

* WIP: Add property-based tests

* WIP: Fix the transaction repository

* Refactor

* WIP: Fix tests

* Fix the `TransactionMapper` test

* Improve the `TransactionMapper` test

* WIP: Improve the transaction mapper tests

* Add property-based tests for the transaction mapper

* Refactor the transaction mapper

* Refactor to `TransactionMapper`

* Fix Detekt errors

* WIP: TransactionRepositoryImpl test

* WIP: TransactionRepositoryImplTest

* Speed-up tests

* WIP: Fix build errors

* Fix build errors

* Delete unnecessary method

* Remove unnecessary method

* Refactor the TransactionRepository

* Add tests for the transactions repository

* Add tests for the save methods

* Cover the TransactionRepository with tests (one failing)

* Fix failing test

* Fix Detekt

* Increase tests heap size

* Add tests and fix bug in the transaction mapper

* WIP: Fix transaction mapper entity<->domain isomorphism

* Fix the TransactionMapperPropertyTest

* Fix Detekt

* Attempt to fix GitHub Actions #1

* Revert useless fix

* Fix flaky tests

* Fix Detekt
  • Loading branch information
ILIYANGERMANOV authored Apr 9, 2024
1 parent ce0da86 commit f1225b9
Show file tree
Hide file tree
Showing 62 changed files with 2,233 additions and 1,265 deletions.
7 changes: 7 additions & 0 deletions buildSrc/src/main/kotlin/ivy.kotlin-android.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ android {
}
}

gradle.projectsEvaluated {
// Increase tests Heap Size because of Kotest property-based tests
tasks.withType<Test> {
maxHeapSize = "2048m"
}
}

dependencies {
implementation(libs.bundles.arrow)
implementation(libs.bundles.kotlin)
Expand Down
6 changes: 3 additions & 3 deletions screen/home/src/main/java/com/ivy/home/HomeViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import com.ivy.legacy.data.model.TimePeriod
import com.ivy.legacy.data.model.toCloseTimeRange
import com.ivy.legacy.datamodel.Account
import com.ivy.legacy.datamodel.Settings
import com.ivy.legacy.datamodel.temp.toDomain
import com.ivy.legacy.datamodel.temp.toLegacyDomain
import com.ivy.legacy.domain.action.settings.UpdateSettingsAct
import com.ivy.legacy.domain.action.viewmodel.home.ShouldHideIncomeAct
import com.ivy.legacy.utils.dateNowUTC
Expand Down Expand Up @@ -358,7 +358,7 @@ class HomeViewModel @Inject constructor(
upcoming.value = LegacyDueSection(
trns = with(transactionMapper) {
result.upcomingTrns.map {
it.toEntity().toDomain()
it.toEntity().toLegacyDomain()
}.toImmutableList()
},
stats = result.upcoming,
Expand All @@ -370,7 +370,7 @@ class HomeViewModel @Inject constructor(
overdue.value = LegacyDueSection(
trns = with(transactionMapper) {
result.overdueTrns.map {
it.toEntity().toDomain()
it.toEntity().toLegacyDomain()
}.toImmutableList()
},
stats = result.overdue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.ivy.importdata.csv.ImportantFields
import com.ivy.importdata.csv.OptionalFields
import com.ivy.importdata.csv.TransferFields
import com.ivy.legacy.datamodel.Account
import com.ivy.legacy.datamodel.temp.toDomain
import com.ivy.legacy.datamodel.temp.toLegacyDomain
import com.ivy.legacy.datamodel.toEntity
import com.ivy.legacy.utils.toLowerCaseLocal
import com.ivy.wallet.domain.data.IvyCurrency
Expand Down Expand Up @@ -64,7 +64,7 @@ class CSVImporterV2 @Inject constructor(
newCategoryColorIndex = 0
newAccountColorIndex = 0

accounts = accountDao.findAll().map { it.toDomain() }
accounts = accountDao.findAll().map { it.toLegacyDomain() }
val initialAccountsCount = accounts.size

categories = categoryRepository.findAll()
Expand Down Expand Up @@ -280,7 +280,7 @@ class CSVImporterV2 @Inject constructor(
val domainAccount = newAccount.toDomainAccount(currencyRepository).getOrNull()
?: return null
accountRepository.save(domainAccount)
accounts = accountDao.findAll().map { it.toDomain() }
accounts = accountDao.findAll().map { it.toLegacyDomain() }

return newAccount
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.ivy.frp.test.TestIdlingResource
import com.ivy.legacy.datamodel.Account
import com.ivy.legacy.datamodel.Loan
import com.ivy.legacy.datamodel.LoanRecord
import com.ivy.legacy.datamodel.temp.toDomain
import com.ivy.legacy.datamodel.temp.toLegacyDomain
import com.ivy.legacy.domain.deprecated.logic.AccountCreator
import com.ivy.legacy.utils.computationThread
import com.ivy.legacy.utils.ioThread
Expand Down Expand Up @@ -258,7 +258,7 @@ class LoanDetailsViewModel @Inject constructor(
)

DisplayLoanRecord(
it.toDomain(),
it.toLegacyDomain(),
account = account,
loanRecordTransaction = trans != null,
loanRecordCurrencyCode = account?.currency ?: defaultCurrencyCode,
Expand Down Expand Up @@ -307,7 +307,7 @@ class LoanDetailsViewModel @Inject constructor(
}

associatedTransaction = ioThread {
transactionDao.findLoanTransaction(loanId = loan.value!!.id)?.toDomain()
transactionDao.findLoanTransaction(loanId = loan.value!!.id)?.toLegacyDomain()
}

associatedTransaction?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import com.ivy.data.model.IntervalType
import com.ivy.data.repository.CategoryRepository
import com.ivy.legacy.datamodel.Account
import com.ivy.legacy.datamodel.PlannedPaymentRule
import com.ivy.legacy.datamodel.temp.toDomain
import com.ivy.legacy.datamodel.temp.toLegacyDomain
import com.ivy.legacy.domain.deprecated.logic.AccountCreator
import com.ivy.legacy.utils.ioThread
import com.ivy.navigation.EditPlannedScreen
Expand Down Expand Up @@ -275,7 +275,7 @@ class EditPlannedViewModel @Inject constructor(
reset()

loadedRule = screen.plannedPaymentRuleId?.let {
ioThread { plannedPaymentRuleDao.findById(it)!!.toDomain() }
ioThread { plannedPaymentRuleDao.findById(it)!!.toLegacyDomain() }
} ?: PlannedPaymentRule(
startDate = null,
intervalN = null,
Expand Down Expand Up @@ -303,7 +303,7 @@ class EditPlannedViewModel @Inject constructor(
intervalType.value = rule.intervalType
initialTitle.value = rule.title
description.value = rule.description
val selectedAccount = ioThread { accountDao.findById(rule.accountId)!!.toDomain() }
val selectedAccount = ioThread { accountDao.findById(rule.accountId)!!.toLegacyDomain() }
account.value = selectedAccount
category.value = rule.categoryId?.let {
ioThread { categoryRepository.findById(CategoryId(it)) }
Expand Down
20 changes: 4 additions & 16 deletions screen/reports/src/main/java/com/ivy/reports/ReportScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,17 @@ import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel
import com.ivy.base.legacy.stringRes
import com.ivy.base.model.TransactionType
import com.ivy.ui.rememberScrollPositionListState
import com.ivy.data.model.Category
import com.ivy.data.model.CategoryId
import com.ivy.data.model.primitive.ColorInt
import com.ivy.data.model.primitive.IconAsset
import com.ivy.data.model.primitive.NotBlankTrimmedString
import com.ivy.data.repository.mapper.TransactionMapper
import com.ivy.design.l0_system.UI
import com.ivy.design.l0_system.style
import com.ivy.legacy.IvyWalletPreview
import com.ivy.legacy.data.AppBaseData
import com.ivy.legacy.data.LegacyDueSection
import com.ivy.legacy.datamodel.Account
import com.ivy.legacy.datamodel.temp.toDomain
import com.ivy.legacy.ui.component.IncomeExpensesCards
import com.ivy.legacy.ui.component.transaction.TransactionsDividerLine
import com.ivy.legacy.ui.component.transaction.transactions
Expand All @@ -51,6 +48,7 @@ import com.ivy.navigation.PieChartStatisticScreen
import com.ivy.navigation.ReportScreen
import com.ivy.navigation.navigation
import com.ivy.ui.R
import com.ivy.ui.rememberScrollPositionListState
import com.ivy.wallet.domain.pure.data.IncomeExpensePair
import com.ivy.wallet.ui.theme.Gray
import com.ivy.wallet.ui.theme.Green
Expand Down Expand Up @@ -94,9 +92,7 @@ private fun BoxWithConstraintsScope.UI(
state: ReportScreenState = ReportScreenState(),
onEventHandler: (ReportScreenEvent) -> Unit = {}
) {
val transactionMapper = TransactionMapper()
val legacyTransactions =
with(transactionMapper) { state.transactions.map { it.toEntity().toDomain() } }
val legacyTransactions = state.transactions
val nav = navigation()
val context = LocalContext.current

Expand Down Expand Up @@ -237,11 +233,7 @@ private fun BoxWithConstraintsScope.UI(
),

upcoming = LegacyDueSection(
trns = with(transactionMapper) {
state.upcomingTransactions.map {
it.toEntity().toDomain()
}.toImmutableList()
},
trns = state.upcomingTransactions,
stats = IncomeExpensePair(
income = state.upcomingIncome.toBigDecimal(),
expense = state.upcomingExpenses.toBigDecimal()
Expand All @@ -254,11 +246,7 @@ private fun BoxWithConstraintsScope.UI(
},

overdue = LegacyDueSection(
trns = with(transactionMapper) {
state.overdueTransactions.map {
it.toEntity().toDomain()
}.toImmutableList()
},
trns = state.overdueTransactions,
stats = IncomeExpensePair(
income = state.overdueIncome.toBigDecimal(),
expense = state.overdueExpenses.toBigDecimal()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ data class ReportScreenState(
val overdueIncome: Double = 0.0,
val overdueExpenses: Double = 0.0,
val history: ImmutableList<TransactionHistoryItem> = persistentListOf(),
val upcomingTransactions: ImmutableList<Transaction> = persistentListOf(),
val overdueTransactions: ImmutableList<Transaction> = persistentListOf(),
val upcomingTransactions: ImmutableList<com.ivy.base.legacy.Transaction> = persistentListOf(),
val overdueTransactions: ImmutableList<com.ivy.base.legacy.Transaction> = persistentListOf(),
val categories: ImmutableList<Category> = persistentListOf(),
val accounts: ImmutableList<Account> = persistentListOf(),
val upcomingExpanded: Boolean = false,
val overdueExpanded: Boolean = false,
val filter: ReportFilter? = null,
val loading: Boolean = false,
val accountIdFilters: ImmutableList<UUID> = persistentListOf(),
val transactions: ImmutableList<Transaction> = persistentListOf(),
val transactions: ImmutableList<com.ivy.base.legacy.Transaction> = persistentListOf(),
val filterOverlayVisible: Boolean = false,
val showTransfersAsIncExpCheckbox: Boolean = false,
val treatTransfersAsIncExp: Boolean = false,
Expand Down
23 changes: 16 additions & 7 deletions screen/reports/src/main/java/com/ivy/reports/ReportViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.compose.runtime.mutableDoubleStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.toArgb
import androidx.lifecycle.viewModelScope
import com.ivy.ui.ComposeViewModel
import com.ivy.base.legacy.LegacyTransaction
import com.ivy.base.legacy.TransactionHistoryItem
import com.ivy.base.legacy.stringRes
import com.ivy.base.model.TransactionType
Expand All @@ -33,11 +33,13 @@ import com.ivy.domain.usecase.csv.ExportCsvUseCase
import com.ivy.frp.filterSuspend
import com.ivy.legacy.IvyWalletCtx
import com.ivy.legacy.datamodel.Account
import com.ivy.legacy.datamodel.temp.toLegacy
import com.ivy.legacy.utils.getISOFormattedDateTime
import com.ivy.legacy.utils.scopedIOThread
import com.ivy.legacy.utils.timeNowUTC
import com.ivy.legacy.utils.toLowerCaseLocal
import com.ivy.legacy.utils.uiThread
import com.ivy.ui.ComposeViewModel
import com.ivy.ui.R
import com.ivy.wallet.domain.action.account.AccountsAct
import com.ivy.wallet.domain.action.exchange.ExchangeAct
Expand Down Expand Up @@ -106,14 +108,15 @@ class ReportViewModel @Inject constructor(
private val overdueExpenses = mutableDoubleStateOf(0.0)
private val history = mutableStateOf<ImmutableList<TransactionHistoryItem>>(persistentListOf())
private val upcomingTransactions =
mutableStateOf<ImmutableList<Transaction>>(persistentListOf())
private val overdueTransactions = mutableStateOf<ImmutableList<Transaction>>(persistentListOf())
mutableStateOf<ImmutableList<LegacyTransaction>>(persistentListOf())
private val overdueTransactions =
mutableStateOf<ImmutableList<LegacyTransaction>>(persistentListOf())
private val accounts = mutableStateOf<ImmutableList<Account>>(persistentListOf())
private val upcomingExpanded = mutableStateOf(false)
private val overdueExpanded = mutableStateOf(false)
private val loading = mutableStateOf(false)
private val accountIdFilters = mutableStateOf<ImmutableList<UUID>>(persistentListOf())
private val transactions = mutableStateOf<ImmutableList<Transaction>>(persistentListOf())
private val transactions = mutableStateOf<ImmutableList<LegacyTransaction>>(persistentListOf())
private val filterOverlayVisible = mutableStateOf(false)
private val showTransfersAsIncExpCheckbox = mutableStateOf(false)
private val treatTransfersAsIncExp = mutableStateOf(false)
Expand Down Expand Up @@ -297,13 +300,19 @@ class ReportViewModel @Inject constructor(
overdueIncome.doubleValue = overdueIncomeExpense.income.toDouble()
overdueExpenses.doubleValue = overdueIncomeExpense.expense.toDouble()
history.value = historyWithDateDividers.await().toImmutableList()
upcomingTransactions.value = upcomingTransactionsList
overdueTransactions.value = overdue
upcomingTransactions.value = upcomingTransactionsList.map {
it.toLegacy(transactionMapper)
}.toImmutableList()
overdueTransactions.value = overdue.map {
it.toLegacy(transactionMapper)
}.toImmutableList()
accounts.value = tempAccounts.toImmutableList()
filter.value = reportFilter
loading.value = false
accountIdFilters.value = accountFilterIdList.await().toImmutableList()
transactions.value = transactionsList
transactions.value = transactionsList.map {
it.toLegacy(transactionMapper)
}.toImmutableList()
balance.doubleValue = tempBalance
filterOverlayVisible.value = false
showTransfersAsIncExpCheckbox.value =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import com.ivy.frp.then
import com.ivy.legacy.IvyWalletCtx
import com.ivy.legacy.data.model.TimePeriod
import com.ivy.legacy.data.model.toCloseTimeRange
import com.ivy.legacy.datamodel.temp.toDomain
import com.ivy.legacy.datamodel.temp.toImmutableLegacyTags
import com.ivy.legacy.datamodel.temp.toLegacyDomain
import com.ivy.legacy.domain.deprecated.logic.AccountCreator
import com.ivy.legacy.utils.computationThread
import com.ivy.legacy.utils.dateNowUTC
Expand Down Expand Up @@ -327,7 +327,7 @@ class TransactionsViewModel @Inject constructor(

private suspend fun initForAccount(accountId: UUID) {
val initialAccount = ioThread {
accountDao.findById(accountId)?.toDomain() ?: error("account not found")
accountDao.findById(accountId)?.toLegacyDomain() ?: error("account not found")
}
account.value = initialAccount
val range = period.value.toRange(ivyContext.startDayOfMonth)
Expand Down Expand Up @@ -378,7 +378,7 @@ class TransactionsViewModel @Inject constructor(
it.map {
val tags =
tagsRepository.findByIds(it.tags).toImmutableLegacyTags()
it.toEntity().toDomain(tags = tags)
it.toEntity().toLegacyDomain(tags = tags)
}
}
)
Expand All @@ -402,7 +402,7 @@ class TransactionsViewModel @Inject constructor(

upcoming.value = ioThread {
with(transactionMapper) {
accountLogic.upcoming(initialAccount, range).map { it.toEntity().toDomain() }
accountLogic.upcoming(initialAccount, range).map { it.toEntity().toLegacyDomain() }
}.toImmutableList()
}

Expand All @@ -418,9 +418,8 @@ class TransactionsViewModel @Inject constructor(
overdue.value = ioThread {
with(transactionMapper) {
accountLogic.overdue(initialAccount, range).map {
it.toEntity().toDomain()
}
.toImmutableList()
it.toEntity().toLegacyDomain()
}.toImmutableList()
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions shared/base/src/main/java/com/ivy/base/TimeProvider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ivy.base

import java.time.ZoneId
import javax.inject.Inject

@Suppress("UnnecessaryPassThroughClass")
class TimeProvider @Inject constructor() {
fun getZoneId(): ZoneId = ZoneId.systemDefault()
}
2 changes: 2 additions & 0 deletions shared/base/src/main/java/com/ivy/base/legacy/Transaction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import java.time.LocalDateTime
import java.time.LocalTime
import java.util.UUID

typealias LegacyTransaction = Transaction

@Deprecated("Legacy data model. Will be deleted")
@Immutable
data class Transaction(
Expand Down
1 change: 1 addition & 0 deletions shared/data/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ dependencies {
implementation(libs.datastore)
implementation(libs.bundles.ktor)

testImplementation(projects.shared.data.modelTesting)
androidTestImplementation(libs.bundles.integration.testing)
}
Loading

0 comments on commit f1225b9

Please sign in to comment.