diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/BankingRepository.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/BankingRepository.kt index 2287612..be9ebca 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/BankingRepository.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/BankingRepository.kt @@ -1,17 +1,17 @@ package net.codinux.banking.dataaccess import net.codinux.banking.client.model.AccountTransaction -import net.codinux.banking.client.model.UserAccount +import net.codinux.banking.client.model.User import net.codinux.banking.dataaccess.entities.AccountTransactionEntity import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.model.AccountTransactionViewModel interface BankingRepository { - fun getAllUserAccounts(): List + fun getAllUsers(): List - suspend fun persistUserAccount(userAccount: UserAccount): UserAccountEntity + suspend fun persistUser(user: User): UserEntity suspend fun persistTransactions(bankAccount: BankAccountEntity, transactions: List): List @@ -20,7 +20,7 @@ interface BankingRepository { fun getAllAccountTransactions(): List - fun getAllTransactionsOfUserAccount(userAccount: UserAccountEntity): List + fun getAllTransactionsOfUser(user: UserEntity): List fun getTransactionById(transactionId: Long): AccountTransactionEntity? diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/InMemoryBankingRepository.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/InMemoryBankingRepository.kt index be672e0..f9449b4 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/InMemoryBankingRepository.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/InMemoryBankingRepository.kt @@ -1,29 +1,29 @@ package net.codinux.banking.dataaccess import net.codinux.banking.client.model.AccountTransaction -import net.codinux.banking.client.model.UserAccount +import net.codinux.banking.client.model.User import net.codinux.banking.dataaccess.entities.AccountTransactionEntity import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.model.AccountTransactionViewModel class InMemoryBankingRepository( - userAccounts: Collection = emptyList(), + users: Collection = emptyList(), transactions: Collection = emptyList() ) : BankingRepository { private var nextId = 0L // TODO: make thread-safe - private val userAccounts = userAccounts.map { map(it) }.toMutableList() + private val users = users.map { map(it) }.toMutableList() private val transactions = transactions.map { map(it) }.toMutableList() - override fun getAllUserAccounts(): List = userAccounts.toList() + override fun getAllUsers(): List = users.toList() - override suspend fun persistUserAccount(userAccount: UserAccount): UserAccountEntity { - val entity = map(userAccount) // TODO: may fix someday and add also BankAccounts and their id - this.userAccounts.add(entity) + override suspend fun persistUser(user: User): UserEntity { + val entity = map(user) // TODO: may fix someday and add also BankAccounts and their id + this.users.add(entity) return entity } @@ -37,29 +37,31 @@ class InMemoryBankingRepository( override fun getAllAccountTransactions(): List = transactions.toList() - override fun getAllTransactionsOfUserAccount(userAccount: UserAccountEntity): List = - getAllAccountTransactions().filter { it.userAccountId == userAccount.id } + override fun getAllTransactionsOfUser(user: UserEntity): List = + getAllAccountTransactions().filter { it.userId == user.id } override fun getTransactionById(transactionId: Long): AccountTransactionEntity? = getAllAccountTransactions().firstOrNull { it.id == transactionId } - private fun map(account: UserAccount) = UserAccountEntity( + private fun map(account: User) = UserEntity( nextId++, account.bankCode, account.loginName, account.password, account.bankName, account.bic, account.customerName, account.userId, // TODO: may fix someday and also add BankAccounts - emptyList(), account.selectedTanMethodId, emptyList(), account.selectedTanMediumName, emptyList(), - account.bankingGroup, account.iconUrl, account.wrongCredentialsEntered, account.userSetDisplayName, account.displayIndex + emptyList(), account.selectedTanMethodIdentifier, emptyList(), account.selectedTanMediumIdentifier, emptyList(), + account.bankingGroup, account.finTsServerAddress, + account.userSetDisplayName, account.displayIndex, + account.iconUrl, account.wrongCredentialsEntered, ) // TODO: someday may fix and get userAccountId and bankAccountId - private fun map(transaction: AccountTransaction, userAccountId: Long = nextId++, bankAccountId: Long = nextId++) = AccountTransactionEntity( + private fun map(transaction: AccountTransaction, userId: Long = nextId++, bankAccountId: Long = nextId++) = AccountTransactionEntity( nextId++, - userAccountId, bankAccountId, + userId, bankAccountId, transaction.amount, transaction.currency, transaction.reference, transaction.bookingDate, transaction.valueDate, - transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId, - transaction.bookingText + transaction.otherPartyName, transaction.otherPartyBankId, transaction.otherPartyAccountId, + transaction.postingText ) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepository.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepository.kt index ba06ca1..8b87929 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepository.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepository.kt @@ -6,7 +6,7 @@ import kotlinx.datetime.LocalDate import net.codinux.banking.client.model.* import net.codinux.banking.dataaccess.entities.AccountTransactionEntity import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.model.AccountTransactionViewModel import net.codinux.log.logger import kotlin.enums.EnumEntries @@ -25,42 +25,46 @@ open class SqliteBankingRepository( private val log by logger() - override fun getAllUserAccounts(): List { - val bankAccounts = getAllBankAccounts().groupBy { it.userAccountId } - return userAccountQueries.selectAllUserAccounts { id, bankCode, loginName, password, bankName, bic, customerName, userId, selectedTanMethodId, selectedTanMediumName, bankingGroup, iconUrl, wrongCredentialsEntered, userSetDisplayName, displayIndex -> - UserAccountEntity(id, bankCode, loginName, password, bankName, bic, customerName, userId, bankAccounts[id] ?: emptyList(), selectedTanMethodId, emptyList(), selectedTanMediumName, emptyList(), - bankingGroup?.let { BankingGroup.valueOf(it) }, iconUrl, wrongCredentialsEntered, userSetDisplayName, displayIndex.toInt()) + override fun getAllUsers(): List { + val bankAccounts = getAllBankAccounts().groupBy { it.userId } + + return userAccountQueries.selectAllUsers { id, bankCode, loginName, password, bankName, bic, customerName, userId, selectedTanMethodId, selectedTanMediumName, bankingGroup, iconUrl, wrongCredentialsEntered, userSetDisplayName, displayIndex -> + UserEntity(id, bankCode, loginName, password, bankName, bic, customerName, userId, bankAccounts[id] ?: emptyList(), selectedTanMethodId, emptyList(), selectedTanMediumName, emptyList(), + bankingGroup?.let { BankingGroup.valueOf(it) }, "", userSetDisplayName, displayIndex.toInt(), iconUrl, wrongCredentialsEntered) }.executeAsList() } - override suspend fun persistUserAccount(userAccount: UserAccount): UserAccountEntity { + override suspend fun persistUser(user: User): UserEntity { return userAccountQueries.transactionWithResult { - userAccountQueries.insertUserAccount(userAccount.bankCode, userAccount.loginName, userAccount.password, userAccount.bankName, userAccount.bic, - userAccount.customerName, userAccount.userId, userAccount.selectedTanMethodId, userAccount.selectedTanMediumName, - userAccount.bankingGroup?.name, userAccount.iconUrl, userAccount.wrongCredentialsEntered, userAccount.userSetDisplayName, userAccount.displayIndex.toLong() + userAccountQueries.insertUser(user.bankCode, user.loginName, user.password, user.bankName, user.bic, + user.customerName, user.userId, user.selectedTanMethodIdentifier, user.selectedTanMediumIdentifier, + user.bankingGroup?.name, user.iconUrl, user.wrongCredentialsEntered, user.userSetDisplayName, user.displayIndex.toLong() ) - val userAccountId = getLastInsertedId() // getLastInsertedId() / last_insert_rowid() has to be called in a transaction with the insert operation, otherwise it will not work + val userId = getLastInsertedId() // getLastInsertedId() / last_insert_rowid() has to be called in a transaction with the insert operation, otherwise it will not work - val bankAccounts = persistBankAccounts(userAccountId, userAccount.accounts) + val bankAccounts = persistBankAccounts(userId, user.accounts) - UserAccountEntity(userAccountId, userAccount, bankAccounts) + UserEntity(userId, user, bankAccounts) } } - fun getAllBankAccounts(): List = userAccountQueries.selectAllBankAccounts { id, userAccountId, identifier, accountHolderName, type, iban, subAccountNumber, productName, currency, accountLimit, balance, isAccountTypeSupportedByApplication, features, countDaysForWhichTransactionsAreKept, lastTransactionsRetrievalTime, retrievedTransactionsFrom, userSetDisplayName, displayIndex, hideAccount, includeInAutomaticAccountsUpdate -> + fun getAllBankAccounts(): List = userAccountQueries.selectAllBankAccounts { id, userId, identifier, accountHolderName, type, iban, subAccountNumber, productName, currency, accountLimit, balance, isAccountTypeSupportedByApplication, features, serverTransactionsRetentionDays, lastTransactionsRetrievalTime, retrievedTransactionsFrom, userSetDisplayName, displayIndex, hideAccount, includeInAutomaticAccountsUpdate -> BankAccountEntity( - id, userAccountId, - identifier, accountHolderName, BankAccountType.valueOf(type), - iban, subAccountNumber, productName, currency, accountLimit, + id, userId, + + identifier, subAccountNumber, iban, productName, + accountHolderName, BankAccountType.valueOf(type), + currency, accountLimit, - mapToAmount(balance), isAccountTypeSupportedByApplication, mapEnumSet(features, BankAccountFeatures.entries), - mapToInt(countDaysForWhichTransactionsAreKept), + mapToAmount(balance), + + mapToInt(serverTransactionsRetentionDays), mapToInstant(lastTransactionsRetrievalTime), mapToDate(retrievedTransactionsFrom), mutableListOf(), mutableListOf(), @@ -70,22 +74,22 @@ open class SqliteBankingRepository( ) }.executeAsList() - private suspend fun persistBankAccounts(userAccountId: Long, bankAccounts: Collection): List = - bankAccounts.map { persistBankAccount(userAccountId, it) } + private suspend fun persistBankAccounts(userId: Long, bankAccounts: Collection): List = + bankAccounts.map { persistBankAccount(userId, it) } /** * Has to be executed in a transaction in order that getting persisted BankAccount's id works~ */ - private suspend fun persistBankAccount(userAccountId: Long, account: BankAccount): BankAccountEntity { + private suspend fun persistBankAccount(userId: Long, account: BankAccount): BankAccountEntity { userAccountQueries.insertBankAccount( - userAccountId, + userId, account.identifier, account.accountHolderName, mapEnum(account.type), account.iban, account.subAccountNumber, account.productName, account.currency, account.accountLimit, mapAmount(account.balance), account.isAccountTypeSupportedByApplication, mapEnumCollectionToString(account.features), - mapInt(account.countDaysForWhichTransactionsAreKept), + mapInt(account.serverTransactionsRetentionDays), mapInstant(account.lastTransactionsRetrievalTime), mapDate(account.retrievedTransactionsFrom), account.userSetDisplayName, mapInt(account.displayIndex), @@ -95,25 +99,24 @@ open class SqliteBankingRepository( val accountId = getLastInsertedId() val accountTransactionEntities = account.bookedTransactions.map { transaction -> - persistTransaction(userAccountId, accountId, transaction) + persistTransaction(userId, accountId, transaction) } - return BankAccountEntity(accountId, userAccountId, account, accountTransactionEntities) + return BankAccountEntity(accountId, userId, account, accountTransactionEntities) } override fun getAllAccountTransactionsAsViewModel(): List = - // TODO: find a better way to express the reference value to display, sepaReference or (unparsed)reference - accountTransactionQueries.selectAllTransactionsAsViewModel { id, userAccountId, bankAccountId, amount, currency, unparsedReference, valueDate, otherPartyName, bookingText, sepaReference, userSetDisplayName, category -> - AccountTransactionViewModel(id, userAccountId, bankAccountId, mapToAmount(amount), currency, sepaReference ?: unparsedReference, mapToDate(valueDate), otherPartyName, bookingText, userSetDisplayName, category) + accountTransactionQueries.selectAllTransactionsAsViewModel { id, userId, bankAccountId, amount, currency, reference, valueDate, otherPartyName, postingText, userSetDisplayName, category -> + AccountTransactionViewModel(id, userId, bankAccountId, mapToAmount(amount), currency, reference, mapToDate(valueDate), otherPartyName, postingText, userSetDisplayName, category) }.executeAsList() override fun getAllAccountTransactions(): List { return accountTransactionQueries.selectAllTransactions(::mapTransaction).executeAsList() } - override fun getAllTransactionsOfUserAccount(userAccount: UserAccountEntity): List { - return accountTransactionQueries.selectAllTransactionsOfUserAccount(userAccount.id, ::mapTransaction).executeAsList() + override fun getAllTransactionsOfUser(user: UserEntity): List { + return accountTransactionQueries.selectAllTransactionsOfUser(user.id, ::mapTransaction).executeAsList() } override fun getTransactionById(transactionId: Long): AccountTransactionEntity? = @@ -123,7 +126,7 @@ open class SqliteBankingRepository( override suspend fun persistTransactions(bankAccount: BankAccountEntity, transactions: List): List { return accountTransactionQueries.transactionWithResult { transactions.map { transaction -> - persistTransaction(bankAccount.userAccountId, bankAccount.id, transaction) + persistTransaction(bankAccount.userId, bankAccount.id, transaction) } } } @@ -131,36 +134,34 @@ open class SqliteBankingRepository( /** * Has to be executed in a transaction in order that getting persisted AccountTransaction's id works~ */ - protected open suspend fun persistTransaction(userAccountId: Long, bankAccountId: Long, transaction: AccountTransaction): AccountTransactionEntity { + protected open suspend fun persistTransaction(userId: Long, bankAccountId: Long, transaction: AccountTransaction): AccountTransactionEntity { accountTransactionQueries.insertTransaction( - userAccountId, bankAccountId, + userId, bankAccountId, - mapAmount(transaction.amount), transaction.currency, transaction.unparsedReference, + mapAmount(transaction.amount), transaction.currency, transaction.reference, mapDate(transaction.bookingDate), mapDate(transaction.valueDate), - transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId, - transaction.bookingText, - transaction.userSetDisplayName, null, transaction.notes, // TODO: add category to AccountTransaction + transaction.otherPartyName, transaction.otherPartyBankId, transaction.otherPartyAccountId, + transaction.postingText, - transaction.information, - transaction.statementNumber?.toLong(), transaction.sequenceNumber?.toLong(), + transaction.userSetDisplayName, transaction.category, transaction.notes, + + transaction.statementNumber?.toLong(), transaction.sheetNumber?.toLong(), mapAmount(transaction.openingBalance), mapAmount(transaction.closingBalance), transaction.endToEndReference, transaction.customerReference, transaction.mandateReference, transaction.creditorIdentifier, transaction.originatorsIdentificationCode, + transaction.compensationAmount, transaction.originalAmount, - transaction.sepaReference, transaction.deviantOriginator, transaction.deviantRecipient, - transaction.referenceWithNoSpecialType, transaction.primaNotaNumber, transaction.textKeySupplement, + transaction.referenceWithNoSpecialType, - transaction.currencyType, transaction.bookingKey, - transaction.referenceForTheAccountOwner, transaction.referenceOfTheAccountServicingInstitution, - transaction.supplementaryDetails, + transaction.journalNumber, transaction.textKeyAddition, - transaction.transactionReferenceNumber, transaction.relatedReferenceNumber + transaction.orderReferenceNumber, transaction.referenceNumber ) - return AccountTransactionEntity(getLastInsertedId(), userAccountId, bankAccountId, transaction) + return AccountTransactionEntity(getLastInsertedId(), userId, bankAccountId, transaction) } @@ -169,46 +170,59 @@ open class SqliteBankingRepository( private fun mapTransaction( - id: Long, userAccountId: Long, bankAccountId: Long, - amount: String, currency: String, reference: String, bookingDate: String, valueDate: String, - otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?, bookingText: String?, + id: Long, userId: Long, bankAccountId: Long, + + amount: String, currency: String, reference: String?, + bookingDate: String, valueDate: String, + + otherPartyName: String?, otherPartyBankId: String?, otherPartyAccountId: String?, + postingText: String?, + userSetDisplayName: String?, category: String?, notes: String?, - information: String?, statementNumber: Long?, sequenceNumber: Long?, + + statementNumber: Long?, sheetNumber: Long?, + openingBalance: String?, closingBalance: String?, + endToEndReference: String?, customerReference: String?, mandateReference: String?, creditorIdentifier: String?, originatorsIdentificationCode: String?, - compensationAmount: String?, originalAmount: String?, sepaReference: String?, deviantOriginator: String?, deviantRecipient: String?, referenceWithNoSpecialType: String?, - primaNotaNumber: String?, textKeySupplement: String?, currencyType: String?, bookingKey: String?, referenceForTheAccountOwner: String?, referenceOfTheAccountServicingInstitution: String?, - supplementaryDetails: String?, transactionReferenceNumber: String?, relatedReferenceNumber: String?): AccountTransactionEntity = - AccountTransactionEntity( - id, - userAccountId, bankAccountId, - Amount(amount), currency, reference, - mapToDate(bookingDate), mapToDate(valueDate), - otherPartyName, otherPartyBankCode, otherPartyAccountId, - bookingText, + compensationAmount: String?, originalAmount: String?, deviantOriginator: String?, deviantRecipient: String?, referenceWithNoSpecialType: String?, - userSetDisplayName, category, notes, + journalNumber: String?, textKeyAddition: String?, - information, - statementNumber?.toInt(), sequenceNumber?.toInt(), + referenceForTheAccountOwner: String?, referenceOfTheAccountServicingInstitution: String?, supplementaryDetails: String?, - mapToAmount(openingBalance), mapToAmount(closingBalance), + transactionReferenceNumber: String?, relatedReferenceNumber: String? + ): AccountTransactionEntity = AccountTransactionEntity( + id, + userId, bankAccountId, - endToEndReference, customerReference, mandateReference, - creditorIdentifier, originatorsIdentificationCode, - compensationAmount, originalAmount, - sepaReference, - deviantOriginator, deviantRecipient, - referenceWithNoSpecialType, primaNotaNumber, - textKeySupplement, + Amount(amount), currency, reference, + mapToDate(bookingDate), mapToDate(valueDate), + otherPartyName, otherPartyBankId, otherPartyAccountId, + postingText, - currencyType, bookingKey, - referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution, - supplementaryDetails, + mapToAmount(openingBalance), mapToAmount(closingBalance), - transactionReferenceNumber, relatedReferenceNumber - ) + userSetDisplayName, category, notes, + + statementNumber?.toInt(), sheetNumber?.toInt(), + + referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution, + supplementaryDetails, + + endToEndReference, mandateReference, + creditorIdentifier, originatorsIdentificationCode, + + compensationAmount, originalAmount, + deviantOriginator, deviantRecipient, + referenceWithNoSpecialType, + + journalNumber, textKeyAddition, + + transactionReferenceNumber, relatedReferenceNumber + // TODO: add isReversal + ) @JvmName("mapAmount") diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/AccountTransactionEntity.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/AccountTransactionEntity.kt index 0383147..96559c6 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/AccountTransactionEntity.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/AccountTransactionEntity.kt @@ -6,108 +6,117 @@ import net.codinux.banking.client.model.Amount class AccountTransactionEntity( val id: Long, - val userAccountId: Long, + val userId: Long, val bankAccountId: Long, amount: Amount, currency: String, - reference: String, + reference: String?, bookingDate: LocalDate, valueDate: LocalDate, otherPartyName: String? = null, - otherPartyBankCode: String? = null, + otherPartyBankId: String? = null, otherPartyAccountId: String? = null, - bookingText: String? = null, - - userSetDisplayName: String? = null, - category: String? = null, - notes: String? = null, - information: String? = null, - - statementNumber: Int? = null, - sequenceNumber: Int? = null, + postingText: String? = null, openingBalance: Amount? = null, closingBalance: Amount? = null, - endToEndReference: String? = null, + userSetDisplayName: String? = null, + category: String? = null, + notes: String? = null, + + statementNumber: Int? = null, + sheetNumber: Int? = null, + customerReference: String? = null, + bankReference: String? = null, + furtherInformation: String? = null, + + + endToEndReference: String? = null, mandateReference: String? = null, creditorIdentifier: String? = null, originatorsIdentificationCode: String? = null, + compensationAmount: String? = null, originalAmount: String? = null, - sepaReference: String? = null, deviantOriginator: String? = null, deviantRecipient: String? = null, referenceWithNoSpecialType: String? = null, - primaNotaNumber: String? = null, - textKeySupplement: String? = null, - currencyType: String? = null, - bookingKey: String? = null, - referenceForTheAccountOwner: String? = null, - referenceOfTheAccountServicingInstitution: String? = null, - supplementaryDetails: String? = null, + journalNumber: String? = null, + textKeyAddition: String? = null, - transactionReferenceNumber: String? = null, - relatedReferenceNumber: String? = null + orderReferenceNumber: String? = null, + referenceNumber: String? = null, + + isReversal: Boolean = false, ) : AccountTransaction( amount, currency, reference, bookingDate, valueDate, - otherPartyName, otherPartyBankCode, otherPartyAccountId, - bookingText, + otherPartyName, otherPartyBankId, otherPartyAccountId, + postingText, - information, - statementNumber, sequenceNumber, openingBalance, closingBalance, - endToEndReference, customerReference, mandateReference, + statementNumber, sheetNumber, + + customerReference, bankReference, furtherInformation, + + endToEndReference, mandateReference, creditorIdentifier, originatorsIdentificationCode, + compensationAmount, originalAmount, - sepaReference, deviantOriginator, deviantRecipient, - referenceWithNoSpecialType, primaNotaNumber, - textKeySupplement, + referenceWithNoSpecialType, - currencyType, bookingKey, - referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution, - supplementaryDetails, + journalNumber, textKeyAddition, - transactionReferenceNumber, relatedReferenceNumber, + orderReferenceNumber, referenceNumber, + + isReversal, userSetDisplayName, category, notes ) { - constructor(id: Long, userAccountId: Long, bankAccountId: Long, transaction: AccountTransaction) : this( - id, userAccountId, bankAccountId, - transaction.amount, transaction.currency, transaction.unparsedReference, transaction.bookingDate, transaction.valueDate, - transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId, transaction.bookingText, + constructor(id: Long, userId: Long, bankAccountId: Long, transaction: AccountTransaction) : this( + id, userId, bankAccountId, + transaction.amount, transaction.currency, transaction.reference, + transaction.bookingDate, transaction.valueDate, - transaction.userSetDisplayName, transaction.category, transaction.notes, transaction.information, + transaction.otherPartyName, transaction.otherPartyBankId, transaction.otherPartyAccountId, + + transaction.postingText, - transaction.statementNumber, transaction.sequenceNumber, transaction.openingBalance, transaction.closingBalance, - transaction.endToEndReference, transaction.customerReference, transaction.mandateReference, + transaction.userSetDisplayName, transaction.category, transaction.notes, + + transaction.statementNumber, transaction.sheetNumber, + + transaction.customerReference, transaction.bankReference, + transaction.furtherInformation, + + transaction.endToEndReference, transaction.mandateReference, transaction.creditorIdentifier, transaction.originatorsIdentificationCode, + transaction.compensationAmount, transaction.originalAmount, - transaction.sepaReference, transaction.deviantOriginator, transaction.deviantRecipient, - transaction.referenceWithNoSpecialType, transaction.primaNotaNumber, transaction.textKeySupplement, + transaction.referenceWithNoSpecialType, - transaction.currencyType, transaction.bookingKey, - transaction.referenceForTheAccountOwner, transaction.referenceOfTheAccountServicingInstitution, - transaction.supplementaryDetails, + transaction.journalNumber, transaction.textKeyAddition, - transaction.transactionReferenceNumber, transaction.relatedReferenceNumber + transaction.orderReferenceNumber, transaction.referenceNumber, + + transaction.isReversal, ) override val identifier: String by lazy { - "$userAccountId ${super.identifier}" + "$userId ${super.identifier}" } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/BankAccountEntity.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/BankAccountEntity.kt index 98ffda4..9e3bf78 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/BankAccountEntity.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/BankAccountEntity.kt @@ -6,28 +6,29 @@ import net.codinux.banking.client.model.* class BankAccountEntity( val id: Long, - val userAccountId: Long, + val userId: Long, identifier: String, + subAccountNumber: String? = null, + iban: String? = null, + productName: String? = null, + accountHolderName: String, type: BankAccountType = BankAccountType.Other, - iban: String? = null, - subAccountNumber: String? = null, - productName: String? = null, currency: String = "EUR", accountLimit: String? = null, - balance: Amount = Amount.Zero, // TODO: add a BigDecimal library - isAccountTypeSupportedByApplication: Boolean = true, features: Set = emptySet(), - countDaysForWhichTransactionsAreKept: Int? = null, + balance: Amount = Amount.Zero, // TODO: add a BigDecimal library + + serverTransactionsRetentionDays: Int? = null, lastTransactionsRetrievalTime: Instant? = null, retrievedTransactionsFrom: LocalDate? = null, bookedTransactions: MutableList = mutableListOf(), - unbookedTransactions: MutableList = mutableListOf(), + prebookedTransactions: MutableList = mutableListOf(), userSetDisplayName: String? = null, displayIndex: Int = 0, @@ -35,21 +36,39 @@ class BankAccountEntity( hideAccount: Boolean = false, includeInAutomaticAccountsUpdate: Boolean = true ) : BankAccount( - identifier, accountHolderName, type, iban, subAccountNumber, productName, currency, accountLimit, - balance, isAccountTypeSupportedByApplication, features, - lastTransactionsRetrievalTime, retrievedTransactionsFrom, countDaysForWhichTransactionsAreKept, - bookedTransactions as MutableList, unbookedTransactions, - userSetDisplayName, displayIndex, hideAccount, includeInAutomaticAccountsUpdate + identifier, subAccountNumber, iban, productName, + + accountHolderName, type, currency, accountLimit, + + isAccountTypeSupportedByApplication, features, + + balance, + + serverTransactionsRetentionDays, lastTransactionsRetrievalTime, retrievedTransactionsFrom, + + bookedTransactions as MutableList, prebookedTransactions, + + userSetDisplayName, displayIndex, + hideAccount, includeInAutomaticAccountsUpdate ) { - constructor(id: Long, userAccountId: Long, account: BankAccount, transactions: List = emptyList()) : this( - id, userAccountId, - account.identifier, account.accountHolderName, account.type, account.iban, account.subAccountNumber, - account.productName, account.currency, account.accountLimit, - account.balance, + constructor(id: Long, userId: Long, account: BankAccount, transactions: List = emptyList()) : this( + id, userId, + account.identifier, account.subAccountNumber, account.iban, account.productName, + + account.accountHolderName, account.type, + account.currency, account.accountLimit, + account.isAccountTypeSupportedByApplication, account.features, - account.countDaysForWhichTransactionsAreKept, account.lastTransactionsRetrievalTime, account.retrievedTransactionsFrom, + + account.balance, + + account.serverTransactionsRetentionDays, + account.lastTransactionsRetrievalTime, account.retrievedTransactionsFrom, + transactions.toMutableList(), mutableListOf(), - account.userSetDisplayName, account.displayIndex, account.hideAccount, account.includeInAutomaticAccountsUpdate + + account.userSetDisplayName, account.displayIndex, + account.hideAccount, account.includeInAutomaticAccountsUpdate ) val bookedTransactionsEntities: MutableList = bookedTransactions diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/UserAccountEntity.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/UserEntity.kt similarity index 52% rename from composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/UserAccountEntity.kt rename to composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/UserEntity.kt index 4f2d443..99376fe 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/UserAccountEntity.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/dataaccess/entities/UserEntity.kt @@ -1,13 +1,13 @@ package net.codinux.banking.dataaccess.entities import net.codinux.banking.client.model.BankingGroup -import net.codinux.banking.client.model.UserAccount +import net.codinux.banking.client.model.User import net.codinux.banking.client.model.tan.TanMedium import net.codinux.banking.client.model.tan.TanMethod -class UserAccountEntity( +class UserEntity( val id: Long, - + bankCode: String, loginName: String, password: String?, @@ -16,38 +16,43 @@ class UserAccountEntity( bic: String, customerName: String, - userId: String = loginName, + userId: String? = null, override val accounts: List = emptyList(), - selectedTanMethodId: String? = null, + selectedTanMethodIdentifier: String? = null, tanMethods: List = listOf(), - selectedTanMediumName: String? = null, + selectedTanMediumIdentifier: String? = null, tanMedia: List = listOf(), bankingGroup: BankingGroup? = null, - iconUrl: String? = null, - - wrongCredentialsEntered: Boolean = false, + finTsServerAddress: String, userSetDisplayName: String? = null, - displayIndex: Int = 0 -) : UserAccount(bankCode, loginName, password, bankName, bic, customerName, userId, accounts, selectedTanMethodId, tanMethods, selectedTanMediumName, tanMedia, bankingGroup, iconUrl) { + displayIndex: Int = 0, + + iconUrl: String? = null, + wrongCredentialsEntered: Boolean = false +) : User(bankCode, loginName, password, bankName, bic, customerName, userId, accounts, selectedTanMethodIdentifier, tanMethods, selectedTanMediumIdentifier, tanMedia, bankingGroup, finTsServerAddress) { init { - this.wrongCredentialsEntered = wrongCredentialsEntered this.userSetDisplayName = userSetDisplayName this.displayIndex = displayIndex + + this.iconUrl = iconUrl + this.wrongCredentialsEntered = wrongCredentialsEntered } - constructor(id: Long, user: UserAccount, bankAccounts: List) : this( + constructor(id: Long, user: User, bankAccounts: List) : this( id, user.bankCode, user.loginName, user.password, user.bankName, user.bic, user.customerName, user.userId, bankAccounts, - user.selectedTanMethodId, emptyList(), user.selectedTanMediumName, emptyList(), - user.bankingGroup, user.iconUrl, user.wrongCredentialsEntered, user.userSetDisplayName, user.displayIndex + user.selectedTanMethodIdentifier, user.tanMethods, user.selectedTanMediumIdentifier, user.tanMedia, + user.bankingGroup, user.finTsServerAddress, + user.userSetDisplayName, user.displayIndex, + user.iconUrl, user.wrongCredentialsEntered, ) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/BottomBar.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/BottomBar.kt index 1d07e5c..0d92c81 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/BottomBar.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/BottomBar.kt @@ -1,7 +1,6 @@ package net.codinux.banking.ui.appskeleton import androidx.compose.animation.* -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape @@ -18,13 +17,9 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.key.* -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.platform.LocalViewConfiguration -import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.toSize import bankmeister.composeapp.generated.resources.Res import bankmeister.composeapp.generated.resources.filter_alt import kotlinx.coroutines.launch @@ -39,7 +34,7 @@ private val IconWidth = 48.dp @Composable fun BottomBar(showMenuDrawer: Boolean = true) { - val userAccounts by uiState.userAccounts.collectAsState() + val users by uiState.users.collectAsState() val transactionsFilter by uiState.transactionsFilter.collectAsState() @@ -75,7 +70,7 @@ fun BottomBar(showMenuDrawer: Boolean = true) { } else if (selectedAccount.bankAccount != null) { selectedAccount.bankAccount.displayName } else { - selectedAccount.userAccount.displayName + selectedAccount.user.displayName } Text(title, color = color, maxLines = 1, overflow = TextOverflow.Ellipsis) @@ -132,7 +127,7 @@ fun BottomBar(showMenuDrawer: Boolean = true) { } - if (userAccounts.isNotEmpty()) { + if (users.isNotEmpty()) { if (showSearchbar == false) { Row(Modifier.fillMaxHeight().widthIn(IconWidth, IconWidth), verticalAlignment = Alignment.CenterVertically) { IconButton({ showSearchbar = true }, Modifier.width(IconWidth)) { diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenuContent.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenuContent.kt index 32ade6e..88f85bc 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenuContent.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenuContent.kt @@ -54,7 +54,7 @@ private val VerticalSpacing = 8.dp fun SideMenuContent() { val drawerState = uiState.drawerState.collectAsState().value - val accounts = uiState.userAccounts.collectAsState().value + val accounts = uiState.users.collectAsState().value val coroutineScope = rememberCoroutineScope() diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BankIcon.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BankIcon.kt index ee546f9..48a9a71 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BankIcon.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BankIcon.kt @@ -9,8 +9,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import net.codinux.banking.client.model.UserAccount -import net.codinux.banking.client.model.UserAccountViewInfo +import net.codinux.banking.client.model.User +import net.codinux.banking.client.model.BankViewInfo import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.model.BankInfo import net.dankito.banking.banklistcreator.prettifier.BankingGroupMapper @@ -22,8 +22,8 @@ private val bankIconService = DI.bankIconService private val DefaultIconModifier: Modifier = Modifier.size(16.dp) @Composable -fun BankIcon(userAccount: UserAccount?, modifier: Modifier = Modifier, iconModifier: Modifier = DefaultIconModifier, iconResource: DrawableResource? = null) { - val iconUrl by remember(userAccount?.bic) { mutableStateOf(userAccount?.let { bankIconService.findIconForBank(it) }) } +fun BankIcon(user: User?, modifier: Modifier = Modifier, iconModifier: Modifier = DefaultIconModifier, iconResource: DrawableResource? = null) { + val iconUrl by remember(user?.bic) { mutableStateOf(user?.let { bankIconService.findIconForBank(it) }) } BankIcon(iconUrl, modifier, iconModifier, iconResource = iconResource) } @@ -38,8 +38,8 @@ fun BankIcon(bank: BankInfo, modifier: Modifier = Modifier, iconModifier: Modifi } @Composable -fun BankIcon(userAccount: UserAccountViewInfo?, modifier: Modifier = Modifier, iconModifier: Modifier = DefaultIconModifier, iconResource: DrawableResource? = null) { - val iconUrl = userAccount?.let { bankIconService.findIconForBank(it.bankName, it.bankingGroup) } +fun BankIcon(user: BankViewInfo?, modifier: Modifier = Modifier, iconModifier: Modifier = DefaultIconModifier, iconResource: DrawableResource? = null) { + val iconUrl = user?.let { bankIconService.findIconForBank(it.bankName, it.bankingGroup) } BankIcon(iconUrl, modifier, iconModifier, iconResource = iconResource) } 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 b448a3d..f12c0ae 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 @@ -10,7 +10,7 @@ import androidx.compose.ui.unit.dp import bankmeister.composeapp.generated.resources.Res import bankmeister.composeapp.generated.resources.account import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.config.DI private val uiState = DI.uiState @@ -24,9 +24,9 @@ fun BanksList( textColor: Color = Color.White, itemModifier: Modifier = Modifier.height(48.dp).widthIn(min = 300.dp), itemHorizontalPadding: Dp = 8.dp, - accountSelected: ((UserAccountEntity?, BankAccountEntity?) -> Unit)? = null + accountSelected: ((UserEntity?, BankAccountEntity?) -> Unit)? = null ) { - val userAccounts = uiState.userAccounts.collectAsState() + val users = uiState.users.collectAsState() Column(modifier) { @@ -34,16 +34,16 @@ fun BanksList( accountSelected?.invoke(null, null) } - userAccounts.value.sortedBy { it.displayIndex }.forEach { userAccount -> + users.value.sortedBy { it.displayIndex }.forEach { user -> Spacer(Modifier.fillMaxWidth().height(12.dp)) - NavigationMenuItem(itemModifier, userAccount.displayName, textColor, iconSize, IconTextSpacing, itemHorizontalPadding, userAccount, iconResource = Res.drawable.account) { - accountSelected?.invoke(userAccount, null) + NavigationMenuItem(itemModifier, user.displayName, textColor, iconSize, IconTextSpacing, itemHorizontalPadding, user, iconResource = Res.drawable.account) { + accountSelected?.invoke(user, null) } - userAccount.accounts.sortedBy { it.displayIndex }.forEach { account -> + user.accounts.sortedBy { it.displayIndex }.forEach { account -> NavigationMenuItem(itemModifier, account.displayName, textColor, iconSize, IconTextSpacing, itemHorizontalPadding, bankAccount = account) { - accountSelected?.invoke(userAccount, account) + accountSelected?.invoke(user, account) } } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/NavigationMenuItem.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/NavigationMenuItem.kt index c38693f..9ec4560 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/NavigationMenuItem.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/NavigationMenuItem.kt @@ -18,7 +18,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.config.Colors import net.codinux.banking.ui.config.DI import org.jetbrains.compose.resources.DrawableResource @@ -37,7 +37,7 @@ fun NavigationMenuItem( iconSize: Dp = 24.dp, iconTextSpacing: Dp = 24.dp, horizontalPadding: Dp = 8.dp, - userAccount: UserAccountEntity? = null, + user: UserEntity? = null, bankAccount: BankAccountEntity? = null, iconResource: DrawableResource? = null, icon: (@Composable () -> Unit)? = null, @@ -54,7 +54,7 @@ fun NavigationMenuItem( modifier = modifier .clickable { onClick?.invoke() } .let { - if (userAccount != null && filterService.isSelected(userAccount, transactionsFilter) + if (user != null && filterService.isSelected(user, transactionsFilter) || bankAccount != null && filterService.isSelected(bankAccount, transactionsFilter)) { it.background(Colors.AccentAsSelectionBackground, shape = RoundedCornerShape(4.dp)) } else { @@ -68,7 +68,7 @@ fun NavigationMenuItem( icon() } } else { - BankIcon(userAccount, Modifier.padding(end = iconTextSpacing), Modifier.size(iconSize), iconResource = iconResource) + BankIcon(user, Modifier.padding(end = iconTextSpacing), Modifier.size(iconSize), iconResource = iconResource) } Text(text, color = textColor, modifier = Modifier.weight(1f), maxLines = 1, overflow = TextOverflow.Ellipsis) @@ -77,8 +77,8 @@ fun NavigationMenuItem( null } else if (bankAccount != null) { bankAccount.balance - } else if (userAccount != null) { - calculator.calculateBalanceOfUserAccount(userAccount) + } else if (user != null) { + calculator.calculateBalanceOfUser(user) } else { null } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/GroupedTransactionsListItems.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/GroupedTransactionsListItems.kt index ff646f8..a66a80e 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/GroupedTransactionsListItems.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/GroupedTransactionsListItems.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.codinux.banking.client.model.Amount -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.forms.RoundedCornersCard import net.codinux.banking.ui.model.AccountTransactionViewModel @@ -28,7 +28,7 @@ private val formatUtil = DI.formatUtil fun GroupedTransactionsListItems( modifier: Modifier, transactionsToDisplay: List, - userAccountsId: Map, + userAccountsId: Map, transactionsGrouping: TransactionsGrouping ) { val groupingService = remember { TransactionsGroupingService() } @@ -57,7 +57,9 @@ fun GroupedTransactionsListItems( RoundedCornersCard { Column(Modifier.background(Color.White)) { // LazyColumn inside LazyColumn is not allowed monthTransactions.forEachIndexed { index, transaction -> - TransactionListItem(userAccountsId[transaction.userAccountId], transaction, index, monthTransactions.size) + key(transaction.id) { + TransactionListItem(userAccountsId[transaction.userId], transaction, index, monthTransactions.size) + } } } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionListItem.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionListItem.kt index 0f11cee..12586c8 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionListItem.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionListItem.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch -import net.codinux.banking.client.model.UserAccount +import net.codinux.banking.client.model.User import net.codinux.banking.ui.composables.BankIcon import net.codinux.banking.ui.config.Colors import net.codinux.banking.ui.config.DI @@ -25,7 +25,7 @@ private val uiSettings = DI.uiSettings private val formatUtil = DI.formatUtil @Composable -fun TransactionListItem(userAccount: UserAccount?, transaction: AccountTransactionViewModel, itemIndex: Int, countItems: Int) { +fun TransactionListItem(user: User?, transaction: AccountTransactionViewModel, itemIndex: Int, countItems: Int) { val zebraStripes by uiSettings.zebraStripes.collectAsState() val showBankIcons by uiSettings.showBankIcons.collectAsState() @@ -48,9 +48,9 @@ fun TransactionListItem(userAccount: UserAccount?, transaction: AccountTransacti val transactionEntity = DI.bankingService.getTransaction(transaction.id) DI.uiState.showTransferMoneyDialogData.value = ShowTransferMoneyDialogData( - DI.uiState.userAccounts.value.firstNotNullOf { it.accounts.firstOrNull { it.id == transaction.bankAccountId } }, + DI.uiState.users.value.firstNotNullOf { it.accounts.firstOrNull { it.id == transaction.bankAccountId } }, transaction.otherPartyName, - transactionEntity?.otherPartyBankCode, + transactionEntity?.otherPartyBankId, transactionEntity?.otherPartyAccountId, if (withSameData) transaction.amount else null, if (withSameData) transaction.reference else null @@ -76,7 +76,7 @@ fun TransactionListItem(userAccount: UserAccount?, transaction: AccountTransacti Column(Modifier.weight(1f)) { Row { if (showBankIcons) { - BankIcon(userAccount, Modifier.padding(end = 6.dp)) + BankIcon(user, Modifier.padding(end = 6.dp)) } Text( @@ -90,7 +90,7 @@ fun TransactionListItem(userAccount: UserAccount?, transaction: AccountTransacti Spacer(modifier = Modifier.height(6.dp)) Text( - text = transaction.reference, + text = transaction.reference ?: "", Modifier.fillMaxWidth(), maxLines = 1, overflow = TextOverflow.Ellipsis diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionsList.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionsList.kt index 15d85d0..9ca12d5 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionsList.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/transactions/TransactionsList.kt @@ -25,9 +25,9 @@ private val formatUtil = DI.formatUtil @Composable fun TransactionsList(uiState: UiState, uiSettings: UiSettings, isMobile: Boolean = true) { - val userAccounts by uiState.userAccounts.collectAsState() - val userAccountsId by remember(userAccounts) { - derivedStateOf { userAccounts.associateBy { it.id } } + val users by uiState.users.collectAsState() + val usersById by remember(users) { + derivedStateOf { users.associateBy { it.id } } } val transactionsFilter by uiState.transactionsFilter.collectAsState() @@ -53,17 +53,19 @@ fun TransactionsList(uiState: UiState, uiSettings: UiSettings, isMobile: Boolean Spacer(Modifier.weight(1f)) if (showBalance) { - val balance = calculator.calculateBalanceOfDisplayedTransactions(transactionsToDisplay, userAccounts, transactionsFilter) + val balance = calculator.calculateBalanceOfDisplayedTransactions(transactionsToDisplay, users, transactionsFilter) Text(formatUtil.formatAmount(balance, "EUR"), color = formatUtil.getColorForAmount(balance, showColoredAmounts)) } } if (transactionsGrouping != TransactionsGrouping.None) { - GroupedTransactionsListItems(transactionsListModifier, transactionsToDisplay, userAccountsId, transactionsGrouping) + GroupedTransactionsListItems(transactionsListModifier, transactionsToDisplay, usersById, transactionsGrouping) } else { LazyColumn(transactionsListModifier, contentPadding = PaddingValues(top = 8.dp, bottom = 16.dp)) { itemsIndexed(transactionsToDisplay) { index, transaction -> - TransactionListItem(userAccountsId[transaction.userAccountId], transaction, index, transactionsToDisplay.size) + key(transaction.id) { + TransactionListItem(usersById[transaction.userId], transaction, index, transactionsToDisplay.size) + } } } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/TransferMoneyDialog.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/TransferMoneyDialog.kt index 18909fe..8ff9500 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/TransferMoneyDialog.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/TransferMoneyDialog.kt @@ -39,12 +39,12 @@ fun TransferMoneyDialog( data: ShowTransferMoneyDialogData, onDismiss: () -> Unit, ) { - val userAccounts = uiState.userAccounts.value + val userAccounts = uiState.users.value val accountsToUserAccount = userAccounts.sortedBy { it.displayIndex } .flatMap { user -> user.accounts.sortedBy { it.displayIndex }.map { it to user } }.toMap() val accountsSupportingTransferringMoney = userAccounts.flatMap { it.accounts } - .filter { it.supportsAnyFeature(BankAccountFeatures.TransferMoney, BankAccountFeatures.InstantPayment) } + .filter { it.supportsMoneyTransfer } if (accountsSupportingTransferringMoney.isEmpty()) { uiState.applicationErrorOccurred(ErroneousAction.TransferMoney, "Keines Ihrer Konten unterstützt das Überweisen von Geld") @@ -59,7 +59,7 @@ fun TransferMoneyDialog( var recipientAccountIdentifier by remember { mutableStateOf(data.recipientAccountIdentifier ?: "") } var amount by remember { mutableStateOf(data.amount?.amount ?: "") } var paymentReference by remember { mutableStateOf(data.reference ?: "") } - val accountSupportsInstantTransfer by remember(senderAccount) { derivedStateOf { senderAccount.supportsAnyFeature(BankAccountFeatures.InstantPayment) } } + val accountSupportsInstantTransfer by remember(senderAccount) { derivedStateOf { senderAccount.supportsInstantTransfer } } var instantTransfer by remember { mutableStateOf(false) } val isRequiredDataEntered by remember(recipientName, recipientAccountIdentifier, amount) { diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionViewModel.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionViewModel.kt index 1b0111c..d03fe5f 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionViewModel.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionViewModel.kt @@ -7,12 +7,12 @@ import net.codinux.banking.dataaccess.entities.AccountTransactionEntity data class AccountTransactionViewModel( val id: Long, - val userAccountId: Long, + val userId: Long, val bankAccountId: Long, val amount: Amount, val currency: String, - val reference: String, + val reference: String?, val valueDate: LocalDate, val otherPartyName: String? = null, @@ -20,8 +20,8 @@ data class AccountTransactionViewModel( val userSetDisplayName: String? = null, val category: String? = null ) { - constructor(entity: AccountTransactionEntity) : this(entity.id, entity.userAccountId, entity.bankAccountId, entity) + constructor(entity: AccountTransactionEntity) : this(entity.id, entity.userId, entity.bankAccountId, entity) - constructor(id: Long, userAccountId: Long, bankAccountId: Long, transaction: AccountTransaction) - : this(id, userAccountId, bankAccountId, transaction.amount, transaction.currency, transaction.reference, transaction.valueDate, transaction.otherPartyName, transaction.bookingText) + constructor(id: Long, userId: Long, bankAccountId: Long, transaction: AccountTransaction) + : this(id, userId, bankAccountId, transaction.amount, transaction.currency, transaction.reference, transaction.valueDate, transaction.otherPartyName, transaction.postingText) } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionsFilter.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionsFilter.kt index da9cbc7..e29f354 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionsFilter.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/AccountTransactionsFilter.kt @@ -2,7 +2,7 @@ package net.codinux.banking.ui.model import androidx.compose.runtime.* import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity class AccountTransactionsFilter { @@ -19,11 +19,11 @@ class AccountTransactionsFilter { val selectedAccount: BankAccountFilter? get() = selectedAccounts.value.firstOrNull() - fun selectedAccountChanged(userAccount: UserAccountEntity?, bankAccount: BankAccountEntity?) { - selectedAccounts.value = if (userAccount == null) { + fun selectedAccountChanged(user: UserEntity?, bankAccount: BankAccountEntity?) { + selectedAccounts.value = if (user == null) { emptyList() } else { - listOf(BankAccountFilter(userAccount, bankAccount)) + listOf(BankAccountFilter(user, bankAccount)) } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/BankAccountFilter.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/BankAccountFilter.kt index 02fad44..1ecdf57 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/BankAccountFilter.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/BankAccountFilter.kt @@ -1,9 +1,9 @@ package net.codinux.banking.ui.model import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity data class BankAccountFilter( - val userAccount: UserAccountEntity, + val user: UserEntity, val bankAccount: BankAccountEntity? = null ) \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/events/AccountTransactionsRetrievedEvent.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/events/AccountTransactionsRetrievedEvent.kt index 31e3ace..66a0b94 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/events/AccountTransactionsRetrievedEvent.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/events/AccountTransactionsRetrievedEvent.kt @@ -1,11 +1,11 @@ package net.codinux.banking.ui.model.events import net.codinux.banking.client.model.BankAccount -import net.codinux.banking.client.model.UserAccount +import net.codinux.banking.client.model.User import net.codinux.banking.ui.model.AccountTransactionViewModel data class AccountTransactionsRetrievedEvent( - val user: UserAccount, + val user: User, val account: BankAccount, val newTransactions: List ) \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/AccountTransactionsFilterService.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/AccountTransactionsFilterService.kt index 08c614a..ac02b80 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/AccountTransactionsFilterService.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/AccountTransactionsFilterService.kt @@ -1,7 +1,7 @@ package net.codinux.banking.ui.service import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.model.AccountTransactionViewModel import net.codinux.banking.ui.model.AccountTransactionsFilter import net.codinux.banking.ui.model.BankAccountFilter @@ -30,27 +30,27 @@ class AccountTransactionsFilterService { } private fun matchesFilter(transaction: AccountTransactionViewModel, accountsFilter: List): Boolean = - accountsFilter.any { (userAccount, bankAccount) -> + accountsFilter.any { (user, bankAccount) -> if (bankAccount != null) { transaction.bankAccountId == bankAccount.id } else { - transaction.userAccountId == userAccount.id + transaction.userId == user.id } } private fun matchesSearchTerm(transaction: AccountTransactionViewModel, searchTerm: String): Boolean = - transaction.reference.contains(searchTerm, true) + transaction.reference?.contains(searchTerm, true) == true || (transaction.otherPartyName != null && transaction.otherPartyName.contains(searchTerm, true)) - fun isSelected(userAccount: UserAccountEntity, transactionsFilter: AccountTransactionsFilter): Boolean { + fun isSelected(user: UserEntity, transactionsFilter: AccountTransactionsFilter): Boolean { if (transactionsFilter.showAllAccounts) { return false } val filter = transactionsFilter.selectedAccount - return filter?.userAccount == userAccount && filter.bankAccount == null + return filter?.user == user && filter.bankAccount == null } fun isSelected(bankAccount: BankAccountEntity, transactionsFilter: AccountTransactionsFilter): Boolean { diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankDataImporterAndExporter.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankDataImporterAndExporter.kt index ce15568..1737dd5 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankDataImporterAndExporter.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankDataImporterAndExporter.kt @@ -22,7 +22,7 @@ class BankDataImporterAndExporter { formatAmount(transaction.amount, decimalSeparator), transaction.currency, transaction.valueDate.toString(), transaction.bookingDate.toString(), transaction.reference, - transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId + transaction.otherPartyName, transaction.otherPartyBankId, transaction.otherPartyAccountId // TODO: export all columns / transaction data ) } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankIconService.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankIconService.kt index 51548db..5a9ec69 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankIconService.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankIconService.kt @@ -1,11 +1,11 @@ package net.codinux.banking.ui.service import net.codinux.banking.client.model.BankingGroup -import net.codinux.banking.client.model.UserAccount +import net.codinux.banking.client.model.User class BankIconService { // TODO: extract to a common library - fun findIconForBank(user: UserAccount) = findIconForBank(user.bankName, user.bankingGroup) + fun findIconForBank(user: User) = findIconForBank(user.bankName, user.bankingGroup) fun findIconForBank(bankName: String, bankingGroup: BankingGroup? = null): String? = when (bankingGroup) { BankingGroup.Sparkasse -> "https://sparkasse.de/favicon-32x32.png" 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 7eaa7cb..6dd3b5b 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 @@ -15,7 +15,7 @@ import net.codinux.banking.client.service.BankingModelService import net.codinux.banking.dataaccess.BankingRepository import net.codinux.banking.dataaccess.entities.AccountTransactionEntity import net.codinux.banking.dataaccess.entities.BankAccountEntity -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.fints.config.FinTsClientConfiguration import net.codinux.banking.fints.config.FinTsClientOptions import net.codinux.banking.ui.IOorDefault @@ -57,11 +57,11 @@ class BankingService( } - fun getAllUserAccounts() = bankingRepository.getAllUserAccounts() + fun getAllUsers() = bankingRepository.getAllUsers() fun getAllAccountTransactions() = bankingRepository.getAllAccountTransactions() - fun getAllTransactionsOfUserAccount(userAccount: UserAccountEntity) = bankingRepository.getAllTransactionsOfUserAccount(userAccount) + fun getAllTransactionsOfUser(user: UserEntity) = bankingRepository.getAllTransactionsOfUser(user) fun getAllAccountTransactionsAsViewModel() = bankingRepository.getAllAccountTransactionsAsViewModel() @@ -95,15 +95,15 @@ class BankingService( private suspend fun handleSuccessfulGetAccountDataResponse(response: GetAccountDataResponse) { try { val newUser = response.user - newUser.displayIndex = uiState.userAccounts.value.size + newUser.displayIndex = uiState.users.value.size - val newUserEntity = bankingRepository.persistUserAccount(newUser) + val newUserEntity = bankingRepository.persistUser(newUser) log.info { "Saved user account $newUserEntity with ${newUserEntity.accounts.flatMap { it.bookedTransactionsEntities }.size} transactions" } - val userAccounts = uiState.userAccounts.value.toMutableList() - userAccounts.add(newUserEntity) - uiState.userAccounts.value = userAccounts + val users = uiState.users.value.toMutableList() + users.add(newUserEntity) + uiState.users.value = users updateTransactionsInUi(newUserEntity.accounts.flatMap { it.bookedTransactionsEntities }) } catch (e: Throwable) { @@ -115,15 +115,15 @@ class BankingService( suspend fun updateAccountTransactions() { val selectedAccount = uiState.transactionsFilter.value.selectedAccount if (selectedAccount != null) { - updateAccountTransactions(selectedAccount.userAccount, selectedAccount.bankAccount) + updateAccountTransactions(selectedAccount.user, selectedAccount.bankAccount) } else { - uiState.userAccounts.value.forEach { user -> + uiState.users.value.forEach { user -> updateAccountTransactions(user) } } } - private suspend fun updateAccountTransactions(user: UserAccountEntity, bankAccount: BankAccountEntity? = null) { + private suspend fun updateAccountTransactions(user: UserEntity, bankAccount: BankAccountEntity? = null) { withContext(Dispatchers.IOorDefault) { try { val response = client.updateAccountTransactionsAsync(user, bankAccount?.let { listOf(it) }) @@ -138,22 +138,22 @@ class BankingService( } } - private suspend fun handleSuccessfulUpdateAccountTransactionsResponse(user: UserAccountEntity, responses: List) { + private suspend fun handleSuccessfulUpdateAccountTransactionsResponse(user: UserEntity, responses: List) { try { // TODO: when user gets updated by BankingClient, also update user in database // val newUser = response.user -// val newUserEntity = bankingRepository.persistUserAccount(newUser) +// val newUserEntity = bankingRepository.persistUser(newUser) // // log.info { "Saved user account $newUserEntity with ${newUserEntity.accounts.flatMap { it.bookedTransactionsEntities }.size} transactions" } - val userAccountTransactions = getAllTransactionsOfUserAccount(user) + val userTransactions = getAllTransactionsOfUser(user) responses.forEach { response -> val account = (response.account as? BankAccountEntity) ?: user.accounts.first { it.identifier == response.account.identifier && it.subAccountNumber == response.account.subAccountNumber } // TODO: update BankAccount and may updated Transactions in database - val existingAccountTransactions = userAccountTransactions.filter { it.bankAccountId == account.id } + val existingAccountTransactions = userTransactions.filter { it.bankAccountId == account.id } val newTransactions = modelService.findNewTransactions(response.bookedTransactions, existingAccountTransactions) @@ -182,7 +182,7 @@ class BankingService( } - suspend fun transferMoney(user: UserAccountEntity, account: BankAccountEntity, + suspend fun transferMoney(user: UserEntity, account: BankAccountEntity, recipientName: String, recipientAccountIdentifier: String, amount: Amount, currency: String, paymentReference: String? = null, instantTransfer: Boolean = false, recipientBankIdentifier: String? = null): Boolean { val response = client.transferMoneyAsync(TransferMoneyRequestForUser( diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/CalculatorService.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/CalculatorService.kt index 4183f38..f9a3522 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/CalculatorService.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/CalculatorService.kt @@ -1,8 +1,8 @@ package net.codinux.banking.ui.service import net.codinux.banking.client.model.Amount -import net.codinux.banking.client.model.UserAccount -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.client.model.User +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.extensions.toBigDecimal import net.codinux.banking.ui.model.AccountTransactionViewModel import net.codinux.banking.ui.model.AccountTransactionsFilter @@ -13,8 +13,8 @@ class CalculatorService { // TODO: find a better solution Amount(transactions.sumOf { it.amount.toBigDecimal() }.toString()) - fun calculateBalanceOfUserAccount(userAccount: UserAccount): Amount = - sumAmounts(userAccount.accounts.map { it.balance }) + fun calculateBalanceOfUser(user: User): Amount = + sumAmounts(user.accounts.map { it.balance }) fun sumAmounts(amounts: Collection): Amount = // TODO: find a better solution @@ -28,9 +28,9 @@ class CalculatorService { // TODO: find a better solution Amount(transactions.map { it.amount.toBigDecimal() }.filter { it < 0 }.sum().toString()) - fun calculateBalanceOfDisplayedTransactions(transactions: Collection, userAccounts: Collection, filter: AccountTransactionsFilter): Amount { + fun calculateBalanceOfDisplayedTransactions(transactions: Collection, users: Collection, filter: AccountTransactionsFilter): Amount { if (filter.noFiltersApplied) { - return sumAmounts(userAccounts.flatMap { it.accounts.map { it.balance } }) + return sumAmounts(users.flatMap { it.accounts.map { it.balance } }) } val selectedAccount = filter.selectedAccount @@ -39,7 +39,7 @@ class CalculatorService { if (selectedAccount.bankAccount != null) { selectedAccount.bankAccount.balance } else { - calculateBalanceOfUserAccount(selectedAccount.userAccount) + calculateBalanceOfUser(selectedAccount.user) } } else { sumTransactions(transactions) diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/RecipientFinder.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/RecipientFinder.kt index cdc606d..e156830 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/RecipientFinder.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/RecipientFinder.kt @@ -33,7 +33,7 @@ class RecipientFinder(private val bankFinder: BankFinder) { suspend fun updateData(transactions: List) { availableRecipients = transactions.mapNotNull { if (it.otherPartyName != null && it.otherPartyAccountId != null) { - RecipientSuggestion(it.otherPartyName!!, it.otherPartyBankCode, it.otherPartyAccountId!!) + RecipientSuggestion(it.otherPartyName!!, it.otherPartyBankId, it.otherPartyAccountId!!) } else { null } @@ -45,7 +45,7 @@ class RecipientFinder(private val bankFinder: BankFinder) { transactionsByIban = transactions.filter { it.otherPartyAccountId != null }.groupBy { it.otherPartyAccountId!! } .mapValues { it.value.map { - PaymentDataSuggestion(it.reference, Amount(it.amount.amount.replace("-", "")), it.currency, it.valueDate) + PaymentDataSuggestion(it.reference ?: "", Amount(it.amount.amount.replace("-", "")), it.currency, it.valueDate) }.toSet().sortedByDescending { it.valueDate } } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt index bfef8b5..ec1e93d 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt @@ -5,7 +5,7 @@ import androidx.compose.material.DrawerValue import androidx.lifecycle.ViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow -import net.codinux.banking.dataaccess.entities.UserAccountEntity +import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.ui.model.* import net.codinux.banking.ui.model.error.ApplicationError import net.codinux.banking.ui.model.error.BankingClientError @@ -15,7 +15,7 @@ import net.codinux.banking.ui.model.events.TransferredMoneyEvent class UiState : ViewModel() { - val userAccounts = MutableStateFlow>(emptyList()) + val users = MutableStateFlow>(emptyList()) val transactions = MutableStateFlow>(emptyList()) diff --git a/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/AccountTransaction.sq b/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/AccountTransaction.sq index be7881a..164af60 100644 --- a/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/AccountTransaction.sq +++ b/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/AccountTransaction.sq @@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS AccountTransaction ( amount TEXT NOT NULL, currency TEXT NOT NULL, - unparsedReference TEXT NOT NULL, + unparsedReference TEXT, bookingDate TEXT NOT NULL, valueDate TEXT NOT NULL, @@ -21,8 +21,6 @@ CREATE TABLE IF NOT EXISTS AccountTransaction ( category TEXT, notes TEXT, - information TEXT, - statementNumber INTEGER, sequenceNumber INTEGER, @@ -34,17 +32,16 @@ CREATE TABLE IF NOT EXISTS AccountTransaction ( mandateReference TEXT, creditorIdentifier TEXT, originatorsIdentificationCode TEXT, + compensationAmount TEXT, originalAmount TEXT, - sepaReference TEXT, deviantOriginator TEXT, deviantRecipient TEXT, referenceWithNoSpecialType TEXT, + primaNotaNumber TEXT, textKeySupplement TEXT, - currencyType TEXT, - bookingKey TEXT, referenceForTheAccountOwner TEXT, referenceOfTheAccountServicingInstitution TEXT, supplementaryDetails TEXT, @@ -65,22 +62,16 @@ INSERT INTO AccountTransaction( userSetDisplayName, category, notes, - information, statementNumber, sequenceNumber, openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, creditorIdentifier, originatorsIdentificationCode, compensationAmount, originalAmount, - sepaReference, deviantOriginator, deviantRecipient, referenceWithNoSpecialType, primaNotaNumber, textKeySupplement, - currencyType, bookingKey, - referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution, - supplementaryDetails, - transactionReferenceNumber, relatedReferenceNumber ) VALUES( @@ -93,22 +84,16 @@ VALUES( ?, ?, ?, - ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, - ?, ?, ?, ?, ?, ?, - ?, ?, - ?, ?, - ?, - ?, ? ); @@ -118,11 +103,11 @@ SELECT AccountTransaction.* FROM AccountTransaction; selectAllTransactionsAsViewModel: -SELECT id, userAccountId, bankAccountId, amount, currency, unparsedReference, valueDate, otherPartyName, bookingText, sepaReference, userSetDisplayName, category +SELECT id, userAccountId, bankAccountId, amount, currency, unparsedReference, valueDate, otherPartyName, bookingText, userSetDisplayName, category FROM AccountTransaction; -selectAllTransactionsOfUserAccount: +selectAllTransactionsOfUser: SELECT AccountTransaction.* FROM AccountTransaction WHERE userAccountId = ?; diff --git a/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/UserAccount.sq b/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/UserAccount.sq index af5daf1..d49e97a 100644 --- a/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/UserAccount.sq +++ b/composeApp/src/commonMain/sqldelight/net/codinux/banking/ui/UserAccount.sq @@ -11,7 +11,7 @@ CREATE TABLE IF NOT EXISTS UserAccount ( bic TEXT NOT NULL, customerName TEXT NOT NULL, - userId TEXT NOT NULL, + userId TEXT, selectedTanMethodId TEXT, @@ -27,7 +27,7 @@ CREATE TABLE IF NOT EXISTS UserAccount ( ); -insertUserAccount: +insertUser: INSERT INTO UserAccount( bankCode, loginName, password, @@ -58,7 +58,7 @@ VALUES( ); -selectAllUserAccounts: +selectAllUsers: SELECT UserAccount.* FROM UserAccount; diff --git a/composeApp/src/desktopMain/kotlin/net/codinux/banking/ui/dialogs/EnterTanDialogPreview.kt b/composeApp/src/desktopMain/kotlin/net/codinux/banking/ui/dialogs/EnterTanDialogPreview.kt index cfdb579..e51d730 100644 --- a/composeApp/src/desktopMain/kotlin/net/codinux/banking/ui/dialogs/EnterTanDialogPreview.kt +++ b/composeApp/src/desktopMain/kotlin/net/codinux/banking/ui/dialogs/EnterTanDialogPreview.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.Composable import net.codinux.banking.client.model.BankAccountType import net.codinux.banking.client.model.BankAccountViewInfo import net.codinux.banking.client.model.BankingGroup -import net.codinux.banking.client.model.UserAccountViewInfo +import net.codinux.banking.client.model.BankViewInfo import net.codinux.banking.client.model.tan.* import net.codinux.banking.ui.model.TanChallengeReceived @@ -13,7 +13,7 @@ import net.codinux.banking.ui.model.TanChallengeReceived @Composable fun EnterTanDialogPreview_EnterTan() { val tanMethods = listOf(TanMethod("Zeig mich an", TanMethodType.AppTan, "902")) - val user = UserAccountViewInfo("12345678", "SupiDupiNutzer", "Abzockbank", BankingGroup.Postbank) + val user = BankViewInfo("12345678", "SupiDupiNutzer", "Abzockbank", BankingGroup.Postbank) val tanChallenge = TanChallenge(TanChallengeType.EnterTan, ActionRequiringTan.GetAccountInfo, "Geben Sie die TAN ein", tanMethods.first().identifier, tanMethods, user = user) EnterTanDialog(TanChallengeReceived(tanChallenge) { }) { } @@ -27,7 +27,7 @@ fun EnterTanDialogPreview_TanImage() { val tanMethod = TanMethod("photoTAN-Verfahren", TanMethodType.photoTan, "902", 6, AllowedTanFormat.Numeric) val tanImage = TanImage("image/png", tanImageBytes) - val user = UserAccountViewInfo("10010010", "Ihr krasser Login Name", "Phantasie Bank", BankingGroup.Comdirect) + val user = BankViewInfo("10010010", "Ihr krasser Login Name", "Phantasie Bank", BankingGroup.Comdirect) val tanChallenge = TanChallenge(TanChallengeType.Image, ActionRequiringTan.GetAccountInfo, "Geben Sie die TAN ein", tanMethod.identifier, listOf(tanMethod), null, emptyList(), tanImage, null, user) @@ -50,7 +50,7 @@ fun EnterTanDialogPreview_WithMultipleTanMedia() { // shows that dialog is reall TanMedium(TanMediumType.TanGenerator, "SparkassenCard (Debitkarte)", TanMediumStatus.Used, TanGeneratorTanMedium("5432109876")) ) - val user = UserAccountViewInfo("10010010", "Ihr krasser Login Name", "Eine ganz gewöhnliche Sparkasse", BankingGroup.Sparkasse) + val user = BankViewInfo("10010010", "Ihr krasser Login Name", "Eine ganz gewöhnliche Sparkasse", BankingGroup.Sparkasse) val account = BankAccountViewInfo("12345678", null, BankAccountType.CheckingAccount, null, "Giro Konto") val tanChallenge = TanChallenge(TanChallengeType.Image, ActionRequiringTan.GetTransactions, "Sie möchten eine \"Umsatzabfrage\" freigeben: Bitte bestätigen Sie den \"Startcode 80061030\" mit der Taste \"OK\".", "913", tanMethods, "SparkassenCard (Debitkarte)", tanMedia, tanImage, null, user, account) diff --git a/composeApp/src/desktopTest/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepositoryTest.kt b/composeApp/src/desktopTest/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepositoryTest.kt index bea20ea..50eacea 100644 --- a/composeApp/src/desktopTest/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepositoryTest.kt +++ b/composeApp/src/desktopTest/kotlin/net/codinux/banking/dataaccess/SqliteBankingRepositoryTest.kt @@ -25,14 +25,14 @@ class SqliteBankingRepositoryTest { @Test fun saveUserAccount() = runTest { val bankAccounts = listOf( - BankAccount("12345", "Monika Tester", BankAccountType.CheckingAccount, balance = Amount("12.34"), retrievedTransactionsFrom = LocalDate(2024, 5, 7), features = setOf(BankAccountFeatures.RetrieveBalance, BankAccountFeatures.InstantPayment), countDaysForWhichTransactionsAreKept = 320) + BankAccount("12345", null, null, null, "Monika Tester", BankAccountType.CheckingAccount, balance = Amount("12.34"), retrievedTransactionsFrom = LocalDate(2024, 5, 7), features = setOf(BankAccountFeatures.RetrieveBalance, BankAccountFeatures.InstantTransfer), serverTransactionsRetentionDays = 320) ) - val userAccount = UserAccount("12345678", "SupiDupiUser", "geheim", "Abzock-Bank", "ABCDDEBBXXX", "Monika Tester", accounts = bankAccounts, bankingGroup = BankingGroup.DKB).apply { + val userAccount = User("12345678", "SupiDupiUser", "geheim", "Abzock-Bank", "ABCDDEBBXXX", "Monika Tester", accounts = bankAccounts, bankingGroup = BankingGroup.DKB, finTsServerAddress = "").apply { wrongCredentialsEntered = true displayIndex = 99 } - val persisted = underTest.persistUserAccount(userAccount) + val persisted = underTest.persistUser(userAccount) assertNotNull(persisted.id) @@ -55,7 +55,7 @@ class SqliteBankingRepositoryTest { val persistedBankAccount = persisted.accounts.first() assertNotNull(persistedBankAccount.id) - assertEquals(persisted.id, persistedBankAccount.userAccountId) + assertEquals(persisted.id, persistedBankAccount.userId) assertEquals(bankAccounts.first().identifier, persistedBankAccount.identifier) assertEquals(bankAccounts.first().accountHolderName, persistedBankAccount.accountHolderName) @@ -67,7 +67,7 @@ class SqliteBankingRepositoryTest { assertEquals(bankAccounts.first().features, persistedBankAccount.features) - assertEquals(bankAccounts.first().countDaysForWhichTransactionsAreKept, persistedBankAccount.countDaysForWhichTransactionsAreKept) + assertEquals(bankAccounts.first().serverTransactionsRetentionDays, persistedBankAccount.serverTransactionsRetentionDays) assertEquals(bankAccounts.first().hideAccount, persistedBankAccount.hideAccount) assertEquals(bankAccounts.first().includeInAutomaticAccountsUpdate, persistedBankAccount.includeInAutomaticAccountsUpdate) } @@ -88,7 +88,7 @@ class SqliteBankingRepositoryTest { assertEquals(transaction.amount, persisted.amount) assertEquals(transaction.currency, persisted.currency) - assertEquals(transaction.unparsedReference, persisted.unparsedReference) + assertEquals(transaction.reference, persisted.reference) assertEquals(transaction.bookingDate, persisted.bookingDate) assertEquals(transaction.valueDate, persisted.valueDate) assertEquals(transaction.otherPartyName, persisted.otherPartyName) @@ -109,7 +109,7 @@ class SqliteBankingRepositoryTest { assertEquals(transaction.amount, persisted.amount) assertEquals(transaction.currency, persisted.currency) - assertEquals(transaction.unparsedReference, persisted.reference) + assertEquals(transaction.reference, persisted.reference) assertEquals(transaction.valueDate, persisted.valueDate) assertEquals(transaction.otherPartyName, persisted.otherPartyName) }