From 5a0ade46b2e1ea8e85d764bc563cd64c556d561f Mon Sep 17 00:00:00 2001 From: dankito Date: Mon, 23 Sep 2024 23:26:07 +0200 Subject: [PATCH] Implemented updating BankAccount properties --- .../banking/persistence/BankingRepository.kt | 2 + .../persistence/InMemoryBankingRepository.kt | 4 ++ .../persistence/SqliteBankingRepository.kt | 16 +++++++ .../net/codinux/banking/persistence/Bank.sq | 16 +++++++ .../banking/ui/composables/BanksList.kt | 2 +- .../ui/screens/BankAccountSettingsScreen.kt | 34 ++++++++++---- .../banking/ui/service/BankingService.kt | 45 ++++++++++++++++--- 7 files changed, 105 insertions(+), 14 deletions(-) diff --git a/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/BankingRepository.kt b/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/BankingRepository.kt index 9e0eb7a..45bebfd 100644 --- a/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/BankingRepository.kt +++ b/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/BankingRepository.kt @@ -28,6 +28,8 @@ interface BankingRepository { suspend fun updateBank(bank: BankAccessEntity, loginName: String, password: String, bankName: String?) + suspend fun updateAccount(bank: BankAccountEntity, userSetDisplayName: String?, hideAccount: Boolean, includeInAutomaticAccountsUpdate: Boolean) + suspend fun deleteBank(bank: BankAccessEntity) diff --git a/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/InMemoryBankingRepository.kt b/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/InMemoryBankingRepository.kt index 2de7e3a..22d5e4b 100644 --- a/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/InMemoryBankingRepository.kt +++ b/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/InMemoryBankingRepository.kt @@ -52,6 +52,10 @@ class InMemoryBankingRepository( // no-op } + override suspend fun updateAccount(bank: BankAccountEntity, userSetDisplayName: String?, hideAccount: Boolean, includeInAutomaticAccountsUpdate: Boolean) { + // no-op + } + override suspend fun deleteBank(bank: BankAccessEntity) { this.banks.remove(bank) } diff --git a/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/SqliteBankingRepository.kt b/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/SqliteBankingRepository.kt index 0e74660..bc28d85 100644 --- a/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/SqliteBankingRepository.kt +++ b/BankingPersistence/src/commonMain/kotlin/net/codinux/banking/persistence/SqliteBankingRepository.kt @@ -141,6 +141,22 @@ open class SqliteBankingRepository : BankingRepository { } } + override suspend fun updateAccount(bank: BankAccountEntity, userSetDisplayName: String?, hideAccount: Boolean, includeInAutomaticAccountsUpdate: Boolean) { + bankQueries.transaction { + if (bank.userSetDisplayName != userSetDisplayName) { + bankQueries.updateBankAccountUserSetDisplayName(userSetDisplayName, bank.id) + } + + if (bank.hideAccount != hideAccount) { + bankQueries.updateBankAccountHideAccount(hideAccount, bank.id) + } + + if (bank.includeInAutomaticAccountsUpdate != includeInAutomaticAccountsUpdate) { + bankQueries.updateBankAccountIncludeInAutomaticAccountsUpdate(includeInAutomaticAccountsUpdate, bank.id) + } + } + } + override suspend fun deleteBank(bank: BankAccessEntity) { bankQueries.transaction { accountTransactionQueries.deleteTransactionsByBankId(bankId = bank.id) diff --git a/BankingPersistence/src/commonMain/sqldelight/net/codinux/banking/persistence/Bank.sq b/BankingPersistence/src/commonMain/sqldelight/net/codinux/banking/persistence/Bank.sq index 200aebe..cd5978a 100644 --- a/BankingPersistence/src/commonMain/sqldelight/net/codinux/banking/persistence/Bank.sq +++ b/BankingPersistence/src/commonMain/sqldelight/net/codinux/banking/persistence/Bank.sq @@ -187,6 +187,22 @@ SELECT BankAccount.* FROM BankAccount; +updateBankAccountUserSetDisplayName: +UPDATE BankAccount +SET userSetDisplayName = ? +WHERE id = ?; + +updateBankAccountHideAccount: +UPDATE BankAccount +SET hideAccount = ? +WHERE id = ?; + +updateBankAccountIncludeInAutomaticAccountsUpdate: +UPDATE BankAccount +SET includeInAutomaticAccountsUpdate = ? +WHERE id = ?; + + CREATE TABLE IF NOT EXISTS TanMethod ( id INTEGER PRIMARY KEY AUTOINCREMENT, diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt index 43addab..46c36dd 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt @@ -44,7 +44,7 @@ fun BanksList( accountSelected?.invoke(bank, null) } - bank.accountsSorted.forEach { account -> + bank.accountsSorted.filterNot { it.hideAccount }.forEach { account -> NavigationMenuItem(itemModifier, account.displayName, textColor, iconSize, IconTextSpacing, itemHorizontalPadding, bankAccount = account) { accountSelected?.invoke(bank, account) } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/screens/BankAccountSettingsScreen.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/screens/BankAccountSettingsScreen.kt index 8906746..5f5a02d 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/screens/BankAccountSettingsScreen.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/screens/BankAccountSettingsScreen.kt @@ -6,7 +6,9 @@ import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import kotlinx.coroutines.launch import net.codinux.banking.persistence.entities.BankAccountEntity +import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.config.Internationalization import net.codinux.banking.ui.extensions.verticalScroll import net.codinux.banking.ui.forms.* @@ -16,20 +18,36 @@ fun BankAccountSettingsScreen(account: BankAccountEntity, onClosed: () -> Unit) var enteredAccountName by remember { mutableStateOf(account.displayName) } - var selectedIncludeInAutomaticAccountsUpdate by remember { mutableStateOf(account.includeInAutomaticAccountsUpdate) } - var selectedHideAccount by remember { mutableStateOf(account.hideAccount) } - val hasDataChanged by remember(enteredAccountName) { + var selectedIncludeInAutomaticAccountsUpdate by remember { mutableStateOf(account.includeInAutomaticAccountsUpdate) } + + val hasDataChanged by remember(enteredAccountName, selectedHideAccount, selectedIncludeInAutomaticAccountsUpdate) { mutableStateOf( enteredAccountName != account.displayName - || selectedIncludeInAutomaticAccountsUpdate != account.includeInAutomaticAccountsUpdate || selectedHideAccount != account.hideAccount + || selectedIncludeInAutomaticAccountsUpdate != account.includeInAutomaticAccountsUpdate ) } + val coroutineScope = rememberCoroutineScope() - FullscreenViewBase(account.displayName, onClosed = onClosed) { + + fun saveChanges() { + coroutineScope.launch { + DI.bankingService.updateAccount(account, enteredAccountName, selectedHideAccount, selectedIncludeInAutomaticAccountsUpdate) + } + } + + + FullscreenViewBase( + account.displayName, + confirmButtonTitle = "Speichern", + confirmButtonEnabled = hasDataChanged, + showDismissButton = true, + onConfirm = { saveChanges() }, + onClosed = onClosed + ) { Column(Modifier.fillMaxSize().verticalScroll().padding(8.dp)) { Column { SectionHeader("Einstellungen", false) @@ -41,9 +59,9 @@ fun BankAccountSettingsScreen(account: BankAccountEntity, onClosed: () -> Unit) modifier = Modifier.fillMaxWidth().padding(top = 8.dp, bottom = 8.dp) ) -// BooleanOption("Bei Kontoaktualisierung einbeziehen", selectedIncludeInAutomaticAccountsUpdate) { selectedIncludeInAutomaticAccountsUpdate = it } -// -// BooleanOption("Konto ausblenden", selectedHideAccount) { selectedHideAccount = it } + BooleanOption("Bei Kontoaktualisierung einbeziehen (autom. Kontoaktualisierung noch nicht umgesetzt)", selectedIncludeInAutomaticAccountsUpdate) { selectedIncludeInAutomaticAccountsUpdate = it } + + BooleanOption("Konto ausblenden", selectedHideAccount) { selectedHideAccount = it } } SelectionContainer { diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt index 7e93fcb..e9a0fea 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt @@ -75,7 +75,7 @@ class BankingService( updateBanksInUi(getAllBanks()) uiState.transactions.value = getAllAccountTransactionsAsViewModel() - uiState.holdings.value = uiState.banks.value.flatMap { it.accounts }.flatMap { it.holdings } + uiState.holdings.value = getCurrentUiBanksList().flatMap { it.accounts }.flatMap { it.holdings } } catch (e: Throwable) { log.error(e) { "Could not read all banks and account transactions from repository" } } @@ -107,7 +107,27 @@ class BankingService( bank.userSetDisplayName = bankName } - updateBanksInUi(uiState.banks.value.toList()) // update displayed banks to reflect new value(s) + notifyBanksListUpdated() + } catch (e: Throwable) { + showAndLogError(ErroneousAction.SaveToDatabase, "Could not update bank $bank", "Bankzugangsdaten konnten nicht aktualisisert werden", e) + } + } + + suspend fun updateAccount(account: BankAccountEntity, userSetDisplayName: String?, hideAccount: Boolean, includeInAutomaticAccountsUpdate: Boolean) { + try { + bankingRepository.updateAccount(account, userSetDisplayName, hideAccount, includeInAutomaticAccountsUpdate) + + if (account.userSetDisplayName != userSetDisplayName) { + account.userSetDisplayName = userSetDisplayName + } + if (account.hideAccount != hideAccount) { + account.hideAccount = hideAccount + } + if (account.includeInAutomaticAccountsUpdate != includeInAutomaticAccountsUpdate) { + account.includeInAutomaticAccountsUpdate = includeInAutomaticAccountsUpdate + } + + notifyBanksListUpdated() } catch (e: Throwable) { // showAndLogError("Could not update bank $bank", e) } @@ -192,7 +212,8 @@ class BankingService( if (selectedAccount != null) { updateAccountTransactions(selectedAccount.bank, selectedAccount.bankAccount) } else { - uiState.banks.value.forEach { bank -> + getCurrentUiBanksList().forEach { bank -> + // TODO: when implementing automatic account transactions update, filter out accounts with includeInAutomaticAccountsUpdate == false updateAccountTransactions(bank) } } @@ -283,8 +304,22 @@ class BankingService( } - private fun updateBanksInUi(banks: List) { - uiState.banks.value = banks + private fun getCurrentUiBanksList() = uiState.banks.value + + private suspend fun notifyBanksListUpdated() { + val currentBanksList = getCurrentUiBanksList() + + if (currentBanksList.isNotEmpty()) { + // if we only would call uiState.banks.emit(banks) with the same banks list as currently, nothing would change -> + // update does not get triggered -> for a short time display a different banks list and then return to actual banks list + updateBanksInUi(currentBanksList.toMutableList().also { it.add(it.last()) }) + try { delay(10) } catch (e: Throwable) { } + updateBanksInUi(currentBanksList) + } + } + + private suspend fun updateBanksInUi(banks: List) { + uiState.banks.emit(banks) } private fun updateTransactionsInUi(addedTransactions: List): List {